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

Chris Lattner lattner at cs.uiuc.edu
Sat Apr 10 16:12:02 PDT 2004


Changes in directory llvm/lib/Transforms/Scalar:

GCSE.cpp updated: 1.36 -> 1.37

---
Log message:

Rewrite the GCSE pass to be *substantially* simpler, a bit more efficient,
and a bit more powerful


---
Diffs of the changes:  (+124 -217)

Index: llvm/lib/Transforms/Scalar/GCSE.cpp
diff -u llvm/lib/Transforms/Scalar/GCSE.cpp:1.36 llvm/lib/Transforms/Scalar/GCSE.cpp:1.37
--- llvm/lib/Transforms/Scalar/GCSE.cpp:1.36	Tue Mar 16 19:59:27 2004
+++ llvm/lib/Transforms/Scalar/GCSE.cpp	Sat Apr 10 16:11:11 2004
@@ -15,14 +15,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Scalar.h"
-#include "llvm/iMemory.h"
-#include "llvm/iOther.h"
+#include "llvm/BasicBlock.h"
+#include "llvm/Constant.h"
+#include "llvm/Instructions.h"
 #include "llvm/Type.h"
 #include "llvm/Analysis/Dominators.h"
 #include "llvm/Analysis/ValueNumbering.h"
-#include "llvm/Support/InstIterator.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "Support/DepthFirstIterator.h"
 #include "Support/Statistic.h"
-#include "Support/Debug.h"
 #include <algorithm>
 using namespace llvm;
 
@@ -33,23 +34,17 @@
   Statistic<> NumNonInsts   ("gcse", "Number of instructions removed due "
                              "to non-instruction values");
 
-  class GCSE : public FunctionPass {
-    std::set<Instruction*>  WorkList;
-    DominatorSet           *DomSetInfo;
-    ValueNumbering         *VN;
-  public:
+  struct GCSE : public FunctionPass {
     virtual bool runOnFunction(Function &F);
 
   private:
-    bool EliminateRedundancies(Instruction *I,std::vector<Value*> &EqualValues);
-    Instruction *EliminateCSE(Instruction *I, Instruction *Other);
-    void ReplaceInstWithInst(Instruction *First, BasicBlock::iterator SI);
+    void ReplaceInstructionWith(Instruction *I, Value *V);
 
     // This transformation requires dominator and immediate dominator info
     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
       AU.setPreservesCFG();
       AU.addRequired<DominatorSet>();
-      AU.addRequired<ImmediateDominators>();
+      AU.addRequired<DominatorTree>();
       AU.addRequired<ValueNumbering>();
     }
   };
@@ -67,226 +62,138 @@
   bool Changed = false;
 
   // Get pointers to the analysis results that we will be using...
