summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/VirtRegMap.cpp
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-03-11 07:19:34 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-03-11 07:19:34 +0000
commite88a625ecd110448a5b8c74f2396fea210fc5bdf (patch)
tree398381579f4c290a6c56f3374d2b4737affc319c /llvm/lib/CodeGen/VirtRegMap.cpp
parent5b59e372dcb4776bd2acb4ae0c6438aead9fe7c2 (diff)
downloadbcm5719-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.cpp40
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);
OpenPOWER on IntegriCloud