[llvm-commits] CVS: llvm/lib/Analysis/LoadValueNumbering.cpp

Chris Lattner lattner at cs.uiuc.edu
Wed Feb 4 18:37:08 PST 2004


Changes in directory llvm/lib/Analysis:

LoadValueNumbering.cpp updated: 1.10 -> 1.11

---
Log message:

Implement optimizations for handling large basic blocks.


---
Diffs of the changes:  (+77 -29)

Index: llvm/lib/Analysis/LoadValueNumbering.cpp
diff -u llvm/lib/Analysis/LoadValueNumbering.cpp:1.10 llvm/lib/Analysis/LoadValueNumbering.cpp:1.11
--- llvm/lib/Analysis/LoadValueNumbering.cpp:1.10	Tue Nov 11 16:41:31 2003
+++ llvm/lib/Analysis/LoadValueNumbering.cpp	Wed Feb  4 18:36:43 2004
@@ -212,47 +212,95 @@
 bool LoadVN::haveEqualValueNumber(LoadInst *L1, LoadInst *L2,
                                   AliasAnalysis &AA,
                                   DominatorSet &DomSetInfo) const {
-  // Figure out which load dominates the other one.  If neither dominates the
-  // other we cannot eliminate them.
-  //
-  // FIXME: This could be enhanced to some cases with a shared dominator!
-  //
-  if (DomSetInfo.dominates(L2, L1)) 
-    std::swap(L1, L2);   // Make L1 dominate L2
-  else if (!DomSetInfo.dominates(L1, L2))
-    return false;  // Neither instruction dominates the other one...
-
-  BasicBlock *BB1 = L1->getParent(), *BB2 = L2->getParent();
-  Value *LoadAddress = L1->getOperand(0);
-
+  assert(L1 != L2 && "haveEqualValueNumber assumes differing loads!");
   assert(L1->getType() == L2->getType() &&
          "How could the same source pointer return different types?");
+  Value *LoadAddress = L1->getOperand(0);
 
   // Find out how many bytes of memory are loaded by the load instruction...
   unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(L1->getType());
 
-  // L1 now dominates L2.  Check to see if the intervening instructions between
-  // the two loads include a store or call...
-  //
-  if (BB1 == BB2) {  // In same basic block?
-    // In this degenerate case, no checking of global basic blocks has to occur
-    // just check the instructions BETWEEN L1 & L2...
+  // If the two loads are in the same basic block, just do a local analysis.
+  if (L1->getParent() == L2->getParent()) {
+    // It can be _very_ expensive to determine which instruction occurs first in
+    // the basic block if the block is large (see PR209).  For this reason,
+    // instead of figuring out which block is first, then scanning all of the
+    // instructions, we scan the instructions both ways from L1 until we find
+    // L2.  Along the way if we find a potentially modifying instruction, we
+    // kill the search.  This helps in cases where we have large blocks the have
+    // potentially modifying instructions in them which stop the search.
+
+    BasicBlock *BB = L1->getParent();
+    BasicBlock::iterator UpIt = L1, DownIt = L1; ++DownIt;
+    bool NoModifiesUp = true, NoModifiesDown = true;
+
+    // Scan up and down looking for L2, a modifying instruction, or the end of a
+    // basic block.
+    while (UpIt != BB->begin() && DownIt != BB->end()) {
+      // Scan up...
+      --UpIt;
+      if (&*UpIt == L2)
+        return NoModifiesUp;  // No instructions invalidate the loads!
+      if (NoModifiesUp)
+        NoModifiesUp &=
+          !(AA.getModRefInfo(UpIt, LoadAddress, LoadSize) & AliasAnalysis::Mod);
+
+      if (&*DownIt == L2)
+        return NoModifiesDown;
+      if (NoModifiesDown)
+        NoModifiesDown &=
+          !(AA.getModRefInfo(DownIt, LoadAddress, LoadSize)
+            & AliasAnalysis::Mod);
+      ++DownIt;
+    }
+
+    // If we got here, we ran into one end of the basic block or the other.
+    if (UpIt != BB->begin()) {
+      // If we know that the upward scan found a modifier, return false.
+      if (!NoModifiesUp) return false;
+
+      // Otherwise, continue the scan looking for a modifier or L2.
+      for (--UpIt; &*UpIt != L2; --UpIt)
+        if (AA.getModRefInfo(UpIt, LoadAddress, LoadSize) & AliasAnalysis::Mod)
+          return false;
+      return true;
+    } else {
+      // If we know that the downward scan found a modifier, return false.
+      assert(DownIt != B->end() && "Didn't find instructions??");
+      if (!NoModifiesDown) return false;
+      
+      // Otherwise, continue the scan looking for a modifier or L2.
+      for (; &*DownIt != L2; ++DownIt) {
+        if (AA.getModRefInfo(DownIt, LoadAddress, LoadSize) &AliasAnalysis::Mod)
+          return false;
+      }
+      return true;
+    }
+  } else {
+    // Figure out which load dominates the other one.  If neither dominates the
+    // other we cannot eliminate them.
     //
-    if (AA.canInstructionRangeModify(*L1, *L2, LoadAddress, LoadSize))
-      return false;   // Cannot eliminate load
+    // FIXME: This could be enhanced greatly!
+    //
+    if (DomSetInfo.dominates(L2, L1)) 
+      std::swap(L1, L2);   // Make L1 dominate L2
+    else if (!DomSetInfo.dominates(L1, L2))
+      return false;  // Neither instruction dominates the other one...
+
+    BasicBlock *BB1 = L1->getParent(), *BB2 = L2->getParent();
+    
+    // L1 now dominates L2.  Check to see if the intervening instructions
+    // between the two loads might modify the loaded location.
 
-    // No instructions invalidate the loads, they produce the same value!
-    return true;
-  } else {
-    // Make sure that there are no store instructions between L1 and the end of
-    // its basic block...
+    // Make sure that there are no modifying instructions between L1 and the end
+    // of its basic block.
     //
     if (AA.canInstructionRangeModify(*L1, *BB1->getTerminator(), LoadAddress,
                                      LoadSize))
       return false;   // Cannot eliminate load
 
-    // Make sure that there are no store instructions between the start of BB2
-    // and the second load instruction...
+    // Make sure that there are no modifying instructions between the start of
+    // BB2 and the second load instruction.
     //
     if (AA.canInstructionRangeModify(BB2->front(), *L2, LoadAddress, LoadSize))
       return false;   // Cannot eliminate load
@@ -266,7 +314,7 @@
       if (CheckForInvalidatingInst(*PI, BB1, LoadAddress, LoadSize, AA,
                                    VisitedSet))
         return false;
-
+    
     // If we passed all of these checks then we are sure that the two loads
     // produce the same value.
     return true;





More information about the llvm-commits mailing list