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

Chris Lattner lattner at cs.uiuc.edu
Fri Dec 10 21:16:13 PST 2004



Changes in directory llvm/lib/Transforms/Scalar:

SCCP.cpp updated: 1.115 -> 1.116
---
Log message:

Implement Transforms/SCCP/ipsccp-gvar.ll, by tracking values stored to
non-address-taken global variables.


---
Diffs of the changes:  (+85 -12)

Index: llvm/lib/Transforms/Scalar/SCCP.cpp
diff -u llvm/lib/Transforms/Scalar/SCCP.cpp:1.115 llvm/lib/Transforms/Scalar/SCCP.cpp:1.116
--- llvm/lib/Transforms/Scalar/SCCP.cpp:1.115	Fri Dec 10 20:53:57 2004
+++ llvm/lib/Transforms/Scalar/SCCP.cpp	Fri Dec 10 23:15:59 2004
@@ -25,11 +25,9 @@
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Constants.h"
-#include "llvm/Function.h"
-#include "llvm/GlobalVariable.h"
+#include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
-#include "llvm/Type.h"
 #include "llvm/Support/InstVisitor.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Support/CallSite.h"
@@ -99,6 +97,12 @@
   std::set<BasicBlock*>     BBExecutable;// The basic blocks that are executable
   hash_map<Value*, LatticeVal> ValueState;  // The state each value is in...
 
+  /// GlobalValue - If we are tracking any values for the contents of a global
+  /// variable, we keep a mapping from the constant accessor to the element of
+  /// the global, to the currently known value.  If the value becomes
+  /// overdefined, it's entry is simply removed from this map.
+  hash_map<GlobalVariable*, LatticeVal> TrackedGlobals;
+
   /// TrackedFunctionRetVals - If we are tracking arguments into and the return
   /// value out of a function, it will have an entry in this map, indicating
   /// what the known return value for the function is.
@@ -134,11 +138,18 @@
     BBWorkList.push_back(BB);  // Add the block to the work list!
   }
 
-  /// TrackValueOfGlobalVariableIfPossible - Clients can use this method to
+  /// TrackValueOfGlobalVariable - Clients can use this method to
   /// inform the SCCPSolver that it should track loads and stores to the
   /// specified global variable if it can.  This is only legal to call if
   /// performing Interprocedural SCCP.
-  void TrackValueOfGlobalVariableIfPossible(GlobalVariable *GV);
+  void TrackValueOfGlobalVariable(GlobalVariable *GV) {
+    const Type *ElTy = GV->getType()->getElementType();
+    if (ElTy->isFirstClassType()) {
+      LatticeVal &IV = TrackedGlobals[GV];
+      if (!isa<UndefValue>(GV->getInitializer()))
+        IV.markConstant(GV->getInitializer());
+    }
+  }
 
   /// AddTrackedFunction - If the SCCP solver is supposed to track calls into
   /// and out of the specified function (which cannot have its address taken),
@@ -178,6 +189,12 @@
     return TrackedFunctionRetVals;
   }
 
+  /// getTrackedGlobals - Get and return the set of inferred initializers for
+  /// global variables.
+  const hash_map<GlobalVariable*, LatticeVal> &getTrackedGlobals() {
+    return TrackedGlobals;
+  }
+
 
 private:
   // markConstant - Make a value be marked as "constant".  If the value
@@ -303,7 +320,7 @@
   void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
 
   // Instructions that cannot be folded away...
-  void visitStoreInst     (Instruction &I) { /*returns void*/ }
+  void visitStoreInst     (Instruction &I);
   void visitLoadInst      (LoadInst &I);
   void visitGetElementPtrInst(GetElementPtrInst &I);
   void visitCallInst      (CallInst &I) { visitCallSite(CallSite::get(&I)); }
@@ -724,6 +741,22 @@
   return C;
 }
 
+void SCCPSolver::visitStoreInst(Instruction &SI) {
+  if (TrackedGlobals.empty() || !isa<GlobalVariable>(SI.getOperand(1)))
+    return;
+  GlobalVariable *GV = cast<GlobalVariable>(SI.getOperand(1));
+  hash_map<GlobalVariable*, LatticeVal>::iterator I = TrackedGlobals.find(GV);
+  if (I == TrackedGlobals.end() || I->second.isOverdefined()) return;
+
+  // Get the value we are storing into the global.
+  LatticeVal &PtrVal = getValueState(SI.getOperand(0));
+
+  mergeInValue(I->second, GV, PtrVal);
+  if (I->second.isOverdefined())
+    TrackedGlobals.erase(I);      // No need to keep tracking this!
+}
+
+
 // Handle load instructions.  If the operand is a constant pointer to a constant
 // global, we can replace the load with the loaded constant value!
 void SCCPSolver::visitLoadInst(LoadInst &I) {
@@ -741,11 +774,22 @@
     }
       
     // Transform load (constant global) into the value loaded.
