From f817d49dfb9c7f8ea66031775cc67a59bf265c6e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 7 Dec 2014 23:08:21 -0800 Subject: [PATCH] jit: Discard clobbered registers on spill. If we're spilling anyway, discard rather than saving. --- Core/MIPS/ARM/ArmRegCache.cpp | 20 ++++++++++++++++---- Core/MIPS/ARM/ArmRegCache.h | 2 +- Core/MIPS/x86/RegCache.cpp | 20 ++++++++++++++++---- Core/MIPS/x86/RegCache.h | 2 +- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Core/MIPS/ARM/ArmRegCache.cpp b/Core/MIPS/ARM/ArmRegCache.cpp index 82272bafdd..f1334edee7 100644 --- a/Core/MIPS/ARM/ArmRegCache.cpp +++ b/Core/MIPS/ARM/ArmRegCache.cpp @@ -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; } diff --git a/Core/MIPS/ARM/ArmRegCache.h b/Core/MIPS/ARM/ArmRegCache.h index 64a97b1cec..02fed51a4b 100644 --- a/Core/MIPS/ARM/ArmRegCache.h +++ b/Core/MIPS/ARM/ArmRegCache.h @@ -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_; diff --git a/Core/MIPS/x86/RegCache.cpp b/Core/MIPS/x86/RegCache.cpp index 46cae1862e..c8cef7ccb7 100644 --- a/Core/MIPS/x86/RegCache.cpp +++ b/Core/MIPS/x86/RegCache.cpp @@ -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; } diff --git a/Core/MIPS/x86/RegCache.h b/Core/MIPS/x86/RegCache.h index 4dff782674..c15ff3b181 100644 --- a/Core/MIPS/x86/RegCache.h +++ b/Core/MIPS/x86/RegCache.h @@ -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];