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

Chris Lattner lattner at cs.uiuc.edu
Sun Jan 11 22:30:01 PST 2004


Changes in directory llvm/lib/Transforms/Scalar:

SCCP.cpp updated: 1.84 -> 1.85

---
Log message:

* Implement minor performance optimization for the getelementptr case
* Implement SCCP of load instructions, implementing Transforms/SCCP/loadtest.ll
  This allows us to fold expressions like "foo"[2], even if the pointer is only
  a conditional constant.


---
Diffs of the changes:  (+69 -3)

Index: llvm/lib/Transforms/Scalar/SCCP.cpp
diff -u llvm/lib/Transforms/Scalar/SCCP.cpp:1.84 llvm/lib/Transforms/Scalar/SCCP.cpp:1.85
--- llvm/lib/Transforms/Scalar/SCCP.cpp:1.84	Sun Jan 11 21:57:30 2004
+++ llvm/lib/Transforms/Scalar/SCCP.cpp	Sun Jan 11 22:29:41 2004
@@ -24,6 +24,7 @@
 #include "llvm/Transforms/Scalar.h"
 #include "llvm/ConstantHandling.h"
 #include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
 #include "llvm/Instructions.h"
 #include "llvm/Pass.h"
 #include "llvm/Support/InstVisitor.h"
@@ -215,7 +216,7 @@
 
   // Instructions that cannot be folded away...
   void visitStoreInst     (Instruction &I) { /*returns void*/ }
-  void visitLoadInst      (Instruction &I) { markOverdefined(&I); }
+  void visitLoadInst      (LoadInst &I);
   void visitGetElementPtrInst(GetElementPtrInst &I);
   void visitCallInst      (Instruction &I) { markOverdefined(&I); }
   void visitInvokeInst    (TerminatorInst &I) {
@@ -666,6 +667,9 @@
 // can turn this into a getelementptr ConstantExpr.
 //
 void SCCP::visitGetElementPtrInst(GetElementPtrInst &I) {
+  InstVal &IV = ValueState[&I];
+  if (IV.isOverdefined()) return;
+
   std::vector<Constant*> Operands;
   Operands.reserve(I.getNumOperands());
 
@@ -674,7 +678,7 @@
     if (State.isUndefined())
       return;  // Operands are not resolved yet...
     else if (State.isOverdefined()) {
-      markOverdefined(&I);
+      markOverdefined(IV, &I);
       return;
     }
     assert(State.isConstant() && "Unknown state!");
@@ -684,6 +688,68 @@
   Constant *Ptr = Operands[0];
   Operands.erase(Operands.begin());  // Erase the pointer from idx list...
 
-  markConstant(&I, ConstantExpr::getGetElementPtr(Ptr, Operands));  
+  markConstant(IV, &I, ConstantExpr::getGetElementPtr(Ptr, Operands));  
+}
+
+/// GetGEPGlobalInitializer - Given a constant and a getelementptr constantexpr,
+/// return the constant value being addressed by the constant expression, or
+/// null if something is funny.
+///
+static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) {
+  if (CE->getOperand(1) != Constant::getNullValue(Type::LongTy))
+    return 0;  // Do not allow stepping over the value!
+
+  // Loop over all of the operands, tracking down which value we are
+  // addressing...
+  for (unsigned i = 2, e = CE->getNumOperands(); i != e; ++i)
+    if (ConstantUInt *CU = dyn_cast<ConstantUInt>(CE->getOperand(i))) {
+      ConstantStruct *CS = cast<ConstantStruct>(C);
+      if (CU->getValue() >= CS->getValues().size()) return 0;
+      C = cast<Constant>(CS->getValues()[CU->getValue()]);
+    } else if (ConstantSInt *CS = dyn_cast<ConstantSInt>(CE->getOperand(i))) {
+      ConstantArray *CA = cast<ConstantArray>(C);
+      if ((uint64_t)CS->getValue() >= CA->getValues().size()) return 0;
+      C = cast<Constant>(CA->getValues()[CS->getValue()]);
+    } else 
+      return 0;
+  return C;
 }
 
+// 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 SCCP::visitLoadInst(LoadInst &I) {
+  InstVal &IV = ValueState[&I];
+  if (IV.isOverdefined()) return;
+
+  InstVal &PtrVal = getValueState(I.getOperand(0));
+  if (PtrVal.isUndefined()) return;   // The pointer is not resolved yet!
+  if (PtrVal.isConstant() && !I.isVolatile()) {
+    Value *Ptr = PtrVal.getConstant();
+    if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(Ptr))
+      Ptr = CPR->getValue();
+
+    // 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;
+      }
+
+    // Transform load (constantexpr_GEP global, 0, ...) into the value loaded.
+    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
+      if (CE->getOpcode() == Instruction::GetElementPtr)
+        if (ConstantPointerRef *G
+            = dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
+          if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getValue()))
+            if (GV->isConstant() && !GV->isExternal())
+              if (Constant *V =
+                  GetGEPGlobalInitializer(GV->getInitializer(), CE)) {
+                markConstant(IV, &I, V);
+                return;
+              }
+  }
+
+  // Otherwise we cannot say for certain what value this load will produce.
+  // Bail out.
+  markOverdefined(IV, &I);
+}





More information about the llvm-commits mailing list