JitIL: Implemented linear scan algorithm for register allocation. This is for speed improvement.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5919 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
nodchip 2010-07-19 15:07:19 +00:00
parent 8c57ef548e
commit c9855f2c22

View File

@ -30,7 +30,7 @@ because it the allocator needs to be able to free unused registers.
In addition, this allows eliminating redundant mov instructions in a lot In addition, this allows eliminating redundant mov instructions in a lot
of cases. of cases.
The register allocation is just a simple forward greedy allocator. The register allocation is linear scan allocation.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
@ -58,6 +58,7 @@ struct RegInfo {
IRBuilder* Build; IRBuilder* Build;
InstLoc FirstI; InstLoc FirstI;
std::vector<unsigned> IInfo; std::vector<unsigned> IInfo;
std::vector<InstLoc> lastUsed;
InstLoc regs[16]; InstLoc regs[16];
InstLoc fregs[16]; InstLoc fregs[16];
unsigned numSpills; unsigned numSpills;
@ -67,7 +68,7 @@ struct RegInfo {
unsigned numProfiledLoads; unsigned numProfiledLoads;
unsigned exitNumber; unsigned exitNumber;
RegInfo(JitIL* j, InstLoc f, unsigned insts) : Jit(j), FirstI(f), IInfo(insts) { RegInfo(JitIL* j, InstLoc f, unsigned insts) : Jit(j), FirstI(f), IInfo(insts), lastUsed(insts) {
for (unsigned i = 0; i < 16; i++) { for (unsigned i = 0; i < 16; i++) {
regs[i] = 0; regs[i] = 0;
fregs[i] = 0; fregs[i] = 0;
@ -87,6 +88,7 @@ static void regMarkUse(RegInfo& R, InstLoc I, InstLoc Op, unsigned OpNum) {
unsigned& info = R.IInfo[Op - R.FirstI]; unsigned& info = R.IInfo[Op - R.FirstI];
if (info == 0) R.IInfo[I - R.FirstI] |= 1 << (OpNum + 1); if (info == 0) R.IInfo[I - R.FirstI] |= 1 << (OpNum + 1);
if (info < 2) info++; if (info < 2) info++;
R.lastUsed[Op - R.FirstI] = max(R.lastUsed[Op - R.FirstI], I);
} }
static unsigned regReadUse(RegInfo& R, InstLoc I) { static unsigned regReadUse(RegInfo& R, InstLoc I) {
@ -178,8 +180,18 @@ static X64Reg regFindFreeReg(RegInfo& RI) {
if (RI.regs[RegAllocOrder[i]] == 0) if (RI.regs[RegAllocOrder[i]] == 0)
return RegAllocOrder[i]; return RegAllocOrder[i];
static unsigned nextReg = 0; int bestIndex = -1;
X64Reg reg = RegAllocOrder[nextReg++ % RegAllocSize]; InstLoc bestEnd = 0;
for (int i = 0; i < RegAllocSize; ++i) {
const InstLoc start = RI.regs[RegAllocOrder[i]];
const InstLoc end = RI.lastUsed[start - RI.FirstI];
if (bestEnd < end) {
bestEnd = end;
bestIndex = i;
}
}
X64Reg reg = RegAllocOrder[bestIndex];
regSpill(RI, reg); regSpill(RI, reg);
return reg; return reg;
} }
@ -188,8 +200,19 @@ static X64Reg fregFindFreeReg(RegInfo& RI) {
for (int i = 0; i < FRegAllocSize; i++) for (int i = 0; i < FRegAllocSize; i++)
if (RI.fregs[FRegAllocOrder[i]] == 0) if (RI.fregs[FRegAllocOrder[i]] == 0)
return FRegAllocOrder[i]; return FRegAllocOrder[i];
static unsigned nextReg = 0;
X64Reg reg = FRegAllocOrder[nextReg++ % FRegAllocSize]; int bestIndex = -1;
InstLoc bestEnd = 0;
for (int i = 0; i < FRegAllocSize; ++i) {
const InstLoc start = RI.fregs[FRegAllocOrder[i]];
const InstLoc end = RI.lastUsed[start - RI.FirstI];
if (bestEnd < end) {
bestEnd = end;
bestIndex = i;
}
}
X64Reg reg = FRegAllocOrder[bestIndex];
fregSpill(RI, reg); fregSpill(RI, reg);
return reg; return reg;
} }