[llvm-commits] [llvm] r135307 - in /llvm/trunk: include/llvm/CodeGen/SlotIndexes.h lib/CodeGen/RegAllocGreedy.cpp lib/CodeGen/SplitKit.cpp lib/CodeGen/SplitKit.h

Jakob Stoklund Olesen stoklund at 2pi.dk
Fri Jul 15 14:47:57 PDT 2011


Author: stoklund
Date: Fri Jul 15 16:47:57 2011
New Revision: 135307

URL: http://llvm.org/viewvc/llvm-project?rev=135307&view=rev
Log:
Extract parts of RAGreedy::splitAroundRegion as SplitKit methods.

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.

Modified:
    llvm/trunk/include/llvm/CodeGen/SlotIndexes.h
    llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp
    llvm/trunk/lib/CodeGen/SplitKit.cpp
    llvm/trunk/lib/CodeGen/SplitKit.h

Modified: llvm/trunk/include/llvm/CodeGen/SlotIndexes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SlotIndexes.h?rev=135307&r1=135306&r2=135307&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SlotIndexes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Fri Jul 15 16:47:57 2011
@@ -140,6 +140,9 @@
       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;
 

Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=135307&r1=135306&r2=135307&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Fri Jul 15 16:47:57 2011
@@ -870,16 +870,6 @@
                   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 @@
       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;

Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=135307&r1=135306&r2=135307&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SplitKit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SplitKit.cpp Fri Jul 15 16:47:57 2011
@@ -1124,3 +1124,262 @@
   }
   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);
+}

Modified: llvm/trunk/lib/CodeGen/SplitKit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=135307&r1=135306&r2=135307&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SplitKit.h (original)
+++ llvm/trunk/lib/CodeGen/SplitKit.h Fri Jul 15 16:47:57 2011
@@ -426,6 +426,42 @@
   /// 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);
 };
 
 }





More information about the llvm-commits mailing list