aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2011-03-30 18:14:07 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2011-03-30 18:14:07 +0000
commitefe65ce25c2f475ef7a9ea767660b029310e503a (patch)
tree198998e31ee4e7a3e3155f0873e03f0c130acc4b
parenteb1c5dcb120faade429f859e0aa9f6fcda1755a0 (diff)
Fix evil VirtRegRewriter bug.
The rewriter can keep track of multiple stack slots in the same register if they happen to have the same value. When an instruction modifies a stack slot by defining a register that is mapped to a stack slot, other stack slots in that register are no longer valid. This is a very rare problem, and I don't have a simple test case. I get the impression that VirtRegRewriter knows it is about to be deleted, inventing a last opaque problem. <rdar://problem/9204040> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@128562 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/VirtRegRewriter.cpp28
1 files changed, 28 insertions, 0 deletions
diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp
index 193892156c..67be1b0842 100644
--- a/lib/CodeGen/VirtRegRewriter.cpp
+++ b/lib/CodeGen/VirtRegRewriter.cpp
@@ -261,6 +261,10 @@ public:
/// now).
void ModifyStackSlotOrReMat(int SlotOrReMat);
+ /// ClobberSharingStackSlots - When a register mapped to a stack slot changes,
+ /// other stack slots sharing the same register are no longer valid.
+ void ClobberSharingStackSlots(int StackSlot);
+
/// AddAvailableRegsToLiveIn - Availability information is being kept coming
/// into the specified MBB. Add available physical registers as potential
/// live-in's. If they are reused in the MBB, they will be added to the
@@ -831,6 +835,26 @@ void AvailableSpills::ModifyStackSlotOrReMat(int SlotOrReMat) {
PhysRegsAvailable.erase(I);
}
+void AvailableSpills::ClobberSharingStackSlots(int StackSlot) {
+ std::map<int, unsigned>::iterator It =
+ SpillSlotsOrReMatsAvailable.find(StackSlot);
+ if (It == SpillSlotsOrReMatsAvailable.end()) return;
+ unsigned Reg = It->second >> 1;
+
+ // Erase entries in PhysRegsAvailable for other stack slots.
+ std::multimap<unsigned, int>::iterator I = PhysRegsAvailable.lower_bound(Reg);
+ while (I != PhysRegsAvailable.end() && I->first == Reg) {
+ std::multimap<unsigned, int>::iterator NextI = llvm::next(I);
+ if (I->second != StackSlot) {
+ DEBUG(dbgs() << "Clobbered sharing SS#" << I->second << " in "
+ << PrintReg(Reg, TRI) << '\n');
+ SpillSlotsOrReMatsAvailable.erase(I->second);
+ PhysRegsAvailable.erase(I);
+ }
+ I = NextI;
+ }
+}
+
// ************************** //
// Reuse Info Implementation //
// ************************** //
@@ -2550,6 +2574,10 @@ LocalRewriter::RewriteMBB(LiveIntervals *LIs,
}
}
+ // If StackSlot is available in a register that also holds other stack
+ // slots, clobber those stack slots now.
+ Spills.ClobberSharingStackSlots(StackSlot);
+
assert(PhysReg && "VR not assigned a physical register?");
MRI->setPhysRegUsed(PhysReg);
unsigned RReg = SubIdx ? TRI->getSubReg(PhysReg, SubIdx) : PhysReg;