Add SplitKit::isOriginalEndpoint and use it to force live range splitting to terminate.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Mon, 21 Feb 2011 23:09:46 +0000 (23:09 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Mon, 21 Feb 2011 23:09:46 +0000 (23:09 +0000)
An original endpoint is an instruction that killed or defined the original live
range before any live ranges were split.

When splitting global live ranges, avoid creating local live ranges without any
original endpoints. We may still create global live ranges without original
endpoints, but such a range won't be split again, and live range splitting still
terminates.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@126151 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/RegAllocGreedy.cpp
lib/CodeGen/SplitKit.cpp
lib/CodeGen/SplitKit.h

index c1372cd038cfecf67907159bc749118f2896c92e..378219b97bef54327e51eb8ff1255cb697c6d291 100644 (file)
@@ -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;
+          }
         }
       }
     }
index 5663936bf3aae501fb0512b3e9be4a8f076c8d91..a97d890c25b09f28ba0332c90a620009fbc98b7b 100644 (file)
@@ -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);
index 5c34afd1c81952d13ee697c11d5ef63fabcce6d8..e02e6297035dadae7578040410242049d657836a 100644 (file)
@@ -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.