[llvm-commits] CVS: llvm/lib/Transforms/Scalar/SCCP.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu Jul 15 16:36:53 PDT 2004



Changes in directory llvm/lib/Transforms/Scalar:

SCCP.cpp updated: 1.95 -> 1.96

---
Log message:

This patch was contributed by Daniel Berlin!

Speed up SCCP substantially by processing overdefined values quickly.  This
patch speeds up SCCP by about 30-40% on large testcases.



---
Diffs of the changes:  (+47 -13)

Index: llvm/lib/Transforms/Scalar/SCCP.cpp
diff -u llvm/lib/Transforms/Scalar/SCCP.cpp:1.95 llvm/lib/Transforms/Scalar/SCCP.cpp:1.96
--- llvm/lib/Transforms/Scalar/SCCP.cpp:1.95	Wed Jul 14 20:50:47 2004
+++ llvm/lib/Transforms/Scalar/SCCP.cpp	Thu Jul 15 18:36:43 2004
@@ -31,6 +31,7 @@
 #include "llvm/Support/InstVisitor.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "Support/Debug.h"
+#include "Support/hash_map"
 #include "Support/Statistic.h"
 #include "Support/STLExtras.h"
 #include <algorithm>
@@ -95,9 +96,19 @@
 namespace {
 class SCCP : public FunctionPass, public InstVisitor<SCCP> {
   std::set<BasicBlock*>     BBExecutable;// The basic blocks that are executable
-  std::map<Value*, InstVal> ValueState;  // The state each value is in...
+  hash_map<Value*, InstVal> ValueState;  // The state each value is in...
 
+  // The reason for two worklists is that overdefined is the lowest state
+  // on the lattice, and moving things to overdefined as fast as possible
+  // makes SCCP converge much faster.
+  // By having a separate worklist, we accomplish this because everything
+  // possibly overdefined will become overdefined at the soonest possible
+  // point.
+  std::vector<Instruction*> OverdefinedInstWorkList;// The overdefined 
+                                                    // instruction work list
   std::vector<Instruction*> InstWorkList;// The instruction work list
+
+
   std::vector<BasicBlock*>  BBWorkList;  // The BasicBlock work list
 
   /// UsersOfOverdefinedPHIs - Keep track of any users of PHI nodes that are not
@@ -126,7 +137,7 @@
 private:
   friend class InstVisitor<SCCP>;        // Allow callbacks from visitor
 
-  // markValueOverdefined - Make a value be marked as "constant".  If the value
+  // markConstant - Make a value be marked as "constant".  If the value
   // is not already a constant, add it to the instruction work list so that 
   // the users of the instruction are updated later.
   //
@@ -140,14 +151,14 @@
     markConstant(ValueState[I], I, C);
   }
 
-  // markValueOverdefined - Make a value be marked as "overdefined". If the
-  // value is not already overdefined, add it to the instruction work list so
-  // that the users of the instruction are updated later.
-  //
+  // markOverdefined - Make a value be marked as "overdefined". If the
+  // value is not already overdefined, add it to the overdefined instruction 
+  // work list so that the users of the instruction are updated later.
+  
   inline void markOverdefined(InstVal &IV, Instruction *I) {
     if (IV.markOverdefined()) {
       DEBUG(std::cerr << "markOverdefined: " << *I);
-      InstWorkList.push_back(I);  // Only instructions go on the work list
+      OverdefinedInstWorkList.push_back(I);  // Only instructions go on the work list
     }
   }
   inline void markOverdefined(Instruction *I) {
@@ -161,7 +172,7 @@
   // Instruction object, then use this accessor to get its value from the map.
   //
   inline InstVal &getValueState(Value *V) {
-    std::map<Value*, InstVal>::iterator I = ValueState.find(V);
+    hash_map<Value*, InstVal>::iterator I = ValueState.find(V);
     if (I != ValueState.end()) return I->second;  // Common case, in the map
       
     if (Constant *CPV = dyn_cast<Constant>(V)) {  // Constants are constant
@@ -282,8 +293,26 @@
   BBExecutable.insert(F.begin());   // Basic block is executable!
   BBWorkList.push_back(F.begin());  // Add the block to the work list!
 
-  // Process the work lists until their are empty!
-  while (!BBWorkList.empty() || !InstWorkList.empty()) {
+  // Process the work lists until they are empty!
+  while (!BBWorkList.empty() || !InstWorkList.empty() || 
+	 !OverdefinedInstWorkList.empty()) {
+    // Process the instruction work list...
+    while (!OverdefinedInstWorkList.empty()) {
+      Instruction *I = OverdefinedInstWorkList.back();
+      OverdefinedInstWorkList.pop_back();
+
+      DEBUG(std::cerr << "\nPopped off OI-WL: " << I);
+      
+      // "I" got into the work list because it either made the transition from
+      // bottom to constant
+      //
+      // Anything on this worklist that is overdefined need not be visited
+      // since all of its users will have already been marked as overdefined
+      // Update all of the users of this instruction's value...
+      //
+      for_each(I->use_begin(), I->use_end(),
+	       bind_obj(this, &SCCP::OperandChangedState));
+    }
     // Process the instruction work list...
     while (!InstWorkList.empty()) {
       Instruction *I = InstWorkList.back();
@@ -292,12 +321,16 @@
       DEBUG(std::cerr << "\nPopped off I-WL: " << *I);
       
       // "I" got into the work list because it either made the transition from
-      // bottom to constant, or to Overdefined.
+      // bottom to constant
       //
+      // Anything on this worklist that is overdefined need not be visited
+      // since all of its users will have already been marked as overdefined.
       // Update all of the users of this instruction's value...
       //
-      for_each(I->use_begin(), I->use_end(),
-	       bind_obj(this, &SCCP::OperandChangedState));
+      InstVal &Ival = getValueState (I);
+      if (!Ival.isOverdefined())
+	for_each(I->use_begin(), I->use_end(),
+		 bind_obj(this, &SCCP::OperandChangedState));
     }
 
     // Process the basic block work list...
@@ -348,6 +381,7 @@
   // Reset state so that the next invocation will have empty data structures
   BBExecutable.clear();
   ValueState.clear();
+  std::vector<Instruction*>().swap(OverdefinedInstWorkList);
   std::vector<Instruction*>().swap(InstWorkList);
   std::vector<BasicBlock*>().swap(BBWorkList);
 





More information about the llvm-commits mailing list