Make ConstantFoldConstantExpression recursively visit the entire
authorDan Gohman <gohman@apple.com>
Mon, 23 Nov 2009 16:22:21 +0000 (16:22 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 23 Nov 2009 16:22:21 +0000 (16:22 +0000)
ConstantExpr, not just the top-level operator. This allows it to
fold many more constants.

Also, make GlobalOpt call ConstantFoldConstantExpression on
GlobalVariable initializers.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89659 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ConstantFolding.cpp
lib/Transforms/IPO/GlobalOpt.cpp
test/Transforms/GlobalOpt/constantfold-initializers.ll [new file with mode: 0644]
test/Transforms/InstCombine/cast.ll
test/Transforms/InstCombine/shufflevec-constant.ll

index 1cdadbfcea41dbe33f93249e2c1418a3ececc02b..8d60907f8cb2be053eac1384bfdbc0405a73cf25 100644 (file)
@@ -671,8 +671,13 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) {
 Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE,
                                                const TargetData *TD) {
   SmallVector<Constant*, 8> Ops;
-  for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i)
-    Ops.push_back(cast<Constant>(*i));
+  for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) {
+    Constant *NewC = cast<Constant>(*i);
+    // Recursively fold the ConstantExpr's operands.
+    if (ConstantExpr *NewCE = dyn_cast<ConstantExpr>(NewC))
+      NewC = ConstantFoldConstantExpression(NewCE, TD);
+    Ops.push_back(NewC);
+  }
 
   if (CE->isCompare())
     return ConstantFoldCompareInstOperands(CE->getPredicate(), Ops[0], Ops[1],
@@ -687,6 +692,10 @@ Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE,
 /// attempting to fold instructions like loads and stores, which have no
 /// constant expression form.
 ///
+/// TODO: This function neither utilizes nor preserves nsw/nuw/inbounds/etc
+/// information, due to only being passed an opcode and operands. Constant
+/// folding using this function strips this information.
+///
 Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, 
                                          Constant* const* Ops, unsigned NumOps,
                                          const TargetData *TD) {
index 442f2fb6552880a21d8fad99319df9049a2e60c6..4635d0e61c394f737ec2224369749ae8286c3d9c 100644 (file)
@@ -1898,6 +1898,15 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) {
     // Global variables without names cannot be referenced outside this module.
     if (!GV->hasName() && !GV->isDeclaration())
       GV->setLinkage(GlobalValue::InternalLinkage);
+    // Simplify the initializer.
+    if (GV->hasInitializer())
+      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GV->getInitializer())) {
+        TargetData *TD = getAnalysisIfAvailable<TargetData>();
+        Constant *New = ConstantFoldConstantExpression(CE, TD);
+        if (New && New != CE)
+          GV->setInitializer(New);
+      }
+    // Do more involved optimizations if the global is internal.
     if (!GV->isConstant() && GV->hasLocalLinkage() &&
         GV->hasInitializer())
       Changed |= ProcessInternalGlobal(GV, GVI);
diff --git a/test/Transforms/GlobalOpt/constantfold-initializers.ll b/test/Transforms/GlobalOpt/constantfold-initializers.ll
new file mode 100644 (file)
index 0000000..834bd00
--- /dev/null
@@ -0,0 +1,8 @@
+; RUN: opt < %s -S -globalopt | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+
+@.str91250 = global [3 x i8] zeroinitializer
+
+; CHECK: @A = global i1 false
+@A = global i1 icmp ne (i64 sub nsw (i64 ptrtoint (i8* getelementptr inbounds ([3 x i8]* @.str91250, i64 0, i64 1) to i64), i64 ptrtoint ([3 x i8]* @.str91250 to i64)), i64 1)
index e7695b74b75ed3a1fb2a694c4c7e7902e267c0ac..5f75cd0a8930b8b81cb998e2f5366ee3ead9b6d8 100644 (file)
@@ -103,7 +103,7 @@ define i32* @test12() {
         %p = malloc [4 x i8]            ; <[4 x i8]*> [#uses=1]
         %c = bitcast [4 x i8]* %p to i32*               ; <i32*> [#uses=1]
         ret i32* %c
-; CHECK: %malloccall = tail call i8* @malloc(i32 ptrtoint ([4 x i8]* getelementptr ([4 x i8]* null, i32 1) to i32))
+; CHECK: %malloccall = tail call i8* @malloc(i32 4)
 ; CHECK: ret i32* %c
 }
 
@@ -275,7 +275,7 @@ define void @test32(double** %tmp) {
         %tmp8.upgrd.1 = bitcast [16 x i8]* %tmp8 to double*             ; <double*> [#uses=1]
         store double* %tmp8.upgrd.1, double** %tmp
         ret void
-; CHECK: %malloccall = tail call i8* @malloc(i32 ptrtoint ([16 x i8]* getelementptr ([16 x i8]* null, i32 1) to i32))
+; CHECK: %malloccall = tail call i8* @malloc(i32 16)
 ; CHECK: %tmp8.upgrd.1 = bitcast i8* %malloccall to double*
 ; CHECK: store double* %tmp8.upgrd.1, double** %tmp
 ; CHECK: ret void
index 2c667903b1ebf335c45cb0fb2ca447fc684a666e..29ae5a79824a0a3e7c5d9ad351decdf9de38e135 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt < %s -instcombine -S | grep "2 x float"
+; RUN: opt < %s -instcombine -S | grep {ret <4 x float> <float 0.000000e+00, float 0.000000e+00, float 0x7FF0000000000000, float 0x7FF0000000000000>}
 
 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
 target triple = "i386-apple-darwin9"