Extract parts of RAGreedy::splitAroundRegion as SplitKit methods.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 15 Jul 2011 21:47:57 +0000 (21:47 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 15 Jul 2011 21:47:57 +0000 (21:47 +0000)
This gets rid of some of the gory splitting details in RAGreedy and
makes them available to future SplitKit clients.

Slightly generalize the functionality to support multi-way splitting.
Specifically, SplitEditor::splitLiveThroughBlock() supports switching
between different register intervals in a block.

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

include/llvm/CodeGen/SlotIndexes.h
lib/CodeGen/RegAllocGreedy.cpp
lib/CodeGen/SplitKit.cpp
lib/CodeGen/SplitKit.h

index 33ce675e5cc49e9d9617fef6ce4333453c7dd1b0..6eb31802120e07417f0d3c815f93ad2eacb2b165 100644 (file)
@@ -140,6 +140,9 @@ namespace llvm {
       return lie.getPointer();
     }
 
+    /// Return true for a valid index.
+    operator bool() const { return isValid(); }
+
     /// Print this index to the given raw_ostream.
     void print(raw_ostream &os) const;
 
index 8677a3e257a5838ecbf9b522488ac98939604be8..2dde767c828d976ab67a0ba2ae92f8a0a7f142bb 100644 (file)
@@ -870,16 +870,6 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
                   LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)];
 
     // Create separate intervals for isolated blocks with multiple uses.
