mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-14 23:00:44 +02:00
FEXCore/JIT: Encode the JITRIPReconstructionEntries using variable length integer
When #2722 implemented this initially and #4271 switched over to signed int16_t there was assumptions made that int16_t was a reasonable trade-off in encoding size versus needing to deal with 8-bit values being too small in some cases. In the common case we are almost always encoding 8-bit values because instructions are typically linear (and less than 15-bytes in size), but 16-bit was chosen because optimizing JIT and multiple instructions that don't cause exceptions can add up to larger than 8-bit. Instead of hardcoding 16-bit values, implement a variable length integer class where ~96.8% of values are 8-bit encoded, and the remaining 3.19% are encoded using 16-bit. Due to some constraints that #4271 put in place, we can basically guarantee currently that branch targets are within 16-bit. The VL class does support 32-bit and 64-bit as well so if we change behaviour then nothing needs to change. Some stats when running Sonic Mania with multiblock enabled. Encoded integers: 3,504,907 Encoded 8-bit: 3,393,095 (96.8%) Encoded 16-bit: 111,812 (3.19%) Encoded 32/64-bit: 0 Encoded Size: 3,615,181 bytes (3.44MiB) Fixed encoded size: 7,007,604 bytes (6.68MiB) Definitely worth using and saves the headache of large RIP/PC offsets causing problems.
This commit is contained in:
5 files changed
+314
-35
No files matched your search
@@ -0,0 +1,114 @@
|
||||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <catch2/generators/catch_generators_range.hpp>
|
||||
#include <catch2/generators/catch_generators_random.hpp>
|
||||
|
||||
#include "Utils/variable_length_integer.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
TEST_CASE("vl-size") {
|
||||
// Check 8-bit minimum and maximum.
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(-64) == 1);
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(63) == 1);
|
||||
|
||||
// Check 16-bit minimum and maximum.
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(-8192) == 2);
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(8191) == 2);
|
||||
|
||||
// Check 32-bit minimum and maximum.
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(std::numeric_limits<int32_t>::min()) == 5);
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(std::numeric_limits<int32_t>::max()) == 5);
|
||||
|
||||
// Check 64-bit minimum and maximum.
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(std::numeric_limits<int64_t>::min()) == 9);
|
||||
CHECK(FEXCore::Utils::vl64::EncodedSize(std::numeric_limits<int64_t>::max()) == 9);
|
||||
}
|
||||
|
||||
TEST_CASE("vl8 - in memory - encode") {
|
||||
uint8_t data[1];
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, 0) == 1);
|
||||
CHECK(data[0] == 0);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, 63) == 1);
|
||||
CHECK(data[0] == 0b0011'1111);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, -1) == 1);
|
||||
CHECK(data[0] == 0b0111'1111);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, -64) == 1);
|
||||
CHECK(data[0] == 0b0100'0000);
|
||||
}
|
||||
|
||||
TEST_CASE("vl16 - in memory - encode") {
|
||||
uint8_t data[2];
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, -65) == 2);
|
||||
CHECK(data[0] == 0b1011'1111);
|
||||
CHECK(data[1] == 0b1011'1111);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, -66) == 2);
|
||||
CHECK(data[0] == 0b1011'1110);
|
||||
CHECK(data[1] == 0b1011'1111);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, 64) == 2);
|
||||
CHECK(data[0] == 0b0100'0000);
|
||||
CHECK(data[1] == 0b1000'0000);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, 8191) == 2);
|
||||
CHECK(data[0] == 0b1111'1111);
|
||||
CHECK(data[1] == 0b1001'1111);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, -8192) == 2);
|
||||
CHECK(data[0] == 0b0000'0000);
|
||||
CHECK(data[1] == 0b1010'0000);
|
||||
}
|
||||
|
||||
TEST_CASE("vl32 - in memory - encode") {
|
||||
uint8_t data[5];
|
||||
int32_t result {};
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, 8192) == 5);
|
||||
CHECK(data[0] == 0b1100'0000);
|
||||
memcpy(&result, &data[1], sizeof(int32_t));
|
||||
CHECK(result == 8192);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, -8193) == 5);
|
||||
CHECK(data[0] == 0b1100'0000);
|
||||
memcpy(&result, &data[1], sizeof(int32_t));
|
||||
CHECK(result == -8193);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, std::numeric_limits<int32_t>::min()) == 5);
|
||||
CHECK(data[0] == 0b1100'0000);
|
||||
memcpy(&result, &data[1], sizeof(int32_t));
|
||||
CHECK(result == std::numeric_limits<int32_t>::min());
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, std::numeric_limits<int32_t>::max()) == 5);
|
||||
CHECK(data[0] == 0b1100'0000);
|
||||
memcpy(&result, &data[1], sizeof(int32_t));
|
||||
CHECK(result == std::numeric_limits<int32_t>::max());
|
||||
}
|
||||
|
||||
TEST_CASE("vl64 - in memory - encode") {
|
||||
uint8_t data[9];
|
||||
int64_t result {};
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1) == 9);
|
||||
CHECK(data[0] == 0b1110'0000);
|
||||
memcpy(&result, &data[1], sizeof(int64_t));
|
||||
CHECK(result == static_cast<int64_t>(std::numeric_limits<int32_t>::min()) - 1);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 1) == 9);
|
||||
CHECK(data[0] == 0b1110'0000);
|
||||
memcpy(&result, &data[1], sizeof(int64_t));
|
||||
CHECK(result == static_cast<int64_t>(std::numeric_limits<int32_t>::max()) + 1);
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, std::numeric_limits<int64_t>::min()) == 9);
|
||||
CHECK(data[0] == 0b1110'0000);
|
||||
memcpy(&result, &data[1], sizeof(int64_t));
|
||||
CHECK(result == std::numeric_limits<int64_t>::min());
|
||||
|
||||
REQUIRE(FEXCore::Utils::vl64::Encode(data, std::numeric_limits<int64_t>::max()) == 9);
|
||||
CHECK(data[0] == 0b1110'0000);
|
||||
memcpy(&result, &data[1], sizeof(int64_t));
|
||||
CHECK(result == std::numeric_limits<int64_t>::max());
|
||||
}
|
||||
Reference in new issue
Block a user