summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/CodeGen/RegAllocGreedy.cpp13
-rw-r--r--llvm/lib/CodeGen/SplitKit.cpp14
-rw-r--r--llvm/lib/CodeGen/SplitKit.h7
3 files changed, 32 insertions, 2 deletions
diff --git a/llvm/lib/CodeGen/RegAllocGreedy.cpp b/llvm/lib/CodeGen/RegAllocGreedy.cpp
index c1372cd038c..378219b97be 100644
--- a/llvm/lib/CodeGen/RegAllocGreedy.cpp
+++ b/llvm/lib/CodeGen/RegAllocGreedy.cpp
@@ -426,8 +426,13 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) {
if (!IntI.valid())
break;
// Not live in, but before the first use.
- if (IntI.start() < BI.FirstUse)
+ if (IntI.start() < BI.FirstUse) {
BC.Entry = SpillPlacement::PrefSpill;
+ // If the block contains a kill from an earlier split, never split
+ // again in the same block.
+ if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Kill))
+ BC.Entry = SpillPlacement::MustSpill;
+ }
}
// Does interference overlap the uses in the entry segment
@@ -458,8 +463,12 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) {
IntI.advanceTo(BI.LastUse);
if (!IntI.valid())
break;
- if (IntI.start() < Stop)
+ if (IntI.start() < Stop) {
BC.Exit = SpillPlacement::PrefSpill;
+ // Avoid splitting twice in the same block.
+ if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Def))
+ BC.Exit = SpillPlacement::MustSpill;
+ }
}
}
}
diff --git a/llvm/lib/CodeGen/SplitKit.cpp b/llvm/lib/CodeGen/SplitKit.cpp
index 5663936bf3a..a97d890c25b 100644
--- a/llvm/lib/CodeGen/SplitKit.cpp
+++ b/llvm/lib/CodeGen/SplitKit.cpp
@@ -167,6 +167,20 @@ void SplitAnalysis::calcLiveBlockInfo() {
}
}
+bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const {
+ unsigned OrigReg = VRM.getOriginal(CurLI->reg);
+ const LiveInterval &Orig = LIS.getInterval(OrigReg);
+ assert(!Orig.empty() && "Splitting empty interval?");
+ LiveInterval::const_iterator I = Orig.find(Idx);
+
+ // Range containing Idx should begin at Idx.
+ if (I != Orig.end() && I->start <= Idx)
+ return I->start == Idx;
+
+ // Range does not contain Idx, previous must end at Idx.
+ return I != Orig.begin() && (--I)->end == Idx;
+}
+
void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const {
for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) {
unsigned count = UsingBlocks.lookup(*I);
diff --git a/llvm/lib/CodeGen/SplitKit.h b/llvm/lib/CodeGen/SplitKit.h
index 5c34afd1c81..e02e6297035 100644
--- a/llvm/lib/CodeGen/SplitKit.h
+++ b/llvm/lib/CodeGen/SplitKit.h
@@ -125,6 +125,13 @@ public:
return UsingBlocks.lookup(MBB);
}
+ /// isOriginalEndpoint - Return true if the original live range was killed or
+ /// (re-)defined at Idx. Idx should be the 'def' slot for a normal kill/def,
+ /// and 'use' for an early-clobber def.
+ /// This can be used to recognize code inserted by earlier live range
+ /// splitting.
+ bool isOriginalEndpoint(SlotIndex Idx) const;
+
typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet;
// Print a set of blocks with use counts.
OpenPOWER on IntegriCloud