-    //
-    //     |---o---o---|    Enter and leave on the stack.
-    //     ____-----____    Create local interval for uses.
-    //
-    //     |   o---o---|    Defined in block, leave on stack.
-    //         -----____    Create local interval for uses.
-    //
-    //     |---o---x   |    Enter on stack, killed in block.
-    //     ____-----        Create local interval for uses.
-    //
     if (!RegIn && !RegOut) {
       DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n");
       if (!BI.isOneInstr()) {
@@ -889,304 +879,28 @@ void RAGreedy::splitAroundRegion(LiveInterval &VirtReg,
       continue;
     }
 
-    SlotIndex Start, Stop;
-    tie(Start, Stop) = Indexes->getMBBRange(BI.MBB);
     Intf.moveToBlock(BI.MBB->getNumber());
-    DEBUG(dbgs() << "EB#" << Bundles->getBundle(BI.MBB->getNumber(), 0)
-                 << (BI.LiveIn ? (RegIn ? " => " : " -> ") : "    ")
-                 << "BB#" << BI.MBB->getNumber()
-                 << (BI.LiveOut ? (RegOut ? " => " : " -> ") : "    ")
-                 << " EB#" << Bundles->getBundle(BI.MBB->getNumber(), 1)
-                 << " [" << Start << ';'
-                 << SA->getLastSplitPoint(BI.MBB->getNumber()) << '-' << Stop
-                 << ") uses [" << BI.FirstUse << ';' << BI.LastUse
-                 << ") intf [" << Intf.first() << ';' << Intf.last() << ')');
-
-    // The interference interval should either be invalid or overlap MBB.
-    assert((!Intf.hasInterference() || Intf.first() < Stop)
-           && "Bad interference");
-    assert((!Intf.hasInterference() || Intf.last() > Start)
-           && "Bad interference");
-
-    // We are now ready to decide where to split in the current block.  There
-    // are many variables guiding the decision:
-    //
-    // - RegIn / RegOut: The global splitting algorithm's decisions for our
-    //   ingoing and outgoing bundles.
-    //
-    // - BI.BlockIn / BI.BlockOut: Is the live range live-in and/or live-out
-    //   from this block.
-    //
-    // - Intf.hasInterference(): Is there interference in this block.
-    //
-    // - Intf.first() / Inft.last(): The range of interference.
-    //
-    // The live range should be split such that MainIntv is live-in when RegIn
-    // is set, and live-out when RegOut is set.  MainIntv should never overlap
-    // the interference, and the stack interval should never have more than one
-    // use per block.
-
-    // No splits can be inserted after LastSplitPoint, overlap instead.
-    SlotIndex LastSplitPoint = Stop;
-    if (BI.LiveOut)
-      LastSplitPoint = SA->getLastSplitPoint(BI.MBB->getNumber());
-
-    // At this point, we know that either RegIn or RegOut is set. We dealt with
-    // the all-stack case above.
-
-    // Blocks without interference are relatively easy.
-    if (!Intf.hasInterference()) {
-      DEBUG(dbgs() << ", no interference.\n");
-      SE->selectIntv(MainIntv);
-      // The easiest case has MainIntv live through.
-      //
-      //     |---o---o---|    Live-in, live-out.
-      //     =============    Use MainIntv everywhere.
-      //
-      SlotIndex From = Start, To = Stop;
-
-      // Block entry. Reload before the first use if MainIntv is not live-in.
-      //
-      //     |---o--    Enter on stack.
-      //     ____===    Reload before first use.
-      //
-      //     |   o--    Defined in block.
-      //         ===    Use MainIntv from def.
-      //
-      if (!RegIn)
-        From = SE->enterIntvBefore(BI.FirstUse);
-
-      // Block exit. Handle cases where MainIntv is not live-out.
-      if (!BI.LiveOut)
-        //
-        //     --x   |    Killed in block.
-        //     ===        Use MainIntv up to kill.
-        //
-        To = SE->leaveIntvAfter(BI.LastUse);
-      else if (!RegOut) {
-        //
-        //     --o---|    Live-out on stack.
-        //     ===____    Use MainIntv up to last use, switch to stack.
-        //
-        //     -----o|    Live-out on stack, last use after last split point.
-        //     ======     Extend MainIntv to last use, overlapping.
-        //       \____    Copy to stack interval before last split point.
-        //
-        if (BI.LastUse < LastSplitPoint)
-          To = SE->leaveIntvAfter(BI.LastUse);
-        else {
-          // The last use is after the last split point, it is probably an
-          // indirect branch.
-          To = SE->leaveIntvBefore(LastSplitPoint);
-          // Run a double interval from the split to the last use.  This makes
-          // it possible to spill the complement without affecting the indirect
-          // branch.
-          SE->overlapIntv(To, BI.LastUse);
-        }
-      }
-
-      // Paint in MainIntv liveness for this block.
-      SE->useIntv(From, To);
-      continue;
-    }
-
-    // We are now looking at a block with interference, and we know that either
-    // RegIn or RegOut is set.
-    assert(Intf.hasInterference() && (RegIn || RegOut) && "Bad invariant");
-
-    // If the live range is not live through the block, it is possible that the
-    // interference doesn't even overlap.  Deal with those cases first.  Since
-    // no copy instructions are required, we can tolerate interference starting
-    // or ending at the same instruction that kills or defines our live range.
 
-    // Live-in, killed before interference.
-    //
-    //               ~~~    Interference after kill.
-    //     |---o---x   |    Killed in block.
-    //     =========        Use MainIntv everywhere.
-    //
-    if (RegIn && !BI.LiveOut && BI.LastUse <= Intf.first()) {
-      DEBUG(dbgs() << ", live-in, killed before interference.\n");
-      SE->selectIntv(MainIntv);
-      SlotIndex To = SE->leaveIntvAfter(BI.LastUse);
-      SE->useIntv(Start, To);
-      continue;
-    }
-
-    // Live-out, defined after interference.
-    //
-    //     ~~~              Interference before def.
-    //     |   o---o---|    Defined in block.
-    //         =========    Use MainIntv everywhere.
-    //
-    if (RegOut && !BI.LiveIn && BI.FirstUse >= Intf.last()) {
-      DEBUG(dbgs() << ", live-out, defined after interference.\n");
-      SE->selectIntv(MainIntv);
-      SlotIndex From = SE->enterIntvBefore(BI.FirstUse);
-      SE->useIntv(From, Stop);
-      continue;
-    }
-
-    // The interference is now known to overlap the live range, but it may
-    // still be easy to avoid if all the interference is on one side of the
-    // uses, and we enter or leave on the stack.
-
-    // Live-out on stack, interference after last use.
-    //
-    //               ~~~    Interference after last use.
-    //     |---o---o---|    Live-out on stack.
-    //     =========____    Leave MainIntv after last use.
-    //
-    //                 ~    Interference after last use.
-    //     |---o---o--o|    Live-out on stack, late last use.
-    //     ============     Copy to stack after LSP, overlap MainIntv.
-    //            \_____    Stack interval is live-out.
-    //
-    if (!RegOut && Intf.first() > BI.LastUse.getBoundaryIndex()) {
-      assert(RegIn && "Stack-in, stack-out should already be handled");
-      if (BI.LastUse < LastSplitPoint) {
-        DEBUG(dbgs() << ", live-in, stack-out, interference after last use.\n");
-        SE->selectIntv(MainIntv);
-        SlotIndex To = SE->leaveIntvAfter(BI.LastUse);
-        assert(To <= Intf.first() && "Expected to avoid interference");
-        SE->useIntv(Start, To);
-      } else {
-        DEBUG(dbgs() << ", live-in, stack-out, avoid last split point\n");
-        SE->selectIntv(MainIntv);
-        SlotIndex To = SE->leaveIntvBefore(LastSplitPoint);
-        assert(To <= Intf.first() && "Expected to avoid interference");
-        SE->overlapIntv(To, BI.LastUse);
-        SE->useIntv(Start, To);
-      }
-      continue;
-    }
-
-    // Live-in on stack, interference before first use.
-    //
-    //     ~~~              Interference before first use.
-    //     |---o---o---|    Live-in on stack.
-    //     ____=========    Enter MainIntv before first use.
-    //
-    if (!RegIn && Intf.last() < BI.FirstUse.getBaseIndex()) {
-      assert(RegOut && "Stack-in, stack-out should already be handled");
-      DEBUG(dbgs() << ", stack-in, interference before first use.\n");
-      SE->selectIntv(MainIntv);
-      SlotIndex From = SE->enterIntvBefore(BI.FirstUse);
-      assert(From >= Intf.last() && "Expected to avoid interference");
-      SE->useIntv(From, Stop);
-      continue;
-    }
-
-    // The interference is overlapping somewhere we wanted to use MainIntv. That
-    // means we need to create a local interval that can be allocated a
-    // different register.
-    unsigned LocalIntv = SE->openIntv();
-    DEBUG(dbgs() << ", creating local interval " << LocalIntv << ".\n");
-
-    // We may be creating copies directly between MainIntv and LocalIntv,
-    // bypassing the stack interval. When we do that, we should never use the
-    // leaveIntv* methods as they define values in the stack interval. By
-    // starting from the end of the block and working our way backwards, we can
-    // get by with only enterIntv* methods.
-    //
-    // When selecting split points, we generally try to maximize the stack
-    // interval as long at it contains no uses, maximize the main interval as
-    // long as it doesn't overlap interference, and minimize the local interval
-    // that we don't know how to allocate yet.
-
-    // Handle the block exit, set Pos to the first handled slot.
-    SlotIndex Pos = BI.LastUse;
-    if (RegOut) {
-      assert(Intf.last() < LastSplitPoint && "Cannot be live-out in register");
-      // Create a snippet of MainIntv that is live-out.
-      //
-      //     ~~~        Interference overlapping uses.
-      //     --o---|    Live-out in MainIntv.
-      //     ----===    Switch from LocalIntv to MainIntv after interference.
-      //
-      SE->selectIntv(MainIntv);
-      Pos = SE->enterIntvAfter(Intf.last());
-      assert(Pos >= Intf.last() && "Expected to avoid interference");
-      SE->useIntv(Pos, Stop);
-      SE->selectIntv(LocalIntv);
-    } else if (BI.LiveOut) {
-      if (BI.LastUse < LastSplitPoint) {
-        // Live-out on the stack.
-        //
-        //     ~~~        Interference overlapping uses.
-        //     --o---|    Live-out on stack.
-        //     ---____    Switch from LocalIntv to stack after last use.
-        //
-        Pos = SE->leaveIntvAfter(BI.LastUse);
-      } else {
-        // Live-out on the stack, last use after last split point.
-        //
-        //     ~~~        Interference overlapping uses.
-        //     --o--o|    Live-out on stack, late use.
-        //     ------     Copy to stack before LSP, overlap LocalIntv.
-        //         \__
-        //
-        Pos = SE->leaveIntvBefore(LastSplitPoint);
-        // We need to overlap LocalIntv so it can reach LastUse.
-        SE->overlapIntv(Pos, BI.LastUse);
-      }
-    }
-
-    // When not live-out, leave Pos at LastUse. We have handled everything from
-    // Pos to Stop. Find the starting point for LocalIntv.
-    assert(SE->currentIntv() == LocalIntv && "Expecting local interval");
-
-    if (RegIn) {
-      assert(Start < Intf.first() && "Cannot be live-in with interference");
-      // Live-in in MainIntv, only use LocalIntv for interference.
-      //
-      //         ~~~    Interference overlapping uses.
-      //     |---o--    Live-in in MainIntv.
-      //     ====---    Switch to LocalIntv before interference.
-      //
-      SlotIndex Switch = SE->enterIntvBefore(std::min(Pos, Intf.first()));
-      assert(Switch <= Intf.first() && "Expected to avoid interference");
-      SE->useIntv(Switch, Pos);
-      SE->selectIntv(MainIntv);
-      SE->useIntv(Start, Switch);
-    } else {
-      // Live-in on stack, enter LocalIntv before first use.
-      //
-      //         ~~~    Interference overlapping uses.
-      //     |---o--    Live-in in MainIntv.
-      //     ____---    Reload to LocalIntv before interference.
-      //
-      // Defined in block.
-      //
-      //         ~~~    Interference overlapping uses.
-      //     |   o--    Defined in block.
-      //         ---    Begin LocalIntv at first use.
-      //
-      SlotIndex Switch = SE->enterIntvBefore(std::min(Pos, BI.FirstUse));
-      SE->useIntv(Switch, Pos);
-    }
+    if (RegIn && RegOut)
+      SE->splitLiveThroughBlock(BI.MBB->getNumber(),
+                                MainIntv, Intf.first(),
+                                MainIntv, Intf.last());
+    else if (RegIn)
+      SE->splitRegInBlock(BI, MainIntv, Intf.first());
+    else
+      SE->splitRegOutBlock(BI, MainIntv, Intf.last());
   }
 
   // Handle live-through blocks.
-  SE->selectIntv(MainIntv);
   for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) {
     unsigned Number = Cand.ActiveBlocks[i];
     bool RegIn  = LiveBundles[Bundles->getBundle(Number, 0)];
     bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)];
