diff options
| author | Evan Cheng <evan.cheng@apple.com> | 2008-03-11 07:19:34 +0000 |
|---|---|---|
| committer | Evan Cheng <evan.cheng@apple.com> | 2008-03-11 07:19:34 +0000 |
| commit | e88a625ecd110448a5b8c74f2396fea210fc5bdf (patch) | |
| tree | 398381579f4c290a6c56f3374d2b4737affc319c /llvm/lib/CodeGen/VirtRegMap.cpp | |
| parent | 5b59e372dcb4776bd2acb4ae0c6438aead9fe7c2 (diff) | |
| download | bcm5719-llvm-e88a625ecd110448a5b8c74f2396fea210fc5bdf.tar.gz bcm5719-llvm-e88a625ecd110448a5b8c74f2396fea210fc5bdf.zip | |
When the register allocator runs out of registers, spill a physical register around the def's and use's of the interval being allocated to make it possible for the interval to target a register and spill it right away and restore a register for uses. This likely generates terrible code but is before than aborting.
llvm-svn: 48218
Diffstat (limited to 'llvm/lib/CodeGen/VirtRegMap.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/VirtRegMap.cpp | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/VirtRegMap.cpp b/llvm/lib/CodeGen/VirtRegMap.cpp index c39ac610e96..cce36e51628 100644 --- a/llvm/lib/CodeGen/VirtRegMap.cpp +++ b/llvm/lib/CodeGen/VirtRegMap.cpp @@ -125,6 +125,21 @@ void VirtRegMap::assignVirtReMatId(unsigned virtReg, int id) { Virt2ReMatIdMap[virtReg] = id; } +int VirtRegMap::getEmergencySpillSlot(const TargetRegisterClass *RC) { + std::map<const TargetRegisterClass*, int>::iterator I = + EmergencySpillSlots.find(RC); + if (I != EmergencySpillSlots.end()) + return I->second; + int SS = MF.getFrameInfo()->CreateStackObject(RC->getSize(), + RC->getAlignment()); + if (LowSpillSlot == NO_STACK_SLOT) + LowSpillSlot = SS; + if (HighSpillSlot == NO_STACK_SLOT || SS > HighSpillSlot) + HighSpillSlot = SS; + I->second = SS; + return SS; +} + void VirtRegMap::addSpillSlotUse(int FI, MachineInstr *MI) { if (!MF.getFrameInfo()->isFixedObjectIndex(FI)) { assert(FI >= 0 && "Spill slot index should not be negative!"); @@ -164,6 +179,7 @@ void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) { MI2VirtMap.erase(MI); SpillPt2VirtMap.erase(MI); RestorePt2VirtMap.erase(MI); + EmergencySpillMap.erase(MI); } void VirtRegMap::print(std::ostream &OS) const { @@ -1043,6 +1059,30 @@ void LocalSpiller::RewriteMBB(MachineBasicBlock &MBB, VirtRegMap &VRM) { MachineInstr &MI = *MII; const TargetInstrDesc &TID = MI.getDesc(); + if (VRM.hasEmergencySpills(&MI)) { + // Spill physical register(s) in the rare case the allocator has run out + // of registers to allocate. + SmallSet<int, 4> UsedSS; + std::vector<unsigned> &EmSpills = VRM.getEmergencySpills(&MI); + for (unsigned i = 0, e = EmSpills.size(); i != e; ++i) { + unsigned PhysReg = EmSpills[i]; + const TargetRegisterClass *RC = + TRI->getPhysicalRegisterRegClass(PhysReg); + assert(RC && "Unable to determine register class!"); + int SS = VRM.getEmergencySpillSlot(RC); + if (UsedSS.count(SS)) + assert(0 && "Need to spill more than one physical registers!"); + UsedSS.insert(SS); + TII->storeRegToStackSlot(MBB, MII, PhysReg, true, SS, RC); + MachineInstr *StoreMI = prior(MII); + VRM.addSpillSlotUse(SS, StoreMI); + TII->loadRegFromStackSlot(MBB, next(MII), PhysReg, SS, RC); + MachineInstr *LoadMI = next(MII); + VRM.addSpillSlotUse(SS, LoadMI); + ++NumSpills; + } + } + // Insert restores here if asked to. if (VRM.isRestorePt(&MI)) { std::vector<unsigned> &RestoreRegs = VRM.getRestorePtRestores(&MI); |

