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

Owen Anderson resistor at mac.com
Sun Dec 28 13:48:50 PST 2008


Author: resistor
Date: Sun Dec 28 15:48:48 2008
New Revision: 61458

URL: http://llvm.org/viewvc/llvm-project?rev=61458&view=rev
Log:
Add prototype code for recomputing a live interval's ranges and valnos through recursive phi construction.

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=61458&r1=61457&r2=61458&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp (original)
+++ llvm/trunk/lib/CodeGen/PreAllocSplitting.cpp Sun Dec 28 15:48:48 2008
@@ -171,7 +171,15 @@
                             int& SS,
                             SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
     void RenumberValno(VNInfo* VN);
-  };
+    void ReconstructLiveInterval(LiveInterval* LI);
+    VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator use,
+                                   LiveInterval* LI,
+            DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
+            DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
+                                      DenseMap<MachineInstr*, VNInfo*>& NewVNs,
+                                DenseMap<MachineBasicBlock*, VNInfo*>& Visited,
+                                               bool toplevel = false);
+};
 } // end anonymous namespace
 
 char PreAllocSplitting::ID = 0;
@@ -577,6 +585,257 @@
   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(
+                                                MachineBasicBlock::iterator use,
+                                                               LiveInterval* LI,
+             DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
+             DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
+                                       DenseMap<MachineInstr*, VNInfo*>& NewVNs,
+                                 DenseMap<MachineBasicBlock*, VNInfo*>& Visited,
+                                                        bool toplevel) {
+  // Return memoized result if it's available.
+  if (Visited.count(use->getParent()))
+    return Visited[use->getParent()];
+  
+  typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> > RegMap;
+  
+  // Check if our block contains any uses or defs.
+  bool ContainsDefs = Defs.count(use->getParent());
+  bool ContainsUses = Uses.count(use->getParent());
+  
+  VNInfo* ret = 0;
+  
+  // Enumerate the cases of use/def contaning blocks.
+  if (!ContainsDefs && !ContainsUses) {
+  Fallback:
+    // NOTE: Because this is the fallback case from other cases, we do NOT
+    // assume that we are not at toplevel here.
+    
+    // If there are no uses or defs between our starting point and the beginning
+    // of the block, then recursive perform phi construction on our predecessors
+    MachineBasicBlock* MBB = use->getParent();
+    DenseMap<MachineBasicBlock*, VNInfo*> IncomingVNs;
+    for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
+         PE = MBB->pred_end(); PI != PE; ++PI) {
+      VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), LI, Defs, Uses,
+                                                NewVNs, Visited, false);
+      IncomingVNs[*PI] = Incoming;
+    }
+    
+    // If only one VNInfo came back from our predecessors, just use that one...
+    if (IncomingVNs.size() == 1) {
+      ret = IncomingVNs.begin()->second;
+      unsigned StartIndex = LIs->getMBBStartIdx(use->getParent());
+      unsigned EndIndex = 0;
+      if (toplevel) {
+        EndIndex = LIs->getInstructionIndex(use);
+        EndIndex = LiveIntervals::getUseIndex(EndIndex);
+      } else
+        EndIndex = LIs->getMBBEndIdx(use->getParent());
+      
+      LI->addRange(LiveRange(StartIndex, EndIndex, ret));
+    } else {
+      // Otherwise, merge the incoming VNInfos with a phi join.  Create a new
+      // VNInfo to represent the joined value.
+      for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I =
+           IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) {
+        I->second->hasPHIKill = true;
+        unsigned KillIndex = LIs->getMBBEndIdx(I->first);
+        LI->addKill(I->second, KillIndex);
+      }
+      
+      unsigned StartIndex = LIs->getMBBStartIdx(use->getParent());
+      unsigned EndIndex = 0;
+      if (toplevel) {
+        EndIndex = LIs->getInstructionIndex(use);
+        EndIndex = LiveIntervals::getUseIndex(EndIndex);
+      } else
+        EndIndex = LIs->getMBBEndIdx(use->getParent());
+      ret = LI->getNextValue(StartIndex, /*FIXME*/ 0,
+                             LIs->getVNInfoAllocator());
+      LI->addRange(LiveRange(StartIndex, EndIndex, ret));
+    }
+  } else if (ContainsDefs && !ContainsUses) {
+    SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[use->getParent()];
+
+    // Search for the def in this block.  If we don't find it before the
+    // instruction we care about, go to the fallback case.  Note that that
+    // should never happen: this cannot be a toplevel block, so use should
+    // always be an end() iterator.
+    assert(use == use->getParent()->end() && "No use marked in toplevel block");
+    
+    MachineBasicBlock::iterator walker = use;
+    --walker;
+    while (walker != use->getParent()->begin())
+      if (BlockDefs.count(walker)) {
+        break;
+      } else
+        --walker;
+    
+    // Once we've found it, extend its VNInfo to our instruction.
+    unsigned DefIndex = LIs->getInstructionIndex(walker);
+    DefIndex = LiveIntervals::getDefIndex(DefIndex);
+    unsigned EndIndex = LIs->getMBBEndIdx(use->getParent());
+    
+    ret = NewVNs[walker];
+    LI->addRange(LiveRange(DefIndex, EndIndex, ret));
+  } else if (!ContainsDefs && ContainsUses) {
+    SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[use->getParent()];
+    
+    // Search for the use in this block that precedes the instruction we care 
+    // about, going to the fallback case if we don't find it.
+    
+    if (use == use->getParent()->begin())
+      goto Fallback;
+    
+    MachineBasicBlock::iterator walker = use;
+    --walker;
+    bool found = false;
+    while (walker != use->getParent()->begin())
+      if (BlockUses.count(walker)) {
+        found = true;
+        break;
+      } else
+        --walker;
+        
+    // Must check begin() too.
+    if (!found)
+      if (BlockUses.count(walker))
+        found = true;
+      else
+        goto Fallback;
+    
+    unsigned UseIndex = LIs->getInstructionIndex(walker);
+    UseIndex = LiveIntervals::getUseIndex(UseIndex);
+    unsigned EndIndex = 0;
+    if (toplevel) {
+      EndIndex = LIs->getInstructionIndex(walker);
+      EndIndex = LiveIntervals::getUseIndex(EndIndex);
+    } else
+      EndIndex = LIs->getMBBEndIdx(use->getParent());
+
+    // Now, recursively phi construct the VNInfo for the use we found,
+    // and then extend it to include the instruction we care about
+    ret = PerformPHIConstruction(walker, LI, Defs, Uses,
+                                 NewVNs, Visited, false);
+    
+    // FIXME: Need to set kills properly for inter-block stuff.
+    if (toplevel) {
+      if (LI->isKill(ret, UseIndex)) LI->removeKill(ret, UseIndex);
+      LI->addKill(ret, EndIndex);
+    }
+    
+    LI->addRange(LiveRange(UseIndex, EndIndex, ret));
+  } else if (ContainsDefs && ContainsUses){
+    SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[use->getParent()];
+    SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[use->getParent()];
+    
+    // This case is basically a merging of the two preceding case, with the
+    // special note that checking for defs must take precedence over checking
+    // for uses, because of two-address instructions.
+    
+    if (use == use->getParent()->begin())
+      goto Fallback;
+    
+    MachineBasicBlock::iterator walker = use;
+    --walker;
+    bool foundDef = false;
+    bool foundUse = false;
+    while (walker != use->getParent()->begin())
+      if (BlockDefs.count(walker)) {
+        foundDef = true;
+        break;
+      } else if (BlockUses.count(walker)) {
+        foundUse = true;
+        break;
+      } else
+        --walker;
+        
+    // Must check begin() too.
+    if (!foundDef && !foundUse)
+      if (BlockDefs.count(walker))
+        foundDef = true;
+      else if (BlockUses.count(walker))
+        foundUse = true;
+      else
+        goto Fallback;
+      
+    unsigned StartIndex = LIs->getInstructionIndex(walker);
+    StartIndex = foundDef ? LiveIntervals::getDefIndex(StartIndex) :
+                            LiveIntervals::getUseIndex(StartIndex);
+    unsigned EndIndex = 0;
+    if (toplevel) {
+      EndIndex = LIs->getInstructionIndex(walker);
+      EndIndex = LiveIntervals::getUseIndex(EndIndex);
+    } else
+      EndIndex = LIs->getMBBEndIdx(use->getParent());
+
+    if (foundDef)
+      ret = NewVNs[walker];
+    else
+      ret = PerformPHIConstruction(walker, LI, Defs, Uses,
+                                   NewVNs, Visited, false);
+
+    // FIXME: Need to set kills properly for inter-block stuff.
+    if (toplevel) {
+      if (foundUse && LI->isKill(ret, StartIndex))
+        LI->removeKill(ret, StartIndex);
+      LI->addKill(ret, EndIndex);
+    }
+
+    LI->addRange(LiveRange(StartIndex, EndIndex, ret));
+  }
+  
+  // Memoize results so we don't have to recompute them.
+  if (!toplevel) Visited[use->getParent()] = ret;
+  
+  return ret;
+}
+
+/// ReconstructLiveInterval - Recompute a live interval from scratch.
+void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) {
+  BumpPtrAllocator& Alloc = LIs->getVNInfoAllocator();
+  
+  // Clear the old ranges and valnos;
+  LI->clear();
+  
+  // Cache the uses and defs of the register
+  typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> > RegMap;
+  RegMap Defs, Uses;
+  
+  // Keep track of the new VNs we're creating.
+  DenseMap<MachineInstr*, VNInfo*> NewVNs;
+  SmallPtrSet<VNInfo*, 2> PhiVNs;
+  
+  // Cache defs, and create a new VNInfo for each def.
+  for (MachineRegisterInfo::def_iterator DI = MRI->def_begin(LI->reg),
+       DE = MRI->def_end(); DI != DE; ++DI) {
+    Defs[(*DI).getParent()].insert(&*DI);
+    
+    unsigned DefIdx = LIs->getInstructionIndex(&*DI);
+    DefIdx = LiveIntervals::getDefIndex(DefIdx);
+    
+    VNInfo* NewVN = LI->getNextValue(DefIdx, /*FIXME*/ 0, Alloc);
+    NewVNs[&*DI] = NewVN;
+  }
+  
+  // Cache uses as a separate pass from actually processing them.
+  for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg),
+       UE = MRI->use_end(); UI != UE; ++UI)
+    Uses[(*UI).getParent()].insert(&*UI);
+    
+  // Now, actually process every use and use a phi construction algorithm
+  // to walk from it to its reaching definitions, building VNInfos along
+  // the way.
+  for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(LI->reg),
+       UE = MRI->use_end(); UI != UE; ++UI) {
+    DenseMap<MachineBasicBlock*, VNInfo*> Visited;
+    PerformPHIConstruction(&*UI, LI, Defs, Uses, NewVNs, Visited, true); 
+  }
+}
+
 /// ShrinkWrapLiveInterval - Recursively traverse the predecessor
 /// chain to find the new 'kills' and shrink wrap the live interval to the
 /// new kill indices.





More information about the llvm-commits mailing list