-    DEBUG(dbgs() << "Live through BB#" << Number << '\n');
-    if (RegIn && RegOut) {
-      Intf.moveToBlock(Number);
-      if (!Intf.hasInterference()) {
-        SE->useIntv(Indexes->getMBBStartIdx(Number),
-                    Indexes->getMBBEndIdx(Number));
-        continue;
-      }
-    }
-    MachineBasicBlock *MBB = MF->getBlockNumbered(Number);
-    if (RegIn)
-      SE->leaveIntvAtTop(*MBB);
-    if (RegOut)
-      SE->enterIntvAtEnd(*MBB);
+    if (!RegIn && !RegOut)
+      continue;
+    Intf.moveToBlock(Number);
+    SE->splitLiveThroughBlock(Number, RegIn  ? MainIntv : 0, Intf.first(),
+                                      RegOut ? MainIntv : 0, Intf.last());
   }
 
   ++NumGlobalSplits;
index a0952a0866b51d63d38a25a45bdba8424c06827c..d875f18754eef93710b79bc13790e2da95a4df41 100644 (file)
@@ -1124,3 +1124,262 @@ void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) {
   }
   finish();
 }
+
+
+//===----------------------------------------------------------------------===//
+//                    Global Live Range Splitting Support
+//===----------------------------------------------------------------------===//
+
+// These methods support a method of global live range splitting that uses a
+// global algorithm to decide intervals for CFG edges. They will insert split
+// points and color intervals in basic blocks while avoiding interference.
+//
+// Note that splitSingleBlock is also useful for blocks where both CFG edges
+// are on the stack.
+
+void SplitEditor::splitLiveThroughBlock(unsigned MBBNum,
+                                        unsigned IntvIn, SlotIndex LeaveBefore,
+                                        unsigned IntvOut, SlotIndex EnterAfter){
+  SlotIndex Start, Stop;
+  tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(MBBNum);
+
+  DEBUG(dbgs() << "BB#" << MBBNum << " [" << Start << ';' << Stop
+               << ") intf " << LeaveBefore << '-' << EnterAfter
+               << ", live-through " << IntvIn << " -> " << IntvOut);
+
+  assert((IntvIn || IntvOut) && "Use splitSingleBlock for isolated blocks");
+
+  if (!IntvOut) {
+    DEBUG(dbgs() << ", spill on entry.\n");
+    //
+    //        <<<<<<<<<    Possible LeaveBefore interference.
+    //    |-----------|    Live through.
+    //    -____________    Spill on entry.
+    //
+    selectIntv(IntvIn);
+    MachineBasicBlock *MBB = VRM.getMachineFunction().getBlockNumbered(MBBNum);
+    SlotIndex Idx = leaveIntvAtTop(*MBB);
+    assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference");
+    (void)Idx;
+    return;
+  }
+
+  if (!IntvIn) {
+    DEBUG(dbgs() << ", reload on exit.\n");
+    //
+    //    >>>>>>>          Possible EnterAfter interference.
+    //    |-----------|    Live through.
+    //    ___________--    Reload on exit.
+    //
+    selectIntv(IntvOut);
+    MachineBasicBlock *MBB = VRM.getMachineFunction().getBlockNumbered(MBBNum);
+    SlotIndex Idx = enterIntvAtEnd(*MBB);
+    assert((!EnterAfter || Idx >= EnterAfter) && "Interference");
+    (void)Idx;
+    return;
+  }
+
+  if (IntvIn == IntvOut && !LeaveBefore && !EnterAfter) {
+    DEBUG(dbgs() << ", straight through.\n");
+    //
+    //    |-----------|    Live through.
+    //    -------------    Straight through, same intv, no interference.
+    //
+    selectIntv(IntvOut);
+    useIntv(Start, Stop);
+    return;
+  }
+
+  // We cannot legally insert splits after LSP.
+  SlotIndex LSP = SA.getLastSplitPoint(MBBNum);
+
+  if (IntvIn != IntvOut && (!LeaveBefore || !EnterAfter ||
+                  LeaveBefore.getBaseIndex() > EnterAfter.getBoundaryIndex())) {
+    DEBUG(dbgs() << ", switch avoiding interference.\n");
+    //
+    //    >>>>     <<<<    Non-overlapping EnterAfter/LeaveBefore interference.
+    //    |-----------|    Live through.
+    //    ------=======    Switch intervals between interference.
+    //
+    SlotIndex Cut = (LeaveBefore && LeaveBefore < LSP) ? LeaveBefore : LSP;
+    selectIntv(IntvOut);
+    SlotIndex Idx = enterIntvBefore(Cut);
+    useIntv(Idx, Stop);
+    selectIntv(IntvIn);
+    useIntv(Start, Idx);
+    assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference");
+    assert((!EnterAfter || Idx >= EnterAfter) && "Interference");
+    return;
+  }
+
+  DEBUG(dbgs() << ", create local intv for interference.\n");
+  //
+  //    >>><><><><<<<    Overlapping EnterAfter/LeaveBefore interference.
+  //    |-----------|    Live through.
+  //    ==---------==    Switch intervals before/after interference.
+  //
+  assert(LeaveBefore <= EnterAfter && "Missed case");
+
+  selectIntv(IntvOut);
+  SlotIndex Idx = enterIntvAfter(EnterAfter);
+  useIntv(Idx, Stop);
+  assert((!EnterAfter || Idx >= EnterAfter) && "Interference");
+
+  selectIntv(IntvIn);
+  Idx = leaveIntvBefore(LeaveBefore);
+  useIntv(Start, Idx);
+  assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference");
+}
+
+
+void SplitEditor::splitRegInBlock(const SplitAnalysis::BlockInfo &BI,
+                                  unsigned IntvIn, SlotIndex LeaveBefore) {
+  SlotIndex Start, Stop;
+  tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB);
+
+  DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " [" << Start << ';' << Stop
+               << "), uses " << BI.FirstUse << '-' << BI.LastUse
+               << ", reg-in " << IntvIn << ", leave before " << LeaveBefore
+               << (BI.LiveOut ? ", stack-out" : ", killed in block"));
+
+  assert(IntvIn && "Must have register in");
+  assert(BI.LiveIn && "Must be live-in");
+  assert((!LeaveBefore || LeaveBefore > Start) && "Bad interference");
+
+  if (!BI.LiveOut && (!LeaveBefore || LeaveBefore >= BI.LastUse)) {
+    DEBUG(dbgs() << " before interference.\n");
+    //
+    //               <<<    Interference after kill.
+    //     |---o---x   |    Killed in block.
+    //     =========        Use IntvIn everywhere.
+    //
+    selectIntv(IntvIn);
+    useIntv(Start, BI.LastUse);
+    return;
+  }
+
+  SlotIndex LSP = SA.getLastSplitPoint(BI.MBB->getNumber());
+
+  if (!LeaveBefore || LeaveBefore > BI.LastUse.getBoundaryIndex()) {
+    //
+    //               <<<    Possible interference after last use.
+    //     |---o---o---|    Live-out on stack.
+    //     =========____    Leave IntvIn after last use.
+    //
+    //                 <    Interference after last use.
+    //     |---o---o--o|    Live-out on stack, late last use.
+    //     ============     Copy to stack after LSP, overlap IntvIn.
+    //            \_____    Stack interval is live-out.
+    //
+    if (BI.LastUse < LSP) {
+      DEBUG(dbgs() << ", spill after last use before interference.\n");
+      selectIntv(IntvIn);
+      SlotIndex Idx = leaveIntvAfter(BI.LastUse);
+      useIntv(Start, Idx);
+      assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference");
+    } else {
+      DEBUG(dbgs() << ", spill before last split point.\n");
+      selectIntv(IntvIn);
+      SlotIndex Idx = leaveIntvAfter(LSP);
+      overlapIntv(Idx, BI.LastUse);
+      useIntv(Start, Idx);
+      assert((!LeaveBefore || Idx <= LeaveBefore) && "Interference");
+    }
+    return;
+  }
+
+  // The interference is overlapping somewhere we wanted to use IntvIn. That
+  // means we need to create a local interval that can be allocated a
+  // different register.
+  unsigned LocalIntv = openIntv();
+  DEBUG(dbgs() << ", creating local interval " << LocalIntv << ".\n");
+
+  if (!BI.LiveOut || BI.LastUse < LSP) {
+    //
+    //           <<<<<<<    Interference overlapping uses.
+    //     |---o---o---|    Live-out on stack.
+    //     =====----____    Leave IntvIn before interference, then spill.
+    //
+    SlotIndex To = leaveIntvAfter(BI.LastUse);
+    SlotIndex From = enterIntvBefore(LeaveBefore);
+    useIntv(From, To);
+    selectIntv(IntvIn);
+    useIntv(Start, From);
+    assert((!LeaveBefore || From <= LeaveBefore) && "Interference");
+    return;
+  }
+
+  //           <<<<<<<    Interference overlapping uses.
+  //     |---o---o--o|    Live-out on stack, late last use.
+  //     =====-------     Copy to stack before LSP, overlap LocalIntv.
+  //            \_____    Stack interval is live-out.
+  //
+  SlotIndex To = leaveIntvBefore(LSP);
+  overlapIntv(To, BI.LastUse);
+  SlotIndex From = enterIntvBefore(std::min(To, LeaveBefore));
+  useIntv(From, To);
+  selectIntv(IntvIn);
+  useIntv(Start, From);
+  assert((!LeaveBefore || From <= LeaveBefore) && "Interference");
+}
+
+void SplitEditor::splitRegOutBlock(const SplitAnalysis::BlockInfo &BI,
+                                   unsigned IntvOut, SlotIndex EnterAfter) {
+  SlotIndex Start, Stop;
+  tie(Start, Stop) = LIS.getSlotIndexes()->getMBBRange(BI.MBB);
+
+  DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " [" << Start << ';' << Stop
+               << "), uses " << BI.FirstUse << '-' << BI.LastUse
+               << ", reg-out " << IntvOut << ", enter after " << EnterAfter
+               << (BI.LiveIn ? ", stack-in" : ", defined in block"));
+
+  SlotIndex LSP = SA.getLastSplitPoint(BI.MBB->getNumber());
+
+  assert(IntvOut && "Must have register out");
+  assert(BI.LiveOut && "Must be live-out");
+  assert((!EnterAfter || EnterAfter < LSP) && "Bad interference");
+
+  if (!BI.LiveIn && (!EnterAfter || EnterAfter <= BI.FirstUse)) {
+    DEBUG(dbgs() << " after interference.\n");
+    //
+    //    >>>>             Interference before def.
+    //    |   o---o---|    Defined in block.
+    //        =========    Use IntvOut everywhere.
+    //
+    selectIntv(IntvOut);
+    useIntv(BI.FirstUse, Stop);
+    return;
+  }
+
+  if (!EnterAfter || EnterAfter < BI.FirstUse.getBaseIndex()) {
+    DEBUG(dbgs() << ", reload after interference.\n");
+    //
+    //    >>>>             Interference before def.
+    //    |---o---o---|    Live-through, stack-in.
+    //    ____=========    Enter IntvOut before first use.
+    //
+    selectIntv(IntvOut);
+    SlotIndex Idx = enterIntvBefore(std::min(LSP, BI.FirstUse));
+    useIntv(Idx, Stop);
+    assert((!EnterAfter || Idx >= EnterAfter) && "Interference");
+    return;
+  }
+
+  // The interference is overlapping somewhere we wanted to use IntvOut. That
+  // means we need to create a local interval that can be allocated a
+  // different register.
+  DEBUG(dbgs() << ", interference overlaps uses.\n");
+  //
+  //    >>>>>>>          Interference overlapping uses.
+  //    |---o---o---|    Live-through, stack-in.
+  //    ____---======    Create local interval for interference range.
+  //
+  selectIntv(IntvOut);
+  SlotIndex Idx = enterIntvAfter(EnterAfter);
+  useIntv(Idx, Stop);
+  assert((!EnterAfter || Idx >= EnterAfter) && "Interference");
+
+  openIntv();
+  SlotIndex From = enterIntvBefore(std::min(Idx, BI.FirstUse));
+  useIntv(From, Idx);
+}
index a9ccf40be2d51ee5c157a851caa601ca5b9ec14d..7948b725f85684a8e84ada19fff2577af3bdf330 100644 (file)
@@ -426,6 +426,42 @@ public:
   /// splitSingleBlocks - Split CurLI into a separate live interval inside each
   /// basic block in Blocks.
   void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks);
