[llvm-commits] [llvm] r110257 - in /llvm/trunk/lib/CodeGen: InlineSpiller.cpp SplitKit.cpp SplitKit.h

Jakob Stoklund Olesen stoklund at 2pi.dk
Wed Aug 4 15:08:39 PDT 2010


Author: stoklund
Date: Wed Aug  4 17:08:39 2010
New Revision: 110257

URL: http://llvm.org/viewvc/llvm-project?rev=110257&view=rev
Log:
Checkpoint SplitKit progress.

We are now at a point where we can split around simple single-entry, single-exit
loops, although still with some bugs.

Modified:
    llvm/trunk/lib/CodeGen/InlineSpiller.cpp
    llvm/trunk/lib/CodeGen/SplitKit.cpp
    llvm/trunk/lib/CodeGen/SplitKit.h

Modified: llvm/trunk/lib/CodeGen/InlineSpiller.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/InlineSpiller.cpp?rev=110257&r1=110256&r2=110257&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/InlineSpiller.cpp (original)
+++ llvm/trunk/lib/CodeGen/InlineSpiller.cpp Wed Aug  4 17:08:39 2010
@@ -110,7 +110,8 @@
   splitAnalysis_.analyze(li_);
 
   if (const MachineLoop *loop = splitAnalysis_.getBestSplitLoop()) {
-    SplitEditor(splitAnalysis_, lis_, vrm_).splitAroundLoop(loop);
+    SplitEditor(splitAnalysis_, lis_, vrm_, *newIntervals_)
+      .splitAroundLoop(loop);
     return true;
   }
   return false;
@@ -372,7 +373,9 @@
   if (li_->empty())
     return;
 
