[llvm-commits] [llvm] r63041 - /llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp

Bill Wendling isanbard at gmail.com
Mon Jan 26 13:30:17 PST 2009


Author: void
Date: Mon Jan 26 15:30:17 2009
New Revision: 63041

URL: http://llvm.org/viewvc/llvm-project?rev=63041&view=rev
Log:
Also revert r63206

Modified:
    llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp

Modified: llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp?rev=63041&r1=63040&r2=63041&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp (original)
+++ llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp Mon Jan 26 15:30:17 2009
@@ -139,11 +139,26 @@
 
     void UpdateSpillSlotInterval(VNInfo*, unsigned, unsigned);
 
+    VNInfo* UpdateRegisterInterval(VNInfo*, unsigned, unsigned);
+
+    bool ShrinkWrapToLastUse(MachineBasicBlock*, VNInfo*,
+                             SmallVector<MachineOperand*, 4>&,
+                             SmallPtrSet<MachineInstr*, 4>&);
+
+    void ShrinkWrapLiveInterval(VNInfo*, MachineBasicBlock*, MachineBasicBlock*,
+                        MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*, 8>&,
+                DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >&,
+                  DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >&,
+                                SmallVector<MachineBasicBlock*, 4>&);
+
     bool SplitRegLiveInterval(LiveInterval*);
 
     bool SplitRegLiveIntervals(const TargetRegisterClass **,
                                SmallPtrSet<LiveInterval*, 8>&);
     
+    void RepairLiveInterval(LiveInterval* CurrLI, VNInfo* ValNo,
+                            MachineInstr* DefMI, unsigned RestoreIdx);
+    
     bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB,
                         MachineBasicBlock* BarrierMBB);
     bool Rematerialize(unsigned vreg, VNInfo* ValNo,
@@ -408,6 +423,176 @@
   }
 }
 
