[llvm-commits] [llvm] r60588 - /llvm/trunk/lib/Transforms/Scalar/GVN.cpp

Chris Lattner sabre at nondot.org
Thu Dec 4 23:49:08 PST 2008


Author: lattner
Date: Fri Dec  5 01:49:08 2008
New Revision: 60588

URL: http://llvm.org/viewvc/llvm-project?rev=60588&view=rev
Log:
Make IsValueFullyAvailableInBlock safe.

Modified:
    llvm/trunk/lib/Transforms/Scalar/GVN.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/GVN.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/GVN.cpp?rev=60588&r1=60587&r2=60588&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/GVN.cpp Fri Dec  5 01:49:08 2008
@@ -1,4 +1,4 @@
-//===- GVN.cpp - Eliminate redundant values and loads ------------===//
+//===- GVN.cpp - Eliminate redundant values and loads ---------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -47,7 +47,7 @@
 
 static cl::opt<bool> EnablePRE("enable-pre",
                                cl::init(true), cl::Hidden);
-cl::opt<bool> EnableLoadPRE("enable-load-pre");
+cl::opt<bool> EnableLoadPRE("enable-load-pre"/*, cl::init(true)*/);
 
 //===----------------------------------------------------------------------===//
 //                         ValueTable Class
@@ -867,34 +867,79 @@
 
 /// IsValueFullyAvailableInBlock - Return true if we can prove that the value
 /// we're analyzing is fully available in the specified block.  As we go, keep
-/// track of which blocks we know it is fully alive or not in
-/// FullyAvailableBlocks.
+/// track of which blocks we know are fully alive in FullyAvailableBlocks.  This
+/// map is actually a tri-state map with the following values:
+///   0) we know the block *is not* fully available.
+///   1) we know the block *is* fully available.
+///   2) we do not know whether the block is fully available or not, but we are
+///      currently speculating that it will be.
+///   3) we are speculating for this block and have used that to speculate for
+///      other blocks.
 static bool IsValueFullyAvailableInBlock(BasicBlock *BB, 
-                            DenseMap<BasicBlock*, bool> &FullyAvailableBlocks) {
+                            DenseMap<BasicBlock*, char> &FullyAvailableBlocks) {
   // Optimistically assume that the block is fully available and check to see
   // if we already know about this block in one lookup.
-  std::pair<DenseMap<BasicBlock*, bool>::iterator, bool> IV = 
-    FullyAvailableBlocks.insert(std::make_pair(BB, true));
+  std::pair<DenseMap<BasicBlock*, char>::iterator, char> IV = 
+    FullyAvailableBlocks.insert(std::make_pair(BB, 2));
 
   // If the entry already existed for this block, return the precomputed value.
-  if (!IV.second)
-    return IV.first->second;
+  if (!IV.second) {
+    // If this is a speculative "available" value, mark it as being used for
+    // speculation of other blocks.
+    if (IV.first->second == 2)
+      IV.first->second = 3;
+    return IV.first->second != 0;
+  }
   
   // Otherwise, see if it is fully available in all predecessors.
   pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
   
   // If this block has no predecessors, it isn't live-in here.
   if (PI == PE)
-    return FullyAvailableBlocks[BB] = false;
+    goto SpeculationFailure;
   
   for (; PI != PE; ++PI)
     // If the value isn't fully available in one of our predecessors, then it
     // isn't fully available in this block either.  Undo our previous
     // optimistic assumption and bail out.
     if (!IsValueFullyAvailableInBlock(*PI, FullyAvailableBlocks))
-      return FullyAvailableBlocks[BB] = false;
+      goto SpeculationFailure;
   
   return true;
+  
+// SpeculationFailure - If we get here, we found out that this is not, after
+// all, a fully-available block.  We have a problem if we speculated on this and
+// used the speculation to mark other blocks as available.
+SpeculationFailure:
+  char &BBVal = FullyAvailableBlocks[BB];
+  
+  // If we didn't speculate on this, just return with it set to false.
+  if (BBVal == 2) {
+    BBVal = 0;
+    return false;
+  }
+
+  // If we did speculate on this value, we could have blocks set to 1 that are
+  // incorrect.  Walk the (transitive) successors of this block and mark them as
+  // 0 if set to one.
+  SmallVector<BasicBlock*, 32> BBWorklist;
+  BBWorklist.push_back(BB);
+  
+  while (!BBWorklist.empty()) {
+    BasicBlock *Entry = BBWorklist.pop_back_val();
+    // Note that this sets blocks to 0 (unavailable) if they happen to not
+    // already be in FullyAvailableBlocks.  This is safe.
+    char &EntryVal = FullyAvailableBlocks[Entry];
+    if (EntryVal == 0) continue;  // Already unavailable.
+
+    // Mark as unavailable.
+    EntryVal = 0;
+    
+    for (succ_iterator I = succ_begin(Entry), E = succ_end(Entry); I != E; ++I)
+      BBWorklist.push_back(*I);
+  }
+  
+  return false;
 }
 
 /// processNonLocalLoad - Attempt to eliminate a load whose dependencies are
@@ -1047,7 +1092,7 @@
   // that one block.
   BasicBlock *UnavailablePred = 0;
 
-  DenseMap<BasicBlock*, bool> FullyAvailableBlocks;
+  DenseMap<BasicBlock*, char> FullyAvailableBlocks;
   for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i)
     FullyAvailableBlocks[ValuesPerBlock[i].first] = true;
   for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i)
@@ -1086,11 +1131,11 @@
                 << UnavailablePred->getName() << "': " << *LI);
     return false;
   }
-
+  
   // Okay, we can eliminate this load by inserting a reload in the predecessor
   // and using PHI construction to get the value in the other predecessors, do
   // it.
-  DEBUG(cerr << "GVN REMOVING PRE LOAD: " << *LI);
+  /*DEBUG*/(cerr << "GVN REMOVING PRE LOAD: " << *LI);
   
   Value *NewLoad = new LoadInst(LoadPtr, LI->getName()+".pre", false,
                                 LI->getAlignment(),
@@ -1103,6 +1148,7 @@
   // Perform PHI construction.
   Value* v = GetValueForBlock(LI->getParent(), LI, BlockReplValues, true);
   LI->replaceAllUsesWith(v);
+  v->takeName(LI);
   toErase.push_back(LI);
   NumPRELoad++;
   return true;





More information about the llvm-commits mailing list