jit: Discard clobbered registers on spill.

If we're spilling anyway, discard rather than saving.
This commit is contained in:
Unknown W. Brackets committed 2014-12-07 23:08:21 -08:00
1 parent f6531a74e1
commit f817d49dfb
4 files changed
+34 -10

No files matched your search

+16 -4
View File
@@ -193,17 +193,24 @@ void ArmRegCache::MapRegTo(ARMReg reg, MIPSGPReg mipsReg, int mapFlags) {
mr[mipsReg].reg = reg;
}
ARMReg ArmRegCache::FindBestToSpill(bool unusedOnly) {
ARMReg ArmRegCache::FindBestToSpill(bool unusedOnly, bool *clobbered) {
int allocCount;
const ARMReg *allocOrder = GetMIPSAllocationOrder(allocCount);
static const int UNUSED_LOOKAHEAD_OPS = 30;
*clobbered = false;
for (int i = 0; i < allocCount; i++) {
ARMReg reg = allocOrder[i];
if (ar[reg].mipsReg != MIPS_REG_INVALID && mr[ar[reg].mipsReg].spillLock)
continue;
// Awesome, a clobbered reg. Let's use it.
if (MIPSAnalyst::IsRegisterClobbered(ar[reg].mipsReg, compilerPC_, UNUSED_LOOKAHEAD_OPS)) {
*clobbered = true;
return reg;
}
// Not awesome. A used reg. Let's try to avoid spilling.
if (unusedOnly && MIPSAnalyst::IsRegisterUsed(ar[reg].mipsReg, compilerPC_, UNUSED_LOOKAHEAD_OPS)) {
continue;
@@ -280,14 +287,19 @@ allocate:
// Still nothing. Let's spill a reg and goto 10.
// TODO: Use age or something to choose which register to spill?
// TODO: Spill dirty regs first? or opposite?
ARMReg bestToSpill = FindBestToSpill(true);
bool clobbered;
ARMReg bestToSpill = FindBestToSpill(true, &clobbered);
if (bestToSpill == INVALID_REG) {
bestToSpill = FindBestToSpill(false);
bestToSpill = FindBestToSpill(false, &clobbered);
}
if (bestToSpill != INVALID_REG) {
// ERROR_LOG(JIT, "Out of registers at PC %08x - spills register %i.", mips_->pc, bestToSpill);
FlushArmReg(bestToSpill);
if (clobbered) {
DiscardR(ar[bestToSpill].mipsReg);
} else {
FlushArmReg(bestToSpill);
}
goto allocate;
}
+1 -1
View File
@@ -130,7 +130,7 @@ private:
const ArmGen::ARMReg *GetMIPSAllocationOrder(int &count);
void MapRegTo(ArmGen::ARMReg reg, MIPSGPReg mipsReg, int mapFlags);
int FlushGetSequential(MIPSGPReg startMipsReg, bool allowFlushImm);
ArmGen::ARMReg FindBestToSpill(bool unusedOnly);
ArmGen::ARMReg FindBestToSpill(bool unusedOnly, bool *clobbered);
MIPSState *mips_;
ArmGen::ARMXEmitter *emit_;
+16 -4
View File
@@ -122,12 +122,13 @@ void GPRRegCache::UnlockAllX() {
xregs[i].allocLocked = false;
}
X64Reg GPRRegCache::FindBestToSpill(bool unusedOnly) {
X64Reg GPRRegCache::FindBestToSpill(bool unusedOnly, bool *clobbered) {
int allocCount;
const int *allocOrder = GetAllocationOrder(allocCount);
static const int UNUSED_LOOKAHEAD_OPS = 30;
*clobbered = false;
for (int i = 0; i < allocCount; i++) {
X64Reg reg = (X64Reg)allocOrder[i];
if (xregs[reg].allocLocked)
@@ -135,6 +136,12 @@ X64Reg GPRRegCache::FindBestToSpill(bool unusedOnly) {
if (xregs[reg].mipsReg != MIPS_REG_INVALID && regs[xregs[reg].mipsReg].locked)
continue;
// Awesome, a clobbered reg. Let's use it.
if (MIPSAnalyst::IsRegisterClobbered(xregs[reg].mipsReg, js_->compilerPC, UNUSED_LOOKAHEAD_OPS)) {
*clobbered = true;
return reg;
}
// Not awesome. A used reg. Let's try to avoid spilling.
if (unusedOnly && MIPSAnalyst::IsRegisterUsed(xregs[reg].mipsReg, js_->compilerPC, UNUSED_LOOKAHEAD_OPS)) {
continue;
@@ -160,13 +167,18 @@ X64Reg GPRRegCache::GetFreeXReg()
}
//Okay, not found :( Force grab one
X64Reg bestToSpill = FindBestToSpill(true);
bool clobbered;
X64Reg bestToSpill = FindBestToSpill(true, &clobbered);
if (bestToSpill == INVALID_REG) {
bestToSpill = FindBestToSpill(false);
bestToSpill = FindBestToSpill(false, &clobbered);
}
if (bestToSpill != INVALID_REG) {
StoreFromRegister(xregs[bestToSpill].mipsReg);
if (clobbered) {
DiscardRegContentsIfCached(xregs[bestToSpill].mipsReg);
} else {
StoreFromRegister(xregs[bestToSpill].mipsReg);
}
return bestToSpill;
}
+1 -1
View File
@@ -115,7 +115,7 @@ public:
private:
Gen::X64Reg GetFreeXReg();
Gen::X64Reg FindBestToSpill(bool unusedOnly);
Gen::X64Reg FindBestToSpill(bool unusedOnly, bool *clobbered);
const int *GetAllocationOrder(int &count);
MIPSCachedReg regs[NUM_MIPS_GPRS];