-  DomSetInfo = &getAnalysis<DominatorSet>();
-  VN = &getAnalysis<ValueNumbering>();
+  DominatorSet &DS = getAnalysis<DominatorSet>();
+  ValueNumbering &VN = getAnalysis<ValueNumbering>();
+  DominatorTree &DT = getAnalysis<DominatorTree>();
+
+  std::vector<Value*> EqualValues;
+
+  // Traverse the CFG of the function in dominator order, so that we see each
+  // instruction after we see its operands.
+  for (df_iterator<DominatorTree::Node*> DI = df_begin(DT.getRootNode()),
+         E = df_end(DT.getRootNode()); DI != E; ++DI) {
+    BasicBlock *BB = DI->getBlock();
 
-  // Step #1: Add all instructions in the function to the worklist for
-  // processing.  All of the instructions are considered to be our
-  // subexpressions to eliminate if possible.
-  //
-  WorkList.insert(inst_begin(F), inst_end(F));
-
-  // Step #2: WorkList processing.  Iterate through all of the instructions,
-  // checking to see if there are any additionally defined subexpressions in the
-  // program.  If so, eliminate them!
-  //
-  while (!WorkList.empty()) {
-    Instruction &I = **WorkList.begin(); // Get an instruction from the worklist
-    WorkList.erase(WorkList.begin());
-
-    // If this instruction computes a value, try to fold together common
-    // instructions that compute it.
-    //
-    if (I.getType() != Type::VoidTy) {
-      std::vector<Value*> EqualValues;
-      VN->getEqualNumberNodes(&I, EqualValues);
+    // Remember which instructions we've seen in this basic block as we scan.
+    std::set<Instruction*> BlockInsts;
 
-      if (!EqualValues.empty())
-        Changed |= EliminateRedundancies(&I, EqualValues);
-    }
-  }
+    for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
+      Instruction *Inst = I++;
 
-  // When the worklist is empty, return whether or not we changed anything...
-  return Changed;
-}
-
-bool GCSE::EliminateRedundancies(Instruction *I,
-                                 std::vector<Value*> &EqualValues) {
-  // If the EqualValues set contains any non-instruction values, then we know
-  // that all of the instructions can be replaced with the non-instruction value
-  // because it is guaranteed to dominate all of the instructions in the
-  // function.  We only have to do hard work if all we have are instructions.
-  //
-  for (unsigned i = 0, e = EqualValues.size(); i != e; ++i)
-    if (!isa<Instruction>(EqualValues[i])) {
-      // Found a non-instruction.  Replace all instructions with the
-      // non-instruction.
+      // If this instruction computes a value, try to fold together common
+      // instructions that compute it.
       //
-      Value *Replacement = EqualValues[i];
-
-      // Make sure we get I as well...
-      EqualValues[i] = I;
+      if (Inst->getType() != Type::VoidTy) {
+        VN.getEqualNumberNodes(Inst, EqualValues);
 
-      // Replace all instructions with the Replacement value.
-      for (i = 0; i != e; ++i)
-        if (Instruction *I = dyn_cast<Instruction>(EqualValues[i])) {
-          // Change all users of I to use Replacement.
-          I->replaceAllUsesWith(Replacement);
-
-          if (isa<LoadInst>(I))
-            ++NumLoadRemoved; // Keep track of loads eliminated
-          if (isa<CallInst>(I))
-            ++NumCallRemoved; // Keep track of calls eliminated
-          ++NumInstRemoved;   // Keep track of number of instructions eliminated
-          ++NumNonInsts;      // Keep track of number of insts repl with values
-
-          // Erase the instruction from the program.
-          I->getParent()->getInstList().erase(I);
-          WorkList.erase(I);
+        // If this instruction computes a value that is already computed
+        // elsewhere, try to recycle the old value.
+        if (!EqualValues.empty()) {
+          if (Inst == &*BB->begin())
+            I = BB->end();
+          else {
+            I = Inst; --I;
+          }
+          
+          // First check to see if we were able to value number this instruction
+          // to a non-instruction value.  If so, prefer that value over other
+          // instructions which may compute the same thing.
+          for (unsigned i = 0, e = EqualValues.size(); i != e; ++i)
+            if (!isa<Instruction>(EqualValues[i])) {
+              ++NumNonInsts;      // Keep track of # of insts repl with values
+
+              // Change all users of Inst to use the replacement and remove it
+              // from the program.
+              ReplaceInstructionWith(Inst, EqualValues[i]);
+              Inst = 0;
+              EqualValues.clear();  // don't enter the next loop
+              break;
+            }
+
+          // If there were no non-instruction values that this instruction
+          // produces, find a dominating instruction that produces the same
+          // value.  If we find one, use it's value instead of ours.
+          for (unsigned i = 0, e = EqualValues.size(); i != e; ++i) {
+            Instruction *OtherI = cast<Instruction>(EqualValues[i]);
+            bool Dominates = false;
+            if (OtherI->getParent() == BB)
+              Dominates = BlockInsts.count(OtherI);
+            else
+              Dominates = DS.dominates(OtherI->getParent(), BB);
+
+            if (Dominates) {
+              // Okay, we found an instruction with the same value as this one
+              // and that dominates this one.  Replace this instruction with the
+              // specified one.
+              ReplaceInstructionWith(Inst, OtherI);
+              Inst = 0;
+              break;
+            }
+          }
+
+          EqualValues.clear();
+
+          if (Inst) {
+            I = Inst; ++I;             // Deleted no instructions
+          } else if (I == BB->end()) { // Deleted first instruction
+            I = BB->begin();
+          } else {                     // Deleted inst in middle of block.
+            ++I;
+          }
         }
-      
-      return true;
-    }
-  
-  // Remove duplicate entries from EqualValues...
-  std::sort(EqualValues.begin(), EqualValues.end());
-  EqualValues.erase(std::unique(EqualValues.begin(), EqualValues.end()),
-                    EqualValues.end());
 
-  // From this point on, EqualValues is logically a vector of instructions.
-  //
-  bool Changed = false;
-  EqualValues.push_back(I); // Make sure I is included...
-  while (EqualValues.size() > 1) {
-    // FIXME, this could be done better than simple iteration!
-    Instruction *Test = cast<Instruction>(EqualValues.back());
-    EqualValues.pop_back();
-    
-    for (unsigned i = 0, e = EqualValues.size(); i != e; ++i)
-      if (Instruction *Ret = EliminateCSE(Test,
-                                          cast<Instruction>(EqualValues[i]))) {
-        if (Ret == Test)          // Eliminated EqualValues[i]
-          EqualValues[i] = Test;  // Make sure that we reprocess I at some point
-        Changed = true;
-        break;
+        if (Inst)
+          BlockInsts.insert(Inst);
       }
+    }
   }
+
+  // When the worklist is empty, return whether or not we changed anything...
   return Changed;
 }
 
 
-// ReplaceInstWithInst - Destroy the instruction pointed to by SI, making all
-// uses of the instruction use First now instead.
-//
-void GCSE::ReplaceInstWithInst(Instruction *First, BasicBlock::iterator SI) {
-  Instruction &Second = *SI;
-
-  DEBUG(std::cerr << "GCSE: Substituting %" << First->getName() << " for: "
-                  << Second);
-  
-  //cerr << "DEL " << (void*)Second << Second;
-
-  // Add the first instruction back to the worklist
-  WorkList.insert(First);
-
-  // Add all uses of the second instruction to the worklist
-  for (Value::use_iterator UI = Second.use_begin(), UE = Second.use_end();
-       UI != UE; ++UI)
-    WorkList.insert(cast<Instruction>(*UI));
-    
-  // Make all users of 'Second' now use 'First'
-  Second.replaceAllUsesWith(First);
-
-  // Erase the second instruction from the program
-  Second.getParent()->getInstList().erase(SI);
-}
+void GCSE::ReplaceInstructionWith(Instruction *I, Value *V) {
+  if (isa<LoadInst>(I))
+    ++NumLoadRemoved; // Keep track of loads eliminated
+  if (isa<CallInst>(I))
+    ++NumCallRemoved; // Keep track of calls eliminated
+  ++NumInstRemoved;   // Keep track of number of insts eliminated
+
+  // If we are not replacing the instruction with a constant, we cannot do
+  // anything special.
+  if (!isa<Constant>(V)) {
+    I->replaceAllUsesWith(V);
+
+    // Erase the instruction from the program.
+    I->getParent()->getInstList().erase(I);
+    return;
+  }
 
-// EliminateCSE - The two instruction I & Other have been found to be common
-// subexpressions.  This function is responsible for eliminating one of them,
-// and for fixing the worklist to be correct.  The instruction that is preserved
-// is returned from the function if the other is eliminated, otherwise null is
-// returned.
-//
-Instruction *GCSE::EliminateCSE(Instruction *I, Instruction *Other) {
-  assert(I != Other);
+  Constant *C = cast<Constant>(V);
+  std::vector<User*> Users(I->use_begin(), I->use_end());
 
-  WorkList.erase(I);
-  WorkList.erase(Other); // Other may not actually be on the worklist anymore...
+  // Perform the replacement.
+  I->replaceAllUsesWith(C);
 
-  // Handle the easy case, where both instructions are in the same basic block
-  BasicBlock *BB1 = I->getParent(), *BB2 = Other->getParent();
-  Instruction *Ret = 0;
-
-  if (BB1 == BB2) {
-    // Eliminate the second occurring instruction.  Add all uses of the second
-    // instruction to the worklist.
-    //
-    // Scan the basic block looking for the "first" instruction
-    BasicBlock::iterator BI = BB1->begin();
-    while (&*BI != I && &*BI != Other) {
-      ++BI;
-      assert(BI != BB1->end() && "Instructions not found in parent BB!");
+  // Erase the instruction from the program.
+  I->getParent()->getInstList().erase(I);
+  
+  // Check each user to see if we can constant fold it.
+  while (!Users.empty()) {
+    Instruction *U = cast<Instruction>(Users.back());
+    Users.pop_back();
+
+    if (Constant *C = ConstantFoldInstruction(U)) {
+      ReplaceInstructionWith(U, C);
+
+      // If the instruction used I more than once, it could be on the user list
+      // multiple times.  Make sure we don't reprocess it.
+      std::vector<User*>::iterator It = std::find(Users.begin(), Users.end(),U);
+      while (It != Users.end()) {
+        Users.erase(It);
+        It = std::find(Users.begin(), Users.end(), U);
+      }
     }
-
-    // Keep track of which instructions occurred first & second
-    Instruction *First = BI;
-    Instruction *Second = I != First ? I : Other; // Get iterator to second inst
-    BI = Second;
-
-    if (isa<LoadInst>(Second))
-      ++NumLoadRemoved;  // Keep track of loads eliminated
-    if (isa<CallInst>(Second))
-      ++NumCallRemoved;  // Keep track of calls eliminated
-
-    // Destroy Second, using First instead.
-    ReplaceInstWithInst(First, BI);
-    Ret = First;
-
-    // Otherwise, the two instructions are in different basic blocks.  If one
-    // dominates the other instruction, we can simply use it
-    //
-  } else if (DomSetInfo->dominates(BB1, BB2)) {    // I dom Other?
-    if (isa<LoadInst>(Other))
-      ++NumLoadRemoved;  // Keep track of loads eliminated
-    if (isa<CallInst>(Other))
-      ++NumCallRemoved;  // Keep track of calls eliminated
-
-    ReplaceInstWithInst(I, Other);
-    Ret = I;
-  } else if (DomSetInfo->dominates(BB2, BB1)) {    // Other dom I?
-    if (isa<LoadInst>(I))
-      ++NumLoadRemoved;  // Keep track of loads eliminated
-    if (isa<CallInst>(I))
-      ++NumCallRemoved;  // Keep track of calls eliminated
-
-    ReplaceInstWithInst(Other, I);
-    Ret = Other;
-  } else {
-    // This code is disabled because it has several problems:
-    // One, the actual assumption is wrong, as shown by this code:
-    // int "test"(int %X, int %Y) {
-    //         %Z = add int %X, %Y
-    //         ret int %Z
-    // Unreachable:
-    //         %Q = add int %X, %Y
-    //         ret int %Q
-    // }
-    //
-    // Here there are no shared dominators.  Additionally, this had the habit of
-    // moving computations where they were not always computed.  For example, in
-    // a case like this:
-    //  if (c) {
-    //    if (d)  ...
-    //    else ... X+Y ...
-    //  } else {
-    //    ... X+Y ...
-    //  }
-    // 
-    // In this case, the expression would be hoisted to outside the 'if' stmt,
-    // causing the expression to be evaluated, even for the if (d) path, which
-    // could cause problems, if, for example, it caused a divide by zero.  In
-    // general the problem this case is trying to solve is better addressed with
-    // PRE than GCSE.
-    //
-    return 0;
   }
-
-  ++NumInstRemoved;   // Keep track of number of instructions eliminated
-
-  // Add all users of Ret to the worklist...
-  for (Value::use_iterator I = Ret->use_begin(), E = Ret->use_end(); I != E;++I)
-    if (Instruction *Inst = dyn_cast<Instruction>(*I))
-      WorkList.insert(Inst);
-
-  return Ret;
 }





More information about the llvm-commits mailing list