Move some constant folding logic for loads out of instcombine into
Analysis/ConstantFolding.cpp.  This doesn't change the behavior of
instcombine but makes other clients of ConstantFoldInstruction
able to handle loads.  This was partially extracted from Eli's patch
in PR3152.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84836 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index 0ce1c24..da671c8 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -30,6 +30,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/GlobalVariable.h"
 #include <cerrno>
 #include <cmath>
 using namespace llvm;
@@ -92,6 +93,37 @@
   return false;
 }
 
+/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
+/// produce if it is constant and determinable.  If this is not determinable,
+/// return null.
+Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C,
+                                             const TargetData *TD) {
+  // First, try the easy cases:
+  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
+    if (GV->isConstant() && GV->hasDefinitiveInitializer())
+      return GV->getInitializer();
+
+  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+    if (CE->getOpcode() == Instruction::GetElementPtr) {
+      if (GlobalVariable *GV = dyn_cast<GlobalVariable>(CE->getOperand(0)))
+        if (GV->isConstant() && GV->hasDefinitiveInitializer())
+          if (Constant *V = 
+               ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE))
+            return V;
+    }
+  }
+
+  return 0;
+}
+
+static Constant *ConstantFoldLoadInst(const LoadInst *LI, const TargetData *TD){
+  if (LI->isVolatile()) return 0;
+  
+  if (Constant *C = dyn_cast<Constant>(LI->getOperand(0)))
+    return ConstantFoldLoadFromConstPtr(C, TD);
+    
+  return 0;
+}
 
 /// SymbolicallyEvaluateBinop - One of Op0/Op1 is a constant expression.
 /// Attempt to symbolically evaluate the result of a binary operator merging
@@ -380,6 +412,9 @@
                                            Ops.data(), Ops.size(), 
                                            Context, TD);
   
+  if (const LoadInst *LI = dyn_cast<LoadInst>(I))
+    return ConstantFoldLoadInst(LI, TD);
+  
   return ConstantFoldInstOperands(I->getOpcode(), I->getType(),
                                   Ops.data(), Ops.size(), Context, TD);
 }