-    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr))
-      if (GV->isConstant() && !GV->isExternal()) {
-        markConstant(IV, &I, GV->getInitializer());
-        return;
+    if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) {
+      if (GV->isConstant()) {
+        if (!GV->isExternal()) {
+          markConstant(IV, &I, GV->getInitializer());
+          return;
+        }
+      } else if (!TrackedGlobals.empty()) {
+        // If we are tracking this global, merge in the known value for it.
+        hash_map<GlobalVariable*, LatticeVal>::iterator It =
+          TrackedGlobals.find(GV);
+        if (It != TrackedGlobals.end()) {
+          mergeInValue(IV, &I, It->second);
+          return;
+        }
       }
+    }
 
     // Transform load (constantexpr_GEP global, 0, ...) into the value loaded.
     if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
@@ -1029,6 +1073,8 @@
   Statistic<> IPNumDeadBlocks ("ipsccp", "Number of basic blocks unreachable");
   Statistic<> IPNumArgsElimed ("ipsccp",
                                "Number of arguments constant propagated");
+  Statistic<> IPNumGlobalConst("ipsccp",
+                               "Number of globals found to be constant");
 
   //===--------------------------------------------------------------------===//
   //
@@ -1053,7 +1099,8 @@
   for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end();
        UI != E; ++UI)
     if (StoreInst *SI = dyn_cast<StoreInst>(*UI)) {
-      if (SI->getOperand(0) == GV) return true;  // Storing addr of GV.
+      if (SI->getOperand(0) == GV || SI->isVolatile())
+        return true;  // Storing addr of GV.
     } else if (isa<InvokeInst>(*UI) || isa<CallInst>(*UI)) {
       // Make sure we are calling the function, not passing the address.
       CallSite CS = CallSite::get(cast<Instruction>(*UI));
@@ -1061,7 +1108,10 @@
              E = CS.arg_end(); AI != E; ++AI)
         if (*AI == GV)
           return true;
-    } else if (!isa<LoadInst>(*UI)) {
+    } else if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
+      if (LI->isVolatile())
+        return true;
+    } else {
       return true;
     }
   return false;
@@ -1084,6 +1134,13 @@
       Solver.AddTrackedFunction(F);
     }
 
+  // Loop over global variables.  We inform the solver about any internal global
+  // variables that do not have their 'addresses taken'.  If they don't have
+  // their addresses taken, we can propagate constants through them.
+  for (Module::giterator G = M.gbegin(), E = M.gend(); G != E; ++G)
+    if (!G->isConstant() && G->hasInternalLinkage() && !AddressIsTaken(G))
+      Solver.TrackValueOfGlobalVariable(G);
+
   // Solve for constants.
   bool ResolvedBranches = true;
   while (ResolvedBranches) {
@@ -1208,6 +1265,22 @@
           if (!isa<UndefValue>(RI->getOperand(0)))
             RI->setOperand(0, UndefValue::get(F->getReturnType()));
     }
+
+  // If we infered constant or undef values for globals variables, we can delete
+  // the global and any stores that remain to it.
+  const hash_map<GlobalVariable*, LatticeVal> &TG = Solver.getTrackedGlobals();
+  for (hash_map<GlobalVariable*, LatticeVal>::const_iterator I = TG.begin(),
+         E = TG.end(); I != E; ++I) {
+    GlobalVariable *GV = I->first;
+    assert(!I->second.isOverdefined() &&
+           "Overdefined values should have been taken out of the map!");
+    DEBUG(std::cerr << "Found that GV '" << GV->getName()<< "' is constant!\n");
+    while (!GV->use_empty()) {
+      StoreInst *SI = cast<StoreInst>(GV->use_back());
+      SI->eraseFromParent();
+    }
+    M.getGlobalList().erase(GV);
+  }
   
   return MadeChanges;
 }






More information about the llvm-commits mailing list