diff options
author | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2010-05-14 00:02:20 +0000 |
---|---|---|
committer | Jakob Stoklund Olesen <stoklund@2pi.dk> | 2010-05-14 00:02:20 +0000 |
commit | 7d4f25904de543b039a28eddbea3034a5d80e7f8 (patch) | |
tree | 39b1274f6604e86b1dc7807fc0e73becc74513e7 /lib/CodeGen/RegAllocFast.cpp | |
parent | dbf67fefeaccfeb53fb9d6098180ba1f29e682d5 (diff) |
Fix an embarrassing runtime regression for RegAllocFast.
This loop is quadratic in the capacity for a DenseMap:
while(!map.empty())
map.erase(map.begin());
Instead we now do a normal begin() - end() iteration followed by map.clear().
That also has the nice sideeffect of shrinking the map capacity on demand.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103747 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegAllocFast.cpp')
-rw-r--r-- | lib/CodeGen/RegAllocFast.cpp | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/lib/CodeGen/RegAllocFast.cpp b/lib/CodeGen/RegAllocFast.cpp index 0b03efffd6..2f59b1d849 100644 --- a/lib/CodeGen/RegAllocFast.cpp +++ b/lib/CodeGen/RegAllocFast.cpp @@ -45,7 +45,8 @@ namespace { class RAFast : public MachineFunctionPass { public: static char ID; - RAFast() : MachineFunctionPass(&ID), StackSlotForVirtReg(-1) {} + RAFast() : MachineFunctionPass(&ID), StackSlotForVirtReg(-1), + atEndOfBlock(false) {} private: const TargetMachine *TM; MachineFunction *MF; @@ -106,6 +107,11 @@ namespace { // ReservedRegs - vector of reserved physical registers. BitVector ReservedRegs; + // atEndOfBlock - This flag is set after allocating all instructions in a + // block, before emitting final spills. When it is set, LiveRegMap is no + // longer updated properly sonce it will be cleared anyway. + bool atEndOfBlock; + public: virtual const char *getPassName() const { return "Fast Register Allocator"; @@ -126,6 +132,8 @@ namespace { void killVirtReg(LiveRegMap::iterator i); void killVirtReg(unsigned VirtReg); void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + LiveRegMap::iterator i, bool isKill); + void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned VirtReg, bool isKill); void killPhysReg(unsigned PhysReg); void spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I, @@ -182,7 +190,10 @@ void RAFast::killVirtReg(LiveRegMap::iterator lri) { const LiveReg &LR = lri->second; assert(PhysRegState[LR.PhysReg] == lri->first && "Broken RegState mapping"); PhysRegState[LR.PhysReg] = regFree; - LiveVirtRegs.erase(lri); + // Erase from LiveVirtRegs unless we're at the end of the block when + // everything will be bulk erased. + if (!atEndOfBlock) + LiveVirtRegs.erase(lri); } /// killVirtReg - Mark virtreg as no longer available. @@ -204,8 +215,15 @@ void RAFast::spillVirtReg(MachineBasicBlock &MBB, "Spilling a physical register is illegal!"); LiveRegMap::iterator lri = LiveVirtRegs.find(VirtReg); assert(lri != LiveVirtRegs.end() && "Spilling unmapped virtual register"); + spillVirtReg(MBB, MI, lri, isKill); +} + +/// spillVirtReg - Do the actual work of spilling. +void RAFast::spillVirtReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + LiveRegMap::iterator lri, bool isKill) { LiveReg &LR = lri->second; - assert(PhysRegState[LR.PhysReg] == VirtReg && "Broken RegState mapping"); + assert(PhysRegState[LR.PhysReg] == lri->first && "Broken RegState mapping"); // If this physreg is used by the instruction, we want to kill it on the // instruction, not on the spill. @@ -213,10 +231,10 @@ void RAFast::spillVirtReg(MachineBasicBlock &MBB, if (LR.Dirty) { LR.Dirty = false; - DEBUG(dbgs() << "Spilling register " << TRI->getName(LR.PhysReg) - << " containing %reg" << VirtReg); - const TargetRegisterClass *RC = MRI->getRegClass(VirtReg); - int FrameIndex = getStackSpaceFor(VirtReg, RC); + DEBUG(dbgs() << "Spilling %reg" << lri->first + << " in " << TRI->getName(LR.PhysReg)); + const TargetRegisterClass *RC = MRI->getRegClass(lri->first); + int FrameIndex = getStackSpaceFor(lri->first, RC); DEBUG(dbgs() << " to stack slot #" << FrameIndex << "\n"); TII->storeRegToStackSlot(MBB, MI, LR.PhysReg, spillKill, FrameIndex, RC, TRI); @@ -573,6 +591,7 @@ void RAFast::setPhysReg(MachineOperand &MO, unsigned PhysReg) { void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) { DEBUG(dbgs() << "\nAllocating " << MBB); + atEndOfBlock = false; PhysRegState.assign(TRI->getNumRegs(), regDisabled); assert(LiveVirtRegs.empty() && "Mapping not cleared form last block?"); @@ -772,10 +791,13 @@ void RAFast::AllocateBasicBlock(MachineBasicBlock &MBB) { } // Spill all physical registers holding virtual registers now. + atEndOfBlock = true; DEBUG(dbgs() << "Killing live registers at end of block.\n"); MachineBasicBlock::iterator MI = MBB.getFirstTerminator(); - while (!LiveVirtRegs.empty()) - spillVirtReg(MBB, MI, LiveVirtRegs.begin()->first, true); + for (LiveRegMap::iterator i = LiveVirtRegs.begin(), e = LiveVirtRegs.end(); + i != e; ++i) + spillVirtReg(MBB, MI, i, true); + LiveVirtRegs.clear(); DEBUG(MBB.dump()); } |