diff options
author | Pete Cooper <peter_cooper@apple.com> | 2011-12-12 22:16:27 +0000 |
---|---|---|
committer | Pete Cooper <peter_cooper@apple.com> | 2011-12-12 22:16:27 +0000 |
commit | 4777ebb767d1b590c05d502c4a7f6adef4e6d5d1 (patch) | |
tree | 966f9a340cc4d85b357a317b7b695c1610fcf1c0 | |
parent | 22614a02eb8855548a892139e54e478c70050f9f (diff) | |
download | external_llvm-4777ebb767d1b590c05d502c4a7f6adef4e6d5d1.zip external_llvm-4777ebb767d1b590c05d502c4a7f6adef4e6d5d1.tar.gz external_llvm-4777ebb767d1b590c05d502c4a7f6adef4e6d5d1.tar.bz2 |
Fixed register allocator splitting a live range on a spilling variable.
If we create new intervals for a variable that is being spilled, then those new intervals are not guaranteed to also spill. This means that anything reading from the original spilling value might not get the correct value if spills were missed.
Fixes <rdar://problem/10546864>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146428 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/InlineSpiller.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/LiveRangeEdit.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/LiveRangeEdit.h | 7 |
3 files changed, 25 insertions, 4 deletions
diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp index 8f38887..9bf810e 100644 --- a/lib/CodeGen/InlineSpiller.cpp +++ b/lib/CodeGen/InlineSpiller.cpp @@ -957,7 +957,7 @@ void InlineSpiller::reMaterializeAll() { if (DeadDefs.empty()) return; DEBUG(dbgs() << "Remat created " << DeadDefs.size() << " dead defs.\n"); - Edit->eliminateDeadDefs(DeadDefs, LIS, VRM, TII); + Edit->eliminateDeadDefs(DeadDefs, LIS, VRM, TII, RegsToSpill); // Get rid of deleted and empty intervals. for (unsigned i = RegsToSpill.size(); i != 0; --i) { @@ -1240,7 +1240,7 @@ void InlineSpiller::spillAll() { // Hoisted spills may cause dead code. if (!DeadDefs.empty()) { DEBUG(dbgs() << "Eliminating " << DeadDefs.size() << " dead defs\n"); - Edit->eliminateDeadDefs(DeadDefs, LIS, VRM, TII); + Edit->eliminateDeadDefs(DeadDefs, LIS, VRM, TII, RegsToSpill); } // Finally delete the SnippetCopies. diff --git a/lib/CodeGen/LiveRangeEdit.cpp b/lib/CodeGen/LiveRangeEdit.cpp index 428b252..a470877 100644 --- a/lib/CodeGen/LiveRangeEdit.cpp +++ b/lib/CodeGen/LiveRangeEdit.cpp @@ -210,7 +210,8 @@ bool LiveRangeEdit::foldAsLoad(LiveInterval *LI, void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead, LiveIntervals &LIS, VirtRegMap &VRM, - const TargetInstrInfo &TII) { + const TargetInstrInfo &TII, + ArrayRef<unsigned> RegsBeingSpilled) { SetVector<LiveInterval*, SmallVector<LiveInterval*, 8>, SmallPtrSet<LiveInterval*, 8> > ToShrink; @@ -290,6 +291,21 @@ void LiveRangeEdit::eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead, delegate_->LRE_WillShrinkVirtReg(LI->reg); if (!LIS.shrinkToUses(LI, &Dead)) continue; + + // Don't create new intervals for a register being spilled. + // The new intervals would have to be spilled anyway so its not worth it. + // Also they currently aren't spilled so creating them and not spilling + // them results in incorrect code. + bool BeingSpilled = false; + for (unsigned i = 0, e = RegsBeingSpilled.size(); i != e; ++i) { + if (LI->reg == RegsBeingSpilled[i]) { + BeingSpilled = true; + break; + } + } + + if (BeingSpilled) continue; + // LI may have been separated, create new intervals. LI->RenumberValues(LIS); diff --git a/lib/CodeGen/LiveRangeEdit.h b/lib/CodeGen/LiveRangeEdit.h index 9b0a671..057d9bb 100644 --- a/lib/CodeGen/LiveRangeEdit.h +++ b/lib/CodeGen/LiveRangeEdit.h @@ -191,9 +191,14 @@ public: /// eliminateDeadDefs - Try to delete machine instructions that are now dead /// (allDefsAreDead returns true). This may cause live intervals to be trimmed /// and further dead efs to be eliminated. + /// RegsBeingSpilled lists registers currently being spilled by the register + /// allocator. These registers should not be split into new intervals + /// as currently those new intervals are not guaranteed to spill. void eliminateDeadDefs(SmallVectorImpl<MachineInstr*> &Dead, LiveIntervals&, VirtRegMap&, - const TargetInstrInfo&); + const TargetInstrInfo&, + ArrayRef<unsigned> RegsBeingSpilled + = ArrayRef<unsigned>()); /// calculateRegClassAndHint - Recompute register class and hint for each new /// register. |