Use a simpler data structure to calculate the least recently used register in RegAllocLocal.

This makes the local register allocator about 20% faster.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101574 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jakob Stoklund Olesen
2010-04-16 23:32:37 +00:00
parent de0ade4939
commit cf7fbd41be

View File

@ -76,15 +76,16 @@ namespace {
// //
std::vector<int> PhysRegsUsed; std::vector<int> PhysRegsUsed;
// PhysRegsUseOrder - This contains a list of the physical registers that // InstrNum - Number of the current instruction. This is used for the
// currently have a virtual register value in them. This list provides an // PhysLastUse map.
// ordering of registers, imposing a reallocation order. This list is only
// used if all registers are allocated and we have to spill one, in which
// case we spill the least recently used register. Entries at the front of
// the list are the least recently used registers, entries at the back are
// the most recently used.
// //
std::vector<unsigned> PhysRegsUseOrder; unsigned InstrNum;
// PhysLastUse - Store the instruction number of the last use of each physical
// register. This is used to find the least recently used register. when
// spilling.
//
std::vector<unsigned> PhysLastUse;
// Virt2LastUseMap - This maps each virtual register to its last use // Virt2LastUseMap - This maps each virtual register to its last use
// (MachineInstr*, operand index pair). // (MachineInstr*, operand index pair).
@ -123,28 +124,8 @@ namespace {
return VirtRegModified[Reg - TargetRegisterInfo::FirstVirtualRegister]; return VirtRegModified[Reg - TargetRegisterInfo::FirstVirtualRegister];
} }
void AddToPhysRegsUseOrder(unsigned Reg) {
std::vector<unsigned>::iterator It =
std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), Reg);
if (It != PhysRegsUseOrder.end())
PhysRegsUseOrder.erase(It);
PhysRegsUseOrder.push_back(Reg);
}
void MarkPhysRegRecentlyUsed(unsigned Reg) { void MarkPhysRegRecentlyUsed(unsigned Reg) {
if (PhysRegsUseOrder.empty() || PhysLastUse[Reg] = InstrNum;
PhysRegsUseOrder.back() == Reg) return; // Already most recently used
for (unsigned i = PhysRegsUseOrder.size(); i != 0; --i) {
unsigned RegMatch = PhysRegsUseOrder[i-1]; // remove from middle
if (!areRegsEqual(Reg, RegMatch)) continue;
PhysRegsUseOrder.erase(PhysRegsUseOrder.begin()+i-1);
// Add it to the end of the list
PhysRegsUseOrder.push_back(RegMatch);
if (RegMatch == Reg)
return; // Found an exact match, exit early
}
} }
public: public:
@ -279,11 +260,6 @@ int RALocal::getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC) {
/// ///
void RALocal::removePhysReg(unsigned PhysReg) { void RALocal::removePhysReg(unsigned PhysReg) {
PhysRegsUsed[PhysReg] = -1; // PhyReg no longer used PhysRegsUsed[PhysReg] = -1; // PhyReg no longer used
std::vector<unsigned>::iterator It =
std::find(PhysRegsUseOrder.begin(), PhysRegsUseOrder.end(), PhysReg);
if (It != PhysRegsUseOrder.end())
PhysRegsUseOrder.erase(It);
} }
@ -365,7 +341,7 @@ void RALocal::assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) {
// it holds VirtReg. // it holds VirtReg.
PhysRegsUsed[PhysReg] = VirtReg; PhysRegsUsed[PhysReg] = VirtReg;
getVirt2PhysRegMapSlot(VirtReg) = PhysReg; getVirt2PhysRegMapSlot(VirtReg) = PhysReg;
AddToPhysRegsUseOrder(PhysReg); // New use of PhysReg MarkPhysRegRecentlyUsed(PhysReg); // New use of PhysReg
} }
@ -421,56 +397,20 @@ unsigned RALocal::getReg(MachineBasicBlock &MBB, MachineInstr *I,
return PhysReg; return PhysReg;
} }
// If we didn't find an unused register, scavenge one now! // Find the least recently used register in the allocation order.
assert(!PhysRegsUseOrder.empty() && "No allocated registers??"); unsigned Oldest = 0;
TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF);
// Loop over all of the preallocated registers from the least recently used TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF);
// to the most recently used. When we find one that is capable of holding for (; RI != RE; ++RI) {
// our register, use it. unsigned Age = InstrNum-PhysLastUse[*RI];
for (unsigned i = 0; PhysReg == 0; ++i) { if (Age <= Oldest && PhysReg) continue;
assert(i != PhysRegsUseOrder.size() && PhysReg = *RI;
"Couldn't find a register of the appropriate class!"); Oldest = Age;
unsigned R = PhysRegsUseOrder[i];
// We can only use this register if it holds a virtual register (ie, it
// can be spilled). Do not use it if it is an explicitly allocated
// physical register!
assert(PhysRegsUsed[R] != -1 &&
"PhysReg in PhysRegsUseOrder, but is not allocated?");
if (PhysRegsUsed[R] && PhysRegsUsed[R] != -2) {
// If the current register is compatible, use it.
if (RC->contains(R)) {
PhysReg = R;
break;
}
// If one of the registers aliased to the current register is
// compatible, use it.
for (const unsigned *AliasIt = TRI->getAliasSet(R);
*AliasIt; ++AliasIt) {
if (!RC->contains(*AliasIt)) continue;
// If this is pinned down for some reason, don't use it. For
// example, if CL is pinned, and we run across CH, don't use
// CH as justification for using scavenging ECX (which will
// fail).
if (PhysRegsUsed[*AliasIt] == 0) continue;
// Make sure the register is allocatable. Don't allocate SIL on
// x86-32.
if (PhysRegsUsed[*AliasIt] == -2) continue;
PhysReg = *AliasIt; // Take an aliased register
break;
}
}
} }
assert(PhysReg && "Physical register not assigned!?!?"); assert(PhysReg && "Physical register not assigned!?!?");
// At this point PhysRegsUseOrder[i] is the least recently used register of // Spill it to memory and reap its remains.
// compatible register class. Spill it to memory and reap its remains.
spillPhysReg(MBB, I, PhysReg); spillPhysReg(MBB, I, PhysReg);
// Now that we know which register we need to assign this to, do it now! // Now that we know which register we need to assign this to, do it now!
@ -638,18 +578,10 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) {
if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) continue; if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) continue;
const unsigned *Aliases = TRI->getAliasSet(MO.getReg()); for (const unsigned *A = TRI->getAliasSet(MO.getReg()); *A; ++A) {
if (Aliases == 0) std::pair<MachineInstr*, unsigned> &LUD = LastUseDef[*A];
continue; if (LUD.first != I)
LUD = std::make_pair(I, i);
while (*Aliases) {
DenseMap<unsigned, std::pair<MachineInstr*, unsigned> >::iterator
alias = LastUseDef.find(*Aliases);
if (alias != LastUseDef.end() && alias->second.first != I)
LastUseDef[*Aliases] = std::make_pair(I, i);
++Aliases;
} }
} }
@ -780,12 +712,11 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
unsigned Reg = *I; unsigned Reg = *I;
MF->getRegInfo().setPhysRegUsed(Reg); MF->getRegInfo().setPhysRegUsed(Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now PhysRegsUsed[Reg] = 0; // It is free and reserved now
AddToPhysRegsUseOrder(Reg); MarkPhysRegRecentlyUsed(Reg);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
*SubRegs; ++SubRegs) { *SubRegs; ++SubRegs) {
if (PhysRegsUsed[*SubRegs] == -2) continue; if (PhysRegsUsed[*SubRegs] == -2) continue;
MarkPhysRegRecentlyUsed(*SubRegs);
AddToPhysRegsUseOrder(*SubRegs);
PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now
MF->getRegInfo().setPhysRegUsed(*SubRegs); MF->getRegInfo().setPhysRegUsed(*SubRegs);
} }
@ -796,6 +727,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
// Otherwise, sequentially allocate each instruction in the MBB. // Otherwise, sequentially allocate each instruction in the MBB.
while (MII != MBB.end()) { while (MII != MBB.end()) {
MachineInstr *MI = MII++; MachineInstr *MI = MII++;
++InstrNum;
const TargetInstrDesc &TID = MI->getDesc(); const TargetInstrDesc &TID = MI->getDesc();
DEBUG({ DEBUG({
dbgs() << "\nStarting RegAlloc of: " << *MI; dbgs() << "\nStarting RegAlloc of: " << *MI;
@ -874,14 +806,14 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
MF->getRegInfo().setPhysRegUsed(Reg); MF->getRegInfo().setPhysRegUsed(Reg);
spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg
PhysRegsUsed[Reg] = 0; // It is free and reserved now PhysRegsUsed[Reg] = 0; // It is free and reserved now
AddToPhysRegsUseOrder(Reg); MarkPhysRegRecentlyUsed(Reg);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
*SubRegs; ++SubRegs) { *SubRegs; ++SubRegs) {
if (PhysRegsUsed[*SubRegs] == -2) continue; if (PhysRegsUsed[*SubRegs] == -2) continue;
MF->getRegInfo().setPhysRegUsed(*SubRegs); MF->getRegInfo().setPhysRegUsed(*SubRegs);
PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now
AddToPhysRegsUseOrder(*SubRegs); MarkPhysRegRecentlyUsed(*SubRegs);
} }
} }
} }
@ -971,7 +903,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
MF->getRegInfo().setPhysRegUsed(Reg); MF->getRegInfo().setPhysRegUsed(Reg);
spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg
PhysRegsUsed[Reg] = 0; // It is free and reserved now PhysRegsUsed[Reg] = 0; // It is free and reserved now
AddToPhysRegsUseOrder(Reg); MarkPhysRegRecentlyUsed(Reg);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
*SubRegs; ++SubRegs) { *SubRegs; ++SubRegs) {
@ -979,7 +911,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
MF->getRegInfo().setPhysRegUsed(*SubRegs); MF->getRegInfo().setPhysRegUsed(*SubRegs);
PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now
AddToPhysRegsUseOrder(*SubRegs); MarkPhysRegRecentlyUsed(*SubRegs);
} }
} }
@ -990,7 +922,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
unsigned Reg = *ImplicitDefs; unsigned Reg = *ImplicitDefs;
if (PhysRegsUsed[Reg] != -2) { if (PhysRegsUsed[Reg] != -2) {
spillPhysReg(MBB, MI, Reg, true); spillPhysReg(MBB, MI, Reg, true);
AddToPhysRegsUseOrder(Reg); MarkPhysRegRecentlyUsed(Reg);
PhysRegsUsed[Reg] = 0; // It is free and reserved now PhysRegsUsed[Reg] = 0; // It is free and reserved now
} }
MF->getRegInfo().setPhysRegUsed(Reg); MF->getRegInfo().setPhysRegUsed(Reg);
@ -998,7 +930,7 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
*SubRegs; ++SubRegs) { *SubRegs; ++SubRegs) {
if (PhysRegsUsed[*SubRegs] == -2) continue; if (PhysRegsUsed[*SubRegs] == -2) continue;
AddToPhysRegsUseOrder(*SubRegs); MarkPhysRegRecentlyUsed(*SubRegs);
PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now PhysRegsUsed[*SubRegs] = 0; // It is free and reserved now
MF->getRegInfo().setPhysRegUsed(*SubRegs); MF->getRegInfo().setPhysRegUsed(*SubRegs);
} }
@ -1123,11 +1055,6 @@ void RALocal::AllocateBasicBlock(MachineBasicBlock &MBB) {
} }
assert(AllOk && "Virtual registers still in phys regs?"); assert(AllOk && "Virtual registers still in phys regs?");
#endif #endif
// Clear any physical register which appear live at the end of the basic
// block, but which do not hold any virtual registers. e.g., the stack
// pointer.
PhysRegsUseOrder.clear();
} }
/// runOnMachineFunction - Register allocate the whole function /// runOnMachineFunction - Register allocate the whole function
@ -1140,6 +1067,8 @@ bool RALocal::runOnMachineFunction(MachineFunction &Fn) {
TII = TM->getInstrInfo(); TII = TM->getInstrInfo();
PhysRegsUsed.assign(TRI->getNumRegs(), -1); PhysRegsUsed.assign(TRI->getNumRegs(), -1);
InstrNum = 0;
PhysLastUse.assign(TRI->getNumRegs(), 0);
// At various places we want to efficiently check to see whether a register // At various places we want to efficiently check to see whether a register
// is allocatable. To handle this, we mark all unallocatable registers as // is allocatable. To handle this, we mark all unallocatable registers as