-  stackSlot_ = vrm_.assignVirt2StackSlot(li->reg);
+  stackSlot_ = vrm_.getStackSlot(li->reg);
+  if (stackSlot_ == VirtRegMap::NO_STACK_SLOT)
+    stackSlot_ = vrm_.assignVirt2StackSlot(li->reg);
 
   // Iterate over instructions using register.
   for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(li->reg);

Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=110257&r1=110256&r2=110257&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SplitKit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SplitKit.cpp Wed Aug  4 17:08:39 2010
@@ -222,6 +222,13 @@
   for (LoopPtrSet::const_iterator I = usingLoops_.begin(),
        E = usingLoops_.end(); I != E; ++I) {
     getLoopBlocks(*I, Blocks);
+
+    // FIXME: We need an SSA updater to properly handle multiple exit blocks.
+    if (Blocks.Exits.size() > 1) {
+      DEBUG(dbgs() << "MultipleExits: " << **I);
+      continue;
+    }
+
     LoopPtrSet *LPS = 0;
     switch(analyzeLoopPeripheralUse(Blocks)) {
     case OutsideLoop:
@@ -277,11 +284,14 @@
 //===----------------------------------------------------------------------===//
 
 /// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
-SplitEditor::SplitEditor(SplitAnalysis &sa, LiveIntervals &lis, VirtRegMap &vrm)
+SplitEditor::SplitEditor(SplitAnalysis &sa, LiveIntervals &lis, VirtRegMap &vrm,
+                         std::vector<LiveInterval*> &intervals)
   : sa_(sa), lis_(lis), vrm_(vrm),
     mri_(vrm.getMachineFunction().getRegInfo()),
     tii_(*vrm.getMachineFunction().getTarget().getInstrInfo()),
-    dupli_(0), openli_(0)
+    dupli_(0), openli_(0),
+    intervals_(intervals),
+    firstInterval(intervals_.size())
 {
   const LiveInterval *curli = sa_.getCurLI();
   assert(curli && "SplitEditor created from empty SplitAnalysis");
@@ -313,44 +323,56 @@
   return VNI;
 }
 
-/// Create a new virtual register and live interval to be used by following
-/// use* and copy* calls.
-void SplitEditor::openLI() {
-  assert(!openli_ && "Previous LI not closed before openLI");
+/// Insert a COPY instruction curli -> li. Allocate a new value from li
+/// defined by the COPY. Note that rewrite() will deal with the curli
+/// register, so this function can be used to copy from any interval - openli,
+/// curli, or dupli.
+VNInfo *SplitEditor::insertCopy(LiveInterval &LI,
+                                MachineBasicBlock &MBB,
+                                MachineBasicBlock::iterator I) {
+  unsigned curli = sa_.getCurLI()->reg;
+  MachineInstr *MI = BuildMI(MBB, I, DebugLoc(), tii_.get(TargetOpcode::COPY),
+                             LI.reg).addReg(curli);
+  SlotIndex DefIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
+  return LI.getNextValue(DefIdx, MI, true, lis_.getVNInfoAllocator());
+}
+
+/// Create a new virtual register and live interval.
+void SplitEditor::openIntv() {
+  assert(!openli_ && "Previous LI not closed before openIntv");
   openli_ = createInterval();
+  intervals_.push_back(openli_);
+  liveThrough_ = false;
 }
 
-/// copyToPHI - Insert a copy to openli at the end of A, and catch it with a
-/// PHI def at the beginning of the successor B. This call is ignored if dupli
-/// is not live out of A.
-void SplitEditor::copyToPHI(MachineBasicBlock &A, MachineBasicBlock &B) {
-  assert(openli_ && "openLI not called before copyToPHI");
+/// enterIntvAtEnd - Enter openli at the end of MBB.
+/// PhiMBB is a successor inside openli where a PHI value is created.
+/// Currently, all entries must share the same PhiMBB.
+void SplitEditor::enterIntvAtEnd(MachineBasicBlock &A, MachineBasicBlock &B) {
+  assert(openli_ && "openIntv not called before enterIntvAtEnd");
 
   SlotIndex EndA = lis_.getMBBEndIdx(&A);
   VNInfo *DupVNIA = dupli_->getVNInfoAt(EndA.getPrevIndex());
   if (!DupVNIA) {
-    DEBUG(dbgs() << "  ignoring copyToPHI, dupli not live out of BB#"
+    DEBUG(dbgs() << "  ignoring enterIntvAtEnd, dupli not live out of BB#"
                  << A.getNumber() << ".\n");
     return;
   }
 
-  // Insert the COPY instruction at the end of A.
-  MachineInstr *MI = BuildMI(A, A.getFirstTerminator(), DebugLoc(),
-                                 tii_.get(TargetOpcode::COPY), dupli_->reg)
-                           .addReg(openli_->reg);
-  SlotIndex DefIdx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
-
   // Add a phi kill value and live range out of A.
-  VNInfo *VNIA = openli_->getNextValue(DefIdx, MI, true,
-                                       lis_.getVNInfoAllocator());
-  openli_->addRange(LiveRange(DefIdx, EndA, VNIA));
+  VNInfo *VNIA = insertCopy(*openli_, A, A.getFirstTerminator());
+  openli_->addRange(LiveRange(VNIA->def, EndA, VNIA));
+
+  // FIXME: If this is the only entry edge, we don't need the extra PHI value.
+  // FIXME: If there are multiple entry blocks (so not a loop), we need proper
+  // SSA update.
 
   // Now look at the start of B.
   SlotIndex StartB = lis_.getMBBStartIdx(&B);
   SlotIndex EndB = lis_.getMBBEndIdx(&B);
   LiveRange *DupB = dupli_->getLiveRangeContaining(StartB);
   if (!DupB) {
-    DEBUG(dbgs() << "  copyToPHI:, dupli not live in to BB#"
+    DEBUG(dbgs() << "  enterIntvAtEnd: dupli not live in to BB#"
                  << B.getNumber() << ".\n");
     return;
   }
@@ -375,16 +397,16 @@
 
   }
 
-  DEBUG(dbgs() << "  copyToPHI at " << DefIdx << ": " << *openli_ << '\n');
+  DEBUG(dbgs() << "  enterIntvAtEnd: " << *openli_ << '\n');
 }
 
-/// useLI - indicate that all instructions in MBB should use openli.
-void SplitEditor::useLI(const MachineBasicBlock &MBB) {
-  useLI(lis_.getMBBStartIdx(&MBB), lis_.getMBBEndIdx(&MBB));
+/// useIntv - indicate that all instructions in MBB should use openli.
+void SplitEditor::useIntv(const MachineBasicBlock &MBB) {
+  useIntv(lis_.getMBBStartIdx(&MBB), lis_.getMBBEndIdx(&MBB));
 }
 
-void SplitEditor::useLI(SlotIndex Start, SlotIndex End) {
-  assert(openli_ && "openLI not called before useLI");
+void SplitEditor::useIntv(SlotIndex Start, SlotIndex End) {
+  assert(openli_ && "openIntv not called before useIntv");
 
   // Map the dupli values from the interval into openli_
   LiveInterval::const_iterator B = dupli_->begin(), E = dupli_->end();
@@ -392,8 +414,7 @@
 
   if (I != B) {
     --I;
-    // I begins before Start, but overlaps. openli may already have a value from
-    // copyToLI.
+    // I begins before Start, but overlaps. openli may already have a value.
     if (I->end > Start && !openli_->liveAt(Start))
       openli_->addRange(LiveRange(Start, std::min(End, I->end),
                         mapValue(I->valno)));
@@ -408,24 +429,95 @@
                << '\n');
 }
 
-/// copyFromLI - Insert a copy back to dupli from openli at position I.
-SlotIndex SplitEditor::copyFromLI(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) {
-  assert(openli_ && "openLI not called before copyFromLI");
+/// leaveIntvAtTop - Leave the interval at the top of MBB.
+/// Currently, only one value can leave the interval.
+void SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) {
+  assert(openli_ && "openIntv not called before leaveIntvAtTop");
+
+  SlotIndex Start = lis_.getMBBStartIdx(&MBB);
+  LiveRange *DupLR = dupli_->getLiveRangeContaining(Start);
+
+  // Is dupli even live-in to MBB?
+  if (!DupLR) {
+    DEBUG(dbgs() << "  leaveIntvAtTop at " << Start << ": not live\n");
+    return;
+  }
+
+  // Is dupli defined by PHI at the beginning of MBB?
+  bool isPHIDef = DupLR->valno->isPHIDef() &&
+                  DupLR->valno->def.getBaseIndex() == Start;
+
+  // If MBB is using a value of dupli that was defined outside the openli range,
+  // we don't want to copy it back here.
+  if (!isPHIDef && !openli_->liveAt(DupLR->valno->def)) {
+    DEBUG(dbgs() << "  leaveIntvAtTop at " << Start
+                 << ": using external value\n");
+    liveThrough_ = true;
+    return;
+  }
 
   // Insert the COPY instruction.
-  MachineInstr *MI =
-    BuildMI(MBB, I, DebugLoc(), tii_.get(TargetOpcode::COPY), openli_->reg)
-      .addReg(dupli_->reg);
-  SlotIndex Idx = lis_.InsertMachineInstrInMaps(MI);
+  MachineInstr *MI = BuildMI(MBB, MBB.begin(), DebugLoc(),
+                             tii_.get(TargetOpcode::COPY), openli_->reg)
+                       .addReg(dupli_->reg);
+  SlotIndex Idx = lis_.InsertMachineInstrInMaps(MI).getDefIndex();
+
+  // Adjust dupli and openli values.
+  if (isPHIDef) {
+    // dupli was already a PHI on entry to MBB. Simply insert an openli PHI,
+    // and shift the dupli def down to the COPY.
+    VNInfo *VNI = openli_->getNextValue(SlotIndex(Start, true), 0, false,
+                                        lis_.getVNInfoAllocator());
+    VNI->setIsPHIDef(true);
+    openli_->addRange(LiveRange(VNI->def, Idx, VNI));
+
+    dupli_->removeRange(Start, Idx);
+    DupLR->valno->def = Idx;
+    DupLR->valno->setIsPHIDef(false);
+  } else {
+    // The dupli value was defined somewhere inside the openli range.
+    DEBUG(dbgs() << "  leaveIntvAtTop source value defined at "
+                 << DupLR->valno->def << "\n");
+    // FIXME: We may not need a PHI here if all predecessors have the same
+    // value.
+    VNInfo *VNI = openli_->getNextValue(SlotIndex(Start, true), 0, false,
+                                        lis_.getVNInfoAllocator());
+    VNI->setIsPHIDef(true);
+    openli_->addRange(LiveRange(VNI->def, Idx, VNI));
+
+    // FIXME: What if DupLR->valno is used by multiple exits? SSA Update.
+
+    // closeIntv is going to remove the superfluous live ranges.
+    DupLR->valno->def = Idx;
+    DupLR->valno->setIsPHIDef(false);
+  }
 
-  DEBUG(dbgs() << "  copyFromLI at " << Idx << ": " << *openli_ << '\n');
-  return Idx;
+  DEBUG(dbgs() << "  leaveIntvAtTop at " << Idx << ": " << *openli_ << '\n');
 }
 
-/// closeLI - Indicate that we are done editing the currently open
+/// closeIntv - Indicate that we are done editing the currently open
 /// LiveInterval, and ranges can be trimmed.
-void SplitEditor::closeLI() {
-  assert(openli_ && "openLI not called before closeLI");
+void SplitEditor::closeIntv() {
+  assert(openli_ && "openIntv not called before closeIntv");
+
+  DEBUG(dbgs() << "  closeIntv cleaning up\n");
+
+  DEBUG(dbgs() << "    dup  " << *dupli_ << '\n');
+  DEBUG(dbgs() << "    open " << *openli_ << '\n');
+
+  if (liveThrough_) {
+    DEBUG(dbgs() << "  value live through region, leaving dupli as is.\n");
+  } else {
+    // live out with copies inserted, or killed by region. Either way we need to
+    // remove the overlapping region from dupli.
+    for (LiveInterval::iterator I = openli_->begin(), E = openli_->end();
+         I != E; ++I) {
+      dupli_->removeRange(I->start, I->end);
+    }
+    // FIXME: A block branching to the entry block may also branch elsewhere
+    // curli is live. We need both openli and curli to be live in that case.
+    DEBUG(dbgs() << "    dup2 " << *dupli_ << '\n');
+  }
   openli_ = 0;
 }
 
@@ -433,6 +525,39 @@
 /// instructions using curli to use the new intervals.
 void SplitEditor::rewrite() {
   assert(!openli_ && "Previous LI not closed before rewrite");
+  const LiveInterval *curli = sa_.getCurLI();
+  for (MachineRegisterInfo::reg_iterator RI = mri_.reg_begin(curli->reg),
+       RE = mri_.reg_end(); RI != RE;) {
+    MachineOperand &MO = RI.getOperand();
+    MachineInstr *MI = MO.getParent();
+    ++RI;
+    if (MI->isDebugValue()) {
+      DEBUG(dbgs() << "Zapping " << *MI);
+      // FIXME: We can do much better with debug values.
+      MO.setReg(0);
+      continue;
+    }
+    SlotIndex Idx = lis_.getInstructionIndex(MI);
+    Idx = MO.isUse() ? Idx.getUseIndex() : Idx.getDefIndex();
+    LiveInterval *LI = dupli_;
+    for (unsigned i = firstInterval, e = intervals_.size(); i != e; ++i) {
+      LiveInterval *testli = intervals_[i];
+      if (testli->liveAt(Idx)) {
+        LI = testli;
+        break;
+      }
+    }
+    if (LI)
+      MO.setReg(LI->reg);
+    DEBUG(dbgs() << "rewrite " << Idx << '\t' << *MI);
+  }
+
+  // dupli_ goes in last, after rewriting.
+  if (dupli_)
+    intervals_.push_back(dupli_);
+
+  // FIXME: *Calculate spill weights, allocation hints, and register classes for
+  // firstInterval..
 }
 
 
@@ -450,37 +575,29 @@
   assert(CriticalExits.empty() && "Cannot break critical exits yet");
 
   // Create new live interval for the loop.
-  openLI();
+  openIntv();
 
   // Insert copies in the predecessors.
   for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Preds.begin(),
        E = Blocks.Preds.end(); I != E; ++I) {
     MachineBasicBlock &MBB = const_cast<MachineBasicBlock&>(**I);
-    copyToPHI(MBB, *Loop->getHeader());
+    enterIntvAtEnd(MBB, *Loop->getHeader());
   }
 
   // Switch all loop blocks.
   for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Loop.begin(),
        E = Blocks.Loop.end(); I != E; ++I)
-     useLI(**I);
+     useIntv(**I);
 
   // Insert back copies in the exit blocks.
   for (SplitAnalysis::BlockPtrSet::iterator I = Blocks.Exits.begin(),
        E = Blocks.Exits.end(); I != E; ++I) {
     MachineBasicBlock &MBB = const_cast<MachineBasicBlock&>(**I);
-    SlotIndex Start = lis_.getMBBStartIdx(&MBB);
-    VNInfo *VNI = sa_.getCurLI()->getVNInfoAt(Start);
-    // Only insert a back copy if curli is live and is either a phi or a value
-    // defined inside the loop.
-    if (!VNI) continue;
-    if (openli_->liveAt(VNI->def) ||
-        (VNI->isPHIDef() && VNI->def.getBaseIndex() == Start))
-      copyFromLI(MBB, MBB.begin());
+    leaveIntvAtTop(MBB);
   }
 
   // Done.
-  closeLI();
+  closeIntv();
   rewrite();
-  abort();
 }
 

Modified: llvm/trunk/lib/CodeGen/SplitKit.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=110257&r1=110256&r2=110257&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SplitKit.h (original)
+++ llvm/trunk/lib/CodeGen/SplitKit.h Wed Aug  4 17:08:39 2010
@@ -121,14 +121,14 @@
 /// SplitEditor - Edit machine code and LiveIntervals for live range
 /// splitting.
 ///
-/// 1. Create a SplitEditor from a SplitAnalysis. This will create a new
-///    LiveInterval, dupli, that is identical to SA.curli.
-/// 2. Start a new live interval with openLI.
-/// 3. Insert copies to the new interval with copyTo* and mark the ranges where
-///    it should be used with use*.
-/// 4. Insert back-copies with copyFromLI.
-/// 5. Finish the current LI with closeLI and repeat from 2.
-/// 6. Rewrite instructions with rewrite().
+/// - Create a SplitEditor from a SplitAnalysis. This will create a new
+///   LiveInterval, dupli, that is identical to SA.curli.
+/// - Start a new live interval with openIntv.
+/// - Mark the places where the new interval is entered using enterIntv*
+/// - Mark the ranges where the new interval is used with useIntv* 
+/// - Mark the places where the interval is exited with exitIntv*.
+/// - Finish the current interval with closeIntv and repeat from 2.
+/// - Rewrite instructions with rewrite().
 ///
 class SplitEditor {
   SplitAnalysis &sa_;
@@ -138,7 +138,7 @@
   const TargetInstrInfo &tii_;
 
   /// dupli_ - Created as a copy of sa_.curli_, ranges are carved out as new
-  /// intervals get added through openLI / closeLI.
+  /// intervals get added through openIntv / closeIntv.
   LiveInterval *dupli_;
 
   /// Currently open LiveInterval.
@@ -148,43 +148,60 @@
   /// register class and spill slot as curli.
   LiveInterval *createInterval();
 
-	/// valueMap_ - Map values in dupli to values in openli. These are direct 1-1
+	/// valueMap_ - Map values in dupli to values in openIntv. These are direct 1-1
 	/// mappings, and do not include values created by inserted copies.
 	DenseMap<VNInfo*,VNInfo*> valueMap_;
 
-	/// mapValue - Return the openli value that corresponds to the given dupli
+	/// mapValue - Return the openIntv value that corresponds to the given dupli
 	/// value.
-	VNInfo *mapValue(VNInfo *dupliVNI);	
+	VNInfo *mapValue(VNInfo *dupliVNI);
+
+  /// A dupli value is live through openIntv.
+  bool liveThrough_;
+
+  /// All the new intervals created for this split are added to intervals_.
+  std::vector<LiveInterval*> &intervals_;
+
+  /// The index into intervals_ of the first interval we added. There may be
+  /// others from before we got it.
+  unsigned firstInterval;
+
+  /// Insert a COPY instruction curli -> li. Allocate a new value from li
+  /// defined by the COPY
+  VNInfo *insertCopy(LiveInterval &LI,
+                     MachineBasicBlock &MBB,
+                     MachineBasicBlock::iterator I);
 
 public:
   /// Create a new SplitEditor for editing the LiveInterval analyzed by SA.
-  SplitEditor(SplitAnalysis&, LiveIntervals&, VirtRegMap&);
+  /// Newly created intervals will be appended to newIntervals.
+  SplitEditor(SplitAnalysis &SA, LiveIntervals&, VirtRegMap&,
+              std::vector<LiveInterval*> &newIntervals);
 
 	/// getAnalysis - Get the corresponding analysis.
 	SplitAnalysis &getAnalysis() { return sa_; }
 
-  /// Create a new virtual register and live interval to be used by following
-  /// use* and copy* calls.
-  void openLI();
-
-  /// copyToPHI - Insert a copy to openli at the end of A, and catch it with a
-  /// PHI def at the beginning of the successor B. This call is ignored if dupli
-  /// is not live out of A.
-  void copyToPHI(MachineBasicBlock &A, MachineBasicBlock &B);
-
-  /// useLI - indicate that all instructions in MBB should use openli.
-  void useLI(const MachineBasicBlock &MBB);
-
-  /// useLI - indicate that all instructions in range should use openli.
-  void useLI(SlotIndex Start, SlotIndex End);
-
-  /// copyFromLI - Insert a copy back to dupli from openli at position I.
-	/// This also marks the remainder of MBB as not used by openli.
-  SlotIndex copyFromLI(MachineBasicBlock &MBB, MachineBasicBlock::iterator I);
+  /// Create a new virtual register and live interval.
+  void openIntv();
+
+  /// enterIntvAtEnd - Enter openli at the end of MBB.
+  /// PhiMBB is a successor inside openli where a PHI value is created.
+  /// Currently, all entries must share the same PhiMBB.
+  void enterIntvAtEnd(MachineBasicBlock &MBB, MachineBasicBlock &PhiMBB);
+
+  /// useIntv - indicate that all instructions in MBB should use openli.
+  void useIntv(const MachineBasicBlock &MBB);
+
+  /// useIntv - indicate that all instructions in range should use openli.
+  void useIntv(SlotIndex Start, SlotIndex End);
+
+  /// leaveIntvAtTop - Leave the interval at the top of MBB.
+  /// Currently, only one value can leave the interval.
+  void leaveIntvAtTop(MachineBasicBlock &MBB);
 
-  /// closeLI - Indicate that we are done editing the currently open
+  /// closeIntv - Indicate that we are done editing the currently open
   /// LiveInterval, and ranges can be trimmed.
-  void closeLI();
+  void closeIntv();
 
   /// rewrite - after all the new live ranges have been created, rewrite
   /// instructions using curli to use the new intervals.





More information about the llvm-commits mailing list