Merge pull request #2494 from Sonicadvance1/sra_on_32bit

Arm64: Reclaim SRA registers on 32-bit
This commit is contained in:
Ryan Houdek authored and GitHub committed 2023-03-14 07:30:00 -07:00
commit 3a81efdb28
11 files changed
+132 -61

No files matched your search

@@ -25,6 +25,26 @@ Arm64Emitter::Arm64Emitter(FEXCore::Context::ContextImpl *ctx, size_t size)
: Emitter(size ? (uint8_t*)FEXCore::Allocator::mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) : nullptr, size)
, EmitterCTX {ctx} {
CPU.SetUp();
// Number of register available is dependent on what operating mode the proccess is in.
if (EmitterCTX->Config.Is64BitMode()) {
ConfiguredGPRs = NumGPRs64;
ConfiguredSRAGPRs = NumSRAGPRs64;
ConfiguredGPRPairs = NumGPRPairs64;
ConfiguredFPRs = NumFPRs64;
ConfiguredSRAFPRs = NumSRAFPRs64;
ConfiguredDynamicGPRs = NumGPRs64 - NumGPRs64; // Will be zero, just to be consistent with 32-bit side
ConfiguredDynamicRegisterBase = nullptr;
}
else {
ConfiguredGPRs = NumGPRs32;
ConfiguredSRAGPRs = NumSRAGPRs32;
ConfiguredGPRPairs = NumGPRPairs32;
ConfiguredFPRs = NumFPRs32;
ConfiguredSRAFPRs = NumSRAFPRs32;
ConfiguredDynamicGPRs = NumGPRs32 - NumGPRs64; // Will be 8
ConfiguredDynamicRegisterBase = &RA64[9];
}
}
Arm64Emitter::~Arm64Emitter() {
@@ -195,7 +215,7 @@ void Arm64Emitter::SpillStaticRegs(bool FPRs, uint32_t GPRSpillMask, uint32_t FP
return;
}
for (size_t i = 0; i < SRA64.size(); i+=2) {
for (size_t i = 0; i < ConfiguredSRAGPRs; i+=2) {
auto Reg1 = SRA64[i];
auto Reg2 = SRA64[i+1];
if (((1U << Reg1.Idx()) & GPRSpillMask) &&
@@ -212,7 +232,7 @@ void Arm64Emitter::SpillStaticRegs(bool FPRs, uint32_t GPRSpillMask, uint32_t FP
if (FPRs) {
if (EmitterCTX->HostFeatures.SupportsAVX) {
for (size_t i = 0; i < SRAFPR.size(); i++) {
for (size_t i = 0; i < ConfiguredSRAFPRs; i++) {
const auto Reg = SRAFPR[i];
if (((1U << Reg.Idx()) & FPRSpillMask) != 0) {
@@ -227,7 +247,7 @@ void Arm64Emitter::SpillStaticRegs(bool FPRs, uint32_t GPRSpillMask, uint32_t FP
// Load the sse offset in to the temporary register
add(ARMEmitter::Size::i64Bit, TmpReg, STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.xmm.sse.data[0][0]));
for (size_t i = 0; i < SRAFPR.size(); i += 4) {
for (size_t i = 0; i < ConfiguredSRAFPRs; i += 4) {
const auto Reg1 = SRAFPR[i];
const auto Reg2 = SRAFPR[i + 1];
const auto Reg3 = SRAFPR[i + 2];
@@ -236,7 +256,7 @@ void Arm64Emitter::SpillStaticRegs(bool FPRs, uint32_t GPRSpillMask, uint32_t FP
}
}
else {
for (size_t i = 0; i < SRAFPR.size(); i += 2) {
for (size_t i = 0; i < ConfiguredSRAFPRs; i += 2) {
const auto Reg1 = SRAFPR[i];
const auto Reg2 = SRAFPR[i + 1];
@@ -270,7 +290,7 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
ptrue<ARMEmitter::SubRegSize::i8Bit>(PRED_TMP_16B, ARMEmitter::PredicatePattern::SVE_VL16);
ptrue<ARMEmitter::SubRegSize::i8Bit>(PRED_TMP_32B, ARMEmitter::PredicatePattern::SVE_VL32);
for (size_t i = 0; i < SRAFPR.size(); i++) {
for (size_t i = 0; i < ConfiguredSRAFPRs; i++) {
const auto Reg = SRAFPR[i];
if (((1U << Reg.Idx()) & FPRFillMask) != 0) {
mov(ARMEmitter::Size::i64Bit, TMP4.R(), offsetof(Core::CpuStateFrame, State.xmm.avx.data[i][0]));
@@ -285,7 +305,7 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
// Load the sse offset in to the temporary register
add(ARMEmitter::Size::i64Bit, TmpReg, STATE.R(), offsetof(FEXCore::Core::CpuStateFrame, State.xmm.sse.data[0][0]));
for (size_t i = 0; i < SRAFPR.size(); i += 4) {
for (size_t i = 0; i < ConfiguredSRAFPRs; i += 4) {
const auto Reg1 = SRAFPR[i];
const auto Reg2 = SRAFPR[i + 1];
const auto Reg3 = SRAFPR[i + 2];
@@ -294,7 +314,7 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
}
}
else {
for (size_t i = 0; i < SRAFPR.size(); i += 2) {
for (size_t i = 0; i < ConfiguredSRAFPRs; i += 2) {
const auto Reg1 = SRAFPR[i];
const auto Reg2 = SRAFPR[i + 1];
@@ -313,7 +333,7 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
}
}
for (size_t i = 0; i < SRA64.size(); i+=2) {
for (size_t i = 0; i < ConfiguredSRAGPRs; i+=2) {
auto Reg1 = SRA64[i];
auto Reg2 = SRA64[i+1];
if (((1U << Reg1.Idx()) & GPRFillMask) &&
@@ -331,10 +351,10 @@ void Arm64Emitter::FillStaticRegs(bool FPRs, uint32_t GPRFillMask, uint32_t FPRF
void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
const auto CanUseSVE = EmitterCTX->HostFeatures.SupportsAVX;
const auto GPRSize = 1 * Core::CPUState::GPR_REG_SIZE;
const auto GPRSize = (ConfiguredDynamicGPRs + 1) * Core::CPUState::GPR_REG_SIZE;
const auto FPRRegSize = CanUseSVE ? Core::CPUState::XMM_AVX_REG_SIZE
: Core::CPUState::XMM_SSE_REG_SIZE;
const auto FPRSize = RAFPR.size() * FPRRegSize;
const auto FPRSize = ConfiguredFPRs * FPRRegSize;
const uint64_t SPOffset = AlignUp(GPRSize + FPRSize, 16);
sub(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, SPOffset);
@@ -343,7 +363,7 @@ void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
add(ARMEmitter::Size::i64Bit, TmpReg, ARMEmitter::Reg::rsp, 0);
if (CanUseSVE) {
for (size_t i = 0; i < RAFPR.size(); i += 4) {
for (size_t i = 0; i < ConfiguredFPRs; i += 4) {
const auto Reg1 = RAFPR[i];
const auto Reg2 = RAFPR[i + 1];
const auto Reg3 = RAFPR[i + 2];
@@ -352,8 +372,8 @@ void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
add(ARMEmitter::Size::i64Bit, TmpReg, TmpReg, 32 * 4);
}
} else {
static_assert(RAFPR.size() % 4 == 0, "Needs to have multiple of 4 FPRs for RA");
for (size_t i = 0; i < RAFPR.size(); i += 4) {
LOGMAN_THROW_AA_FMT(ConfiguredFPRs % 4 == 0, "Needs to have multiple of 4 FPRs for RA");
for (size_t i = 0; i < ConfiguredFPRs; i += 4) {
const auto Reg1 = RAFPR[i];
const auto Reg2 = RAFPR[i + 1];
const auto Reg3 = RAFPR[i + 2];
@@ -362,6 +382,14 @@ void Arm64Emitter::PushDynamicRegsAndLR(FEXCore::ARMEmitter::Register TmpReg) {
}
}
if (ConfiguredDynamicRegisterBase) {
for (size_t i = 0; i < ConfiguredDynamicGPRs; i += 2) {
const auto Reg1 = ConfiguredDynamicRegisterBase[i];
const auto Reg2 = ConfiguredDynamicRegisterBase[i + 1];
stp<ARMEmitter::IndexType::POST>(Reg1.X(), Reg2.X(), TmpReg, 16);
}
}
str(ARMEmitter::XReg::lr, TmpReg, 0);
}
@@ -369,7 +397,7 @@ void Arm64Emitter::PopDynamicRegsAndLR() {
const auto CanUseSVE = EmitterCTX->HostFeatures.SupportsAVX;
if (CanUseSVE) {
for (size_t i = 0; i < RAFPR.size(); i += 4) {
for (size_t i = 0; i < ConfiguredFPRs; i += 4) {
const auto Reg1 = RAFPR[i];
const auto Reg2 = RAFPR[i + 1];
const auto Reg3 = RAFPR[i + 2];
@@ -378,7 +406,7 @@ void Arm64Emitter::PopDynamicRegsAndLR() {
add(ARMEmitter::Size::i64Bit, ARMEmitter::Reg::rsp, ARMEmitter::Reg::rsp, 32 * 4);
}
} else {
for (size_t i = 0; i < RAFPR.size(); i += 4) {
for (size_t i = 0; i < ConfiguredFPRs; i += 4) {
const auto Reg1 = RAFPR[i];
const auto Reg2 = RAFPR[i + 1];
const auto Reg3 = RAFPR[i + 2];
@@ -387,6 +415,14 @@ void Arm64Emitter::PopDynamicRegsAndLR() {
}
}
if (ConfiguredDynamicRegisterBase) {
for (size_t i = 0; i < ConfiguredDynamicGPRs; i += 2) {
const auto Reg1 = ConfiguredDynamicRegisterBase[i];
const auto Reg2 = ConfiguredDynamicRegisterBase[i + 1];
ldp<ARMEmitter::IndexType::POST>(Reg1.X(), Reg2.X(), ARMEmitter::Reg::rsp, 16);
}
}
ldr<ARMEmitter::IndexType::POST>(ARMEmitter::XReg::lr, ARMEmitter::Reg::rsp, 16);
}
@@ -31,32 +31,47 @@ namespace FEXCore::CPU {
// All but x29 are caller saved
constexpr std::array<FEXCore::ARMEmitter::Register, 16> SRA64 = {
FEXCore::ARMEmitter::Reg::r4, FEXCore::ARMEmitter::Reg::r5, FEXCore::ARMEmitter::Reg::r6, FEXCore::ARMEmitter::Reg::r7, FEXCore::ARMEmitter::Reg::r8, FEXCore::ARMEmitter::Reg::r9, FEXCore::ARMEmitter::Reg::r10, FEXCore::ARMEmitter::Reg::r11,
FEXCore::ARMEmitter::Reg::r12, FEXCore::ARMEmitter::Reg::r18, FEXCore::ARMEmitter::Reg::r17, FEXCore::ARMEmitter::Reg::r16, FEXCore::ARMEmitter::Reg::r15, FEXCore::ARMEmitter::Reg::r14, FEXCore::ARMEmitter::Reg::r13, FEXCore::ARMEmitter::Reg::r29
// Registers that don't exist on 32-bit
FEXCore::ARMEmitter::Reg::r12, FEXCore::ARMEmitter::Reg::r13, FEXCore::ARMEmitter::Reg::r14, FEXCore::ARMEmitter::Reg::r15, FEXCore::ARMEmitter::Reg::r16, FEXCore::ARMEmitter::Reg::r17, FEXCore::ARMEmitter::Reg::r18, FEXCore::ARMEmitter::Reg::r29
};
// All are callee saved
constexpr std::array<FEXCore::ARMEmitter::Register, 9> RA64 = {
// All are callee saved (except additional registers from 32-bit)
constexpr std::array<FEXCore::ARMEmitter::Register, 9 + 8> RA64 = {
FEXCore::ARMEmitter::Reg::r20, FEXCore::ARMEmitter::Reg::r21, FEXCore::ARMEmitter::Reg::r22, FEXCore::ARMEmitter::Reg::r23, FEXCore::ARMEmitter::Reg::r24, FEXCore::ARMEmitter::Reg::r25, FEXCore::ARMEmitter::Reg::r26, FEXCore::ARMEmitter::Reg::r27,
FEXCore::ARMEmitter::Reg::r19
FEXCore::ARMEmitter::Reg::r19,
// Registers only available on 32-bit
// All these are caller saved.
FEXCore::ARMEmitter::Reg::r12, FEXCore::ARMEmitter::Reg::r13, FEXCore::ARMEmitter::Reg::r14, FEXCore::ARMEmitter::Reg::r15, FEXCore::ARMEmitter::Reg::r16, FEXCore::ARMEmitter::Reg::r17, FEXCore::ARMEmitter::Reg::r18, FEXCore::ARMEmitter::Reg::r29
};
constexpr std::array<std::pair<FEXCore::ARMEmitter::Register, FEXCore::ARMEmitter::Register>, 4> RA64Pair = {{
constexpr std::array<std::pair<FEXCore::ARMEmitter::Register, FEXCore::ARMEmitter::Register>, 4 + 3> RA64Pair = {{
{FEXCore::ARMEmitter::Reg::r20, FEXCore::ARMEmitter::Reg::r21},
{FEXCore::ARMEmitter::Reg::r22, FEXCore::ARMEmitter::Reg::r23},
{FEXCore::ARMEmitter::Reg::r24, FEXCore::ARMEmitter::Reg::r25},
{FEXCore::ARMEmitter::Reg::r26, FEXCore::ARMEmitter::Reg::r27},
// Registers only available on 32-bit
{FEXCore::ARMEmitter::Reg::r12, FEXCore::ARMEmitter::Reg::r13},
{FEXCore::ARMEmitter::Reg::r14, FEXCore::ARMEmitter::Reg::r15},
{FEXCore::ARMEmitter::Reg::r16, FEXCore::ARMEmitter::Reg::r17}
}};
// All are caller saved
constexpr std::array<FEXCore::ARMEmitter::VRegister, 16> SRAFPR = {
FEXCore::ARMEmitter::VReg::v16, FEXCore::ARMEmitter::VReg::v17, FEXCore::ARMEmitter::VReg::v18, FEXCore::ARMEmitter::VReg::v19, FEXCore::ARMEmitter::VReg::v20, FEXCore::ARMEmitter::VReg::v21, FEXCore::ARMEmitter::VReg::v22, FEXCore::ARMEmitter::VReg::v23,
// Registers that don't exist on 32-bit
FEXCore::ARMEmitter::VReg::v24, FEXCore::ARMEmitter::VReg::v25, FEXCore::ARMEmitter::VReg::v26, FEXCore::ARMEmitter::VReg::v27, FEXCore::ARMEmitter::VReg::v28, FEXCore::ARMEmitter::VReg::v29, FEXCore::ARMEmitter::VReg::v30, FEXCore::ARMEmitter::VReg::v31
};
// v8..v15 = (lower 64bits) Callee saved
constexpr std::array<FEXCore::ARMEmitter::VRegister, 12> RAFPR = {
constexpr std::array<FEXCore::ARMEmitter::VRegister, 12 + 8> RAFPR = {
/*FEXCore::ARMEmitter::VReg::v0, FEXCore::ARMEmitter::VReg::v1, FEXCore::ARMEmitter::VReg::v2, FEXCore::ARMEmitter::VReg::v3,*/FEXCore::ARMEmitter::VReg::v4, FEXCore::ARMEmitter::VReg::v5, FEXCore::ARMEmitter::VReg::v6, FEXCore::ARMEmitter::VReg::v7, // FEXCore::ARMEmitter::VReg::v0 ~ FEXCore::ARMEmitter::VReg::v3 are used as temps
FEXCore::ARMEmitter::VReg::v8, FEXCore::ARMEmitter::VReg::v9, FEXCore::ARMEmitter::VReg::v10, FEXCore::ARMEmitter::VReg::v11, FEXCore::ARMEmitter::VReg::v12, FEXCore::ARMEmitter::VReg::v13, FEXCore::ARMEmitter::VReg::v14, FEXCore::ARMEmitter::VReg::v15
FEXCore::ARMEmitter::VReg::v8, FEXCore::ARMEmitter::VReg::v9, FEXCore::ARMEmitter::VReg::v10, FEXCore::ARMEmitter::VReg::v11, FEXCore::ARMEmitter::VReg::v12, FEXCore::ARMEmitter::VReg::v13, FEXCore::ARMEmitter::VReg::v14, FEXCore::ARMEmitter::VReg::v15,
// Registers only available on 32-bit
FEXCore::ARMEmitter::VReg::v24, FEXCore::ARMEmitter::VReg::v25, FEXCore::ARMEmitter::VReg::v26, FEXCore::ARMEmitter::VReg::v27, FEXCore::ARMEmitter::VReg::v28, FEXCore::ARMEmitter::VReg::v29, FEXCore::ARMEmitter::VReg::v30, FEXCore::ARMEmitter::VReg::v31
};
// Contains the address to the currently available CPU state
@@ -90,6 +105,45 @@ protected:
FEXCore::Context::ContextImpl *EmitterCTX;
vixl::aarch64::CPU CPU;
uint32_t ConfiguredGPRs;
uint32_t ConfiguredSRAGPRs;
uint32_t ConfiguredGPRPairs;
uint32_t ConfiguredFPRs;
uint32_t ConfiguredSRAFPRs;
uint32_t ConfiguredDynamicGPRs;
const FEXCore::ARMEmitter::Register *ConfiguredDynamicRegisterBase{};
/**
* @name Register Allocation
* @{ */
// 64-bit gets removal of additional pairs
constexpr static uint32_t NumGPRs64 = RA64.size() - 8;
constexpr static uint32_t NumSRAGPRs64 = SRA64.size();
constexpr static uint32_t NumFPRs64 = RAFPR.size() - 8;
constexpr static uint32_t NumSRAFPRs64 = SRAFPR.size();
constexpr static uint32_t NumGPRPairs64 = RA64Pair.size() - 3;
// 32-bit gets full array of GPR registers
// SRA registers remove the additional 8
constexpr static uint32_t NumGPRs32 = RA64.size();
constexpr static uint32_t NumSRAGPRs32 = SRA64.size() - 8;
constexpr static uint32_t NumFPRs32 = RAFPR.size();
constexpr static uint32_t NumSRAFPRs32 = SRAFPR.size() - 8;
constexpr static uint32_t NumGPRPairs32 = RA64Pair.size();
constexpr static uint32_t RegisterClasses = 6;
constexpr static uint64_t GPRBase = (0ULL << 32);
constexpr static uint64_t FPRBase = (1ULL << 32);
constexpr static uint64_t GPRPairBase = (2ULL << 32);
/** @} */
constexpr static uint8_t RA_32 = 0;
constexpr static uint8_t RA_64 = 1;
constexpr static uint8_t RA_FPR = 2;
void LoadConstant(FEXCore::ARMEmitter::Size s, FEXCore::ARMEmitter::Register Reg, uint64_t Constant, bool NOPPad = false);
@@ -99,7 +153,8 @@ protected:
void SpillStaticRegs(bool FPRs = true, uint32_t GPRSpillMask = ~0U, uint32_t FPRSpillMask = ~0U);
void FillStaticRegs(bool FPRs = true, uint32_t GPRFillMask = ~0U, uint32_t FPRFillMask = ~0U);
static constexpr uint32_t CALLER_GPR_MASK = 0b0011'1111'1111'1111'1111;
// Register 0-18 + 29 + 30 are caller saved
static constexpr uint32_t CALLER_GPR_MASK = 0b0110'0000'0000'0111'1111'1111'1111'1111U;
// This isn't technically true because the lower 64-bits of v8..v15 are callee saved
// We can't guarantee only the lower 64bits are used so flush everything
+7 -11
View File
@@ -517,20 +517,16 @@ Arm64JITCore::Arm64JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::In
RAPass = Thread->PassManager->GetPass<IR::RegisterAllocationPass>("RA");
uint32_t NumUsedGPRs = NumGPRs;
uint32_t NumUsedGPRPairs = NumGPRPairs;
uint32_t UsedRegisterCount = RegisterCount;
RAPass->AllocateRegisterSet(RegisterClasses);
RAPass->AllocateRegisterSet(UsedRegisterCount, RegisterClasses);
RAPass->AddRegisters(FEXCore::IR::GPRClass, NumUsedGPRs);
RAPass->AddRegisters(FEXCore::IR::GPRFixedClass, SRA64.size());
RAPass->AddRegisters(FEXCore::IR::FPRClass, NumFPRs);
RAPass->AddRegisters(FEXCore::IR::FPRFixedClass, SRAFPR.size() );
RAPass->AddRegisters(FEXCore::IR::GPRPairClass, NumUsedGPRPairs);
RAPass->AddRegisters(FEXCore::IR::GPRClass, ConfiguredGPRs);
RAPass->AddRegisters(FEXCore::IR::GPRFixedClass, ConfiguredSRAGPRs);
RAPass->AddRegisters(FEXCore::IR::FPRClass, ConfiguredFPRs);
RAPass->AddRegisters(FEXCore::IR::FPRFixedClass, ConfiguredSRAFPRs);
RAPass->AddRegisters(FEXCore::IR::GPRPairClass, ConfiguredGPRPairs);
RAPass->AddRegisters(FEXCore::IR::ComplexClass, 1);
for (uint32_t i = 0; i < NumUsedGPRPairs; ++i) {
for (uint32_t i = 0; i < ConfiguredGPRPairs; ++i) {
RAPass->AddRegisterConflict(FEXCore::IR::GPRClass, i * 2, FEXCore::IR::GPRPairClass, i);
RAPass->AddRegisterConflict(FEXCore::IR::GPRClass, i * 2 + 1, FEXCore::IR::GPRPairClass, i);
}
@@ -64,27 +64,6 @@ private:
std::map<IR::NodeID, ARMEmitter::BiDirectionalLabel> JumpTargets;
/**
* @name Register Allocation
* @{ */
constexpr static uint32_t NumGPRs = RA64.size();
constexpr static uint32_t NumFPRs = RAFPR.size();
constexpr static uint32_t NumGPRPairs = RA64Pair.size();
constexpr static uint32_t NumCalleeGPRs = 10;
constexpr static uint32_t NumCalleeGPRPairs = 5;
constexpr static uint32_t RegisterCount = NumGPRs + NumFPRs + NumGPRPairs;
constexpr static uint32_t RegisterClasses = 6;
constexpr static uint64_t GPRBase = (0ULL << 32);
constexpr static uint64_t FPRBase = (1ULL << 32);
constexpr static uint64_t GPRPairBase = (2ULL << 32);
/** @} */
constexpr static uint8_t RA_32 = 0;
constexpr static uint8_t RA_64 = 1;
constexpr static uint8_t RA_FPR = 2;
[[nodiscard]] FEXCore::ARMEmitter::Register GetReg(IR::NodeID Node) const {
const auto Reg = GetPhys(Node);
+1 -1
View File
@@ -349,7 +349,7 @@ X86JITCore::X86JITCore(FEXCore::Context::ContextImpl *ctx, FEXCore::Core::Intern
RAPass = Thread->PassManager->GetPass<IR::RegisterAllocationPass>("RA");
RAPass->AllocateRegisterSet(RegisterCount, RegisterClasses);
RAPass->AllocateRegisterSet(RegisterClasses);
RAPass->AddRegisters(FEXCore::IR::GPRClass, NumGPRs);
RAPass->AddRegisters(FEXCore::IR::FPRClass, NumXMMs);
RAPass->AddRegisters(FEXCore::IR::GPRPairClass, NumGPRPairs);
@@ -151,7 +151,6 @@ private:
constexpr static uint32_t NumGPRs = RA64.size(); // 4 is the minimum required for GPR ops
constexpr static uint32_t NumXMMs = RAXMM.size();
constexpr static uint32_t NumGPRPairs = RA64Pair.size();
constexpr static uint32_t RegisterCount = NumGPRs + NumXMMs + NumGPRPairs;
constexpr static uint32_t RegisterClasses = 6;
constexpr static uint64_t GPRBase = (0ULL << 32);
+1
View File
@@ -83,6 +83,7 @@
"constexpr FEXCore::IR::RegisterClassType ComplexClass {5}",
"constexpr FEXCore::IR::RegisterClassType InvalidClass {7}",
"",
"// Only up to 30 registers per register class",
"constexpr uint8_t InvalidReg {31}",
"",
"constexpr FEXCore::IR::TypeDefinition i8 {TypeDefinition::Create(1, 0)}",
@@ -273,7 +273,7 @@ namespace {
~ConstrainedRAPass();
bool Run(IREmitter *IREmit) override;
void AllocateRegisterSet(uint32_t RegisterCount, uint32_t ClassCount) override;
void AllocateRegisterSet(uint32_t ClassCount) override;
void AddRegisters(FEXCore::IR::RegisterClassType Class, uint32_t RegisterCount) override;
void AddRegisterConflict(FEXCore::IR::RegisterClassType ClassConflict, uint32_t RegConflict, FEXCore::IR::RegisterClassType Class, uint32_t Reg) override;
@@ -351,8 +351,7 @@ namespace {
FreeRegisterGraph(Graph);
}
void ConstrainedRAPass::AllocateRegisterSet(uint32_t RegisterCount, uint32_t ClassCount) {
LOGMAN_THROW_AA_FMT(RegisterCount <= INVALID_REG, "Up to {} regs supported", INVALID_REG);
void ConstrainedRAPass::AllocateRegisterSet(uint32_t ClassCount) {
LOGMAN_THROW_AA_FMT(ClassCount <= INVALID_CLASS, "Up to {} classes supported", INVALID_CLASS);
Graph = AllocateRegisterGraph(ClassCount);
@@ -19,7 +19,7 @@ class RegisterAllocationPass : public FEXCore::IR::Pass {
public:
bool HasFullRA() const { return HadFullRA; }
virtual void AllocateRegisterSet(uint32_t RegisterCount, uint32_t ClassCount) = 0;
virtual void AllocateRegisterSet(uint32_t ClassCount) = 0;
virtual void AddRegisters(FEXCore::IR::RegisterClassType Class, uint32_t RegisterCount) = 0;
/**
@@ -8,7 +8,9 @@ namespace FEXCore::IR {
union PhysicalRegister {
uint8_t Raw;
struct {
// 32 maximum physical registers
uint8_t Reg: 5;
// 8 Maximum classes
uint8_t Class: 3;
};
+4
View File
@@ -174,6 +174,10 @@ int main(int argc, char **argv, char **const envp)
FEXCore::Config::AddLayer(std::make_unique<FEX::ArgLoader::ArgLoader>(argc, argv));
FEXCore::Config::AddLayer(FEXCore::Config::CreateEnvironmentLayer(envp));
FEXCore::Config::Load();
// Ensure the IRLoader runs in 64-bit mode.
// This is to ensure that static register allocation in the JIT
// is configured correctly for accesses to the top 8 GPRs and 8 XMM registers.
FEXCore::Config::EraseSet(FEXCore::Config::CONFIG_IS64BIT_MODE, "1");
auto Args = FEX::ArgLoader::Get();
auto ParsedArgs = FEX::ArgLoader::GetParsedArgs();