+
+  /// splitLiveThroughBlock - Split CurLI in the given block such that it
+  /// enters the block in IntvIn and leaves it in IntvOut. There may be uses in
+  /// the block, but they will be ignored when placing split points.
+  ///
+  /// @param MBBNum      Block number.
+  /// @param IntvIn      Interval index entering the block.
+  /// @param LeaveBefore When set, leave IntvIn before this point.
+  /// @param IntvOut     Interval index leaving the block.
+  /// @param EnterAfter  When set, enter IntvOut after this point.
+  void splitLiveThroughBlock(unsigned MBBNum,
+                             unsigned IntvIn, SlotIndex LeaveBefore,
+                             unsigned IntvOut, SlotIndex EnterAfter);
+
+  /// splitRegInBlock - Split CurLI in the given block such that it enters the
+  /// block in IntvIn and leaves it on the stack (or not at all). Split points
+  /// are placed in a way that avoids putting uses in the stack interval. This
+  /// may require creating a local interval when there is interference.
+  ///
+  /// @param BI          Block descriptor.
+  /// @param IntvIn      Interval index entering the block. Not 0.
+  /// @param LeaveBefore When set, leave IntvIn before this point.
+  void splitRegInBlock(const SplitAnalysis::BlockInfo &BI,
+                       unsigned IntvIn, SlotIndex LeaveBefore);
+
+  /// splitRegOutBlock - Split CurLI in the given block such that it enters the
+  /// block on the stack (or isn't live-in at all) and leaves it in IntvOut.
+  /// Split points are placed to avoid interference and such that the uses are
+  /// not in the stack interval. This may require creating a local interval
+  /// when there is interference.
+  ///
+  /// @param BI          Block descriptor.
+  /// @param IntvOut     Interval index leaving the block.
+  /// @param EnterAfter  When set, enter IntvOut after this point.
+  void splitRegOutBlock(const SplitAnalysis::BlockInfo &BI,
+                        unsigned IntvOut, SlotIndex EnterAfter);
 };
 
 }