+/// UpdateRegisterInterval - Given the specified val# of the current live
+/// interval is being split, and the spill and restore indices, update the live
+/// interval accordingly.
+VNInfo*
+PreAllocSplitting::UpdateRegisterInterval(VNInfo *ValNo, unsigned SpillIndex,
+                                          unsigned RestoreIndex) {
+  assert(LIs->getMBBFromIndex(RestoreIndex) == BarrierMBB &&
+         "Expect restore in the barrier mbb");
+
+  SmallVector<std::pair<unsigned,unsigned>, 4> Before;
+  SmallVector<std::pair<unsigned,unsigned>, 4> After;
+  SmallVector<unsigned, 4> BeforeKills;
+  SmallVector<unsigned, 4> AfterKills;
+  SmallPtrSet<const LiveRange*, 4> Processed;
+
+  // First, let's figure out which parts of the live interval is now defined
+  // by the restore, which are defined by the original definition.
+  const LiveRange *LR = CurrLI->getLiveRangeContaining(RestoreIndex);
+  After.push_back(std::make_pair(RestoreIndex, LR->end));
+  if (CurrLI->isKill(ValNo, LR->end))
+    AfterKills.push_back(LR->end);
+
+  assert(LR->contains(SpillIndex));
+  if (SpillIndex > LR->start) {
+    Before.push_back(std::make_pair(LR->start, SpillIndex));
+    BeforeKills.push_back(SpillIndex);
+  }
+  Processed.insert(LR);
+
+  // Start from the restore mbb, figure out what part of the live interval
+  // are defined by the restore.
+  SmallVector<MachineBasicBlock*, 4> WorkList;
+  MachineBasicBlock *MBB = BarrierMBB;
+  for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+         SE = MBB->succ_end(); SI != SE; ++SI)
+    WorkList.push_back(*SI);
+
+  SmallPtrSet<MachineBasicBlock*, 4> ProcessedBlocks;
+  ProcessedBlocks.insert(MBB);
+
+  while (!WorkList.empty()) {
+    MBB = WorkList.back();
+    WorkList.pop_back();
+    unsigned Idx = LIs->getMBBStartIdx(MBB);
+    LR = CurrLI->getLiveRangeContaining(Idx);
+    if (LR && LR->valno == ValNo && !Processed.count(LR)) {
+      After.push_back(std::make_pair(LR->start, LR->end));
+      if (CurrLI->isKill(ValNo, LR->end))
+        AfterKills.push_back(LR->end);
+      Idx = LIs->getMBBEndIdx(MBB);
+      if (LR->end > Idx) {
+        // Live range extend beyond at least one mbb. Let's see what other
+        // mbbs it reaches.
+        LIs->findReachableMBBs(LR->start, LR->end, WorkList);
+      }
+      Processed.insert(LR);
+    }
+    
+    ProcessedBlocks.insert(MBB);
+    if (LR)
+      for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+            SE = MBB->succ_end(); SI != SE; ++SI)
+        if (!ProcessedBlocks.count(*SI))
+          WorkList.push_back(*SI);
+  }
+
+  for (LiveInterval::iterator I = CurrLI->begin(), E = CurrLI->end();
+       I != E; ++I) {
+    LiveRange *LR = I;
+    if (LR->valno == ValNo && !Processed.count(LR)) {
+      Before.push_back(std::make_pair(LR->start, LR->end));
+      if (CurrLI->isKill(ValNo, LR->end))
+        BeforeKills.push_back(LR->end);
+    }
+  }
+
+  // Now create new val#s to represent the live ranges defined by the old def
+  // those defined by the restore.
+  unsigned AfterDef = ValNo->def;
+  MachineInstr *AfterCopy = ValNo->copy;
+  bool HasPHIKill = ValNo->hasPHIKill;
+  CurrLI->removeValNo(ValNo);
+  VNInfo *BValNo = (Before.empty())
+    ? NULL
+    : CurrLI->getNextValue(AfterDef, AfterCopy, LIs->getVNInfoAllocator());
+  if (BValNo)
+    CurrLI->addKills(BValNo, BeforeKills);
+
+  VNInfo *AValNo = (After.empty())
+    ? NULL
+    : CurrLI->getNextValue(RestoreIndex, 0, LIs->getVNInfoAllocator());
+  if (AValNo) {
+    AValNo->hasPHIKill = HasPHIKill;
+    CurrLI->addKills(AValNo, AfterKills);
+  }
+
+  for (unsigned i = 0, e = Before.size(); i != e; ++i) {
+    unsigned Start = Before[i].first;
+    unsigned End   = Before[i].second;
+    CurrLI->addRange(LiveRange(Start, End, BValNo));
+  }
+  for (unsigned i = 0, e = After.size(); i != e; ++i) {
+    unsigned Start = After[i].first;
+    unsigned End   = After[i].second;
+    CurrLI->addRange(LiveRange(Start, End, AValNo));
+  }
+  
+  return AValNo;
+}
+
+/// ShrinkWrapToLastUse - There are uses of the current live interval in the
+/// given block, shrink wrap the live interval to the last use (i.e. remove
+/// from last use to the end of the mbb). In case mbb is the where the barrier
+/// is, remove from the last use to the barrier.
+bool
+PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB, VNInfo *ValNo,
+                                       SmallVector<MachineOperand*, 4> &Uses,
+                                       SmallPtrSet<MachineInstr*, 4> &UseMIs) {
+  MachineOperand *LastMO = 0;
+  MachineInstr *LastMI = 0;
+  if (MBB != BarrierMBB && Uses.size() == 1) {
+    // Single use, no need to traverse the block. We can't assume this for the
+    // barrier bb though since the use is probably below the barrier.
+    LastMO = Uses[0];
+    LastMI = LastMO->getParent();
+  } else {
+    MachineBasicBlock::iterator MEE = MBB->begin();
+    MachineBasicBlock::iterator MII;
+    if (MBB == BarrierMBB)
+      MII = Barrier;
+    else
+      MII = MBB->end();
+    while (MII != MEE) {
+      --MII;
+      MachineInstr *UseMI = &*MII;
+      if (!UseMIs.count(UseMI))
+        continue;
+      for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) {
+        MachineOperand &MO = UseMI->getOperand(i);
+        if (MO.isReg() && MO.getReg() == CurrLI->reg) {
+          LastMO = &MO;
+          break;
+        }
+      }
+      LastMI = UseMI;
+      break;
+    }
+  }
+
+  // Cut off live range from last use (or beginning of the mbb if there
+  // are no uses in it) to the end of the mbb.
+  unsigned RangeStart, RangeEnd = LIs->getMBBEndIdx(MBB)+1;
+  if (LastMI) {
+    RangeStart = LIs->getUseIndex(LIs->getInstructionIndex(LastMI))+1;
+    assert(!LastMO->isKill() && "Last use already terminates the interval?");
+    LastMO->setIsKill();
+  } else {
+    assert(MBB == BarrierMBB);
+    RangeStart = LIs->getMBBStartIdx(MBB);
+  }
+  if (MBB == BarrierMBB)
+    RangeEnd = LIs->getUseIndex(BarrierIdx)+1;
+  CurrLI->removeRange(RangeStart, RangeEnd);
+  if (LastMI)
+    CurrLI->addKill(ValNo, RangeStart);
+
+  // Return true if the last use becomes a new kill.
+  return LastMI;
+}
+
 /// PerformPHIConstruction - From properly set up use and def lists, use a PHI
 /// construction algorithm to compute the ranges and valnos for an interval.
 VNInfo* PreAllocSplitting::PerformPHIConstruction(
@@ -705,6 +890,142 @@
   }
 }
 
+/// ShrinkWrapLiveInterval - Recursively traverse the predecessor
+/// chain to find the new 'kills' and shrink wrap the live interval to the
+/// new kill indices.
+void
+PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, MachineBasicBlock *MBB,
+                          MachineBasicBlock *SuccMBB, MachineBasicBlock *DefMBB,
+                                    SmallPtrSet<MachineBasicBlock*, 8> &Visited,
+           DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > &Uses,
+           DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > &UseMIs,
+                                  SmallVector<MachineBasicBlock*, 4> &UseMBBs) {
+  if (Visited.count(MBB))
+    return;
+
+  // If live interval is live in another successor path, then we can't process
+  // this block. But we may able to do so after all the successors have been
+  // processed.
+  if (MBB != BarrierMBB) {
+    for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
+           SE = MBB->succ_end(); SI != SE; ++SI) {
+      MachineBasicBlock *SMBB = *SI;
+      if (SMBB == SuccMBB)
+        continue;
+      if (CurrLI->liveAt(LIs->getMBBStartIdx(SMBB)))
+        return;
+    }
+  }
+
+  Visited.insert(MBB);
+
+  DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
+    UMII = Uses.find(MBB);
+  if (UMII != Uses.end()) {
+    // At least one use in this mbb, lets look for the kill.
+    DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
+      UMII2 = UseMIs.find(MBB);
+    if (ShrinkWrapToLastUse(MBB, ValNo, UMII->second, UMII2->second))
+      // Found a kill, shrink wrapping of this path ends here.
+      return;
+  } else if (MBB == DefMBB) {
+    // There are no uses after the def.
+    MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def);
+    if (UseMBBs.empty()) {
+      // The only use must be below barrier in the barrier block. It's safe to
+      // remove the def.
+      LIs->RemoveMachineInstrFromMaps(DefMI);
+      DefMI->eraseFromParent();
+      CurrLI->removeRange(ValNo->def, LIs->getMBBEndIdx(MBB)+1);
+    }
+  } else if (MBB == BarrierMBB) {
+    // Remove entire live range from start of mbb to barrier.
+    CurrLI->removeRange(LIs->getMBBStartIdx(MBB),
+                        LIs->getUseIndex(BarrierIdx)+1);
+  } else {
+    // Remove entire live range of the mbb out of the live interval.
+    CurrLI->removeRange(LIs->getMBBStartIdx(MBB), LIs->getMBBEndIdx(MBB)+1);
+  }
+
+  if (MBB == DefMBB)
+    // Reached the def mbb, stop traversing this path further.
+    return;
+
+  // Traverse the pathes up the predecessor chains further.
+  for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
+         PE = MBB->pred_end(); PI != PE; ++PI) {
+    MachineBasicBlock *Pred = *PI;
+    if (Pred == MBB)
+      continue;
+    if (Pred == DefMBB && ValNo->hasPHIKill)
+      // Pred is the def bb and the def reaches other val#s, we must
+      // allow the value to be live out of the bb.
+      continue;
+    if (!CurrLI->liveAt(LIs->getMBBEndIdx(Pred)-1))
+      return;
+    ShrinkWrapLiveInterval(ValNo, Pred, MBB, DefMBB, Visited,
+                           Uses, UseMIs, UseMBBs);
+  }
+
+  return;
+}
+
+
+void PreAllocSplitting::RepairLiveInterval(LiveInterval* CurrLI,
+                                           VNInfo* ValNo,
+                                           MachineInstr* DefMI,
+                                           unsigned RestoreIdx) {
+  // Shrink wrap the live interval by walking up the CFG and find the
+  // new kills.
+  // Now let's find all the uses of the val#.
+  DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > Uses;
+  DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > UseMIs;
+  SmallPtrSet<MachineBasicBlock*, 4> Seen;
+  SmallVector<MachineBasicBlock*, 4> UseMBBs;
+  for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(CurrLI->reg),
+         UE = MRI->use_end(); UI != UE; ++UI) {
+    MachineOperand &UseMO = UI.getOperand();
+    MachineInstr *UseMI = UseMO.getParent();
+    unsigned UseIdx = LIs->getInstructionIndex(UseMI);
+    LiveInterval::iterator ULR = CurrLI->FindLiveRangeContaining(UseIdx);
+    if (ULR->valno != ValNo)
+      continue;
+    MachineBasicBlock *UseMBB = UseMI->getParent();
+    // Remember which other mbb's use this val#.
+    if (Seen.insert(UseMBB) && UseMBB != BarrierMBB)
+      UseMBBs.push_back(UseMBB);
+    DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
+      UMII = Uses.find(UseMBB);
+    if (UMII != Uses.end()) {
+      DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
+        UMII2 = UseMIs.find(UseMBB);
+      UMII->second.push_back(&UseMO);
+      UMII2->second.insert(UseMI);
+    } else {
+      SmallVector<MachineOperand*, 4> Ops;
+      Ops.push_back(&UseMO);
+      Uses.insert(std::make_pair(UseMBB, Ops));
+      SmallPtrSet<MachineInstr*, 4> MIs;
+      MIs.insert(UseMI);
+      UseMIs.insert(std::make_pair(UseMBB, MIs));
+    }
+  }
+
+  // Walk up the predecessor chains.
+  SmallPtrSet<MachineBasicBlock*, 8> Visited;
+  ShrinkWrapLiveInterval(ValNo, BarrierMBB, NULL, DefMI->getParent(), Visited,
+                         Uses, UseMIs, UseMBBs);
+
+  // Remove live range from barrier to the restore. FIXME: Find a better
+  // point to re-start the live interval.
+  VNInfo* AfterValNo = UpdateRegisterInterval(ValNo,
+                                              LIs->getUseIndex(BarrierIdx)+1,
+                                              LIs->getDefIndex(RestoreIdx));
+  
+  // Attempt to renumber the new valno into a new vreg.
+  RenumberValno(AfterValNo);
+}
+
 /// RenumberValno - Split the given valno out into a new vreg, allowing it to
 /// be allocated to a different register.  This function creates a new vreg,
 /// copies the valno and its live ranges over to the new vreg's interval,





More information about the llvm-commits mailing list