"ret (constexpr)" can't be folded into a Constant. Add a method to
authorNick Lewycky <nicholas@mxc.ca>
Sun, 25 May 2008 20:56:15 +0000 (20:56 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Sun, 25 May 2008 20:56:15 +0000 (20:56 +0000)
Analysis/ConstantFolding to fold ConstantExpr's, then make instcombine use it
to try to use targetdata to fold constant expressions on void instructions.

Also extend the icmp(inttoptr, inttoptr) folding to handle the case where
int size != ptr size.

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

include/llvm/Analysis/ConstantFolding.h
lib/Analysis/ConstantFolding.cpp
lib/Transforms/Scalar/InstructionCombining.cpp
test/Transforms/InstCombine/2008-05-18-FoldIntToPtr.ll [new file with mode: 0644]

index a22913a0b9023349cf35549004fd21078a1bc0d9..bf360f7e88470e5e89c11556420caf2831b4dcae 100644 (file)
@@ -30,6 +30,12 @@ namespace llvm {
 ///
 Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0);
 
+/// ConstantFoldConstantExpression - Attempt to fold the constant expression
+/// using the specified TargetData.  If successful, the constant result is
+/// result is returned, if not, null is returned.
+Constant *ConstantFoldConstantExpression(ConstantExpr *CE,
+                                         const TargetData *TD);
+
 /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
 /// specified operands.  If successful, the constant result is returned, if not,
 /// null is returned.  Note that this function can fail when attempting to 
index d933dd8d4033d807d2ac6e837777f69131541cdd..43597c85f16237ad35b4229c584eacd0d1b3ce3d 100644 (file)
@@ -312,6 +312,25 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) {
                                     &Ops[0], Ops.size(), TD);
 }
 
+/// ConstantFoldConstantExpression - Attempt to fold the constant expression
+/// using the specified TargetData.  If successful, the constant result is
+/// result is returned, if not, null is returned.
+Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE,
+                                               const TargetData *TD) {
+  assert(TD && "ConstantFoldConstantExpression requires a valid TargetData.");
+
+  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));
+
+  if (CE->isCompare())
+    return ConstantFoldCompareInstOperands(CE->getPredicate(),
+                                           &Ops[0], Ops.size(), TD);
+  else 
+    return ConstantFoldInstOperands(CE->getOpcode(), CE->getType(),
+                                    &Ops[0], Ops.size(), TD);
+}
+
 /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the
 /// specified opcode and operands.  If successful, the constant result is
 /// returned, if not, null is returned.  Note that this function can fail when
@@ -398,7 +417,7 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate,
                                                 const TargetData *TD) {
   // fold: icmp (inttoptr x), null         -> icmp x, 0
   // fold: icmp (ptrtoint x), 0            -> icmp x, null
-  // fold: icmp (inttoptr x), (inttoptr y) -> icmp x, y
+  // fold: icmp (inttoptr x), (inttoptr y) -> icmp trunc/zext x, trunc/zext y
   // fold: icmp (ptrtoint x), (ptrtoint y) -> icmp x, y
   //
   // ConstantExpr::getCompare cannot do this, because it doesn't have TD
@@ -426,21 +445,31 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate,
       }
     }
     
-    if (TD && isa<ConstantExpr>(Ops[1]) &&
-        cast<ConstantExpr>(Ops[1])->getOpcode() == CE0->getOpcode()) {
-      const Type *IntPtrTy = TD->getIntPtrType();
-      // Only do this transformation if the int is intptrty in size, otherwise
-      // there is a truncation or extension that we aren't modeling.
-      if ((CE0->getOpcode() == Instruction::IntToPtr &&
-           CE0->getOperand(0)->getType() == IntPtrTy &&
-           Ops[1]->getOperand(0)->getType() == IntPtrTy) ||
-          (CE0->getOpcode() == Instruction::PtrToInt &&
-           CE0->getType() == IntPtrTy &&
-           CE0->getOperand(0)->getType() == Ops[1]->getOperand(0)->getType())) {
-        Constant *NewOps[] = { 
-          CE0->getOperand(0), cast<ConstantExpr>(Ops[1])->getOperand(0) 
-        };
-        return ConstantFoldCompareInstOperands(Predicate, NewOps, 2, TD);
+    if (ConstantExpr *CE1 = dyn_cast<ConstantExpr>(Ops[1])) {
+      if (TD && CE0->getOpcode() == CE1->getOpcode()) {
+        const Type *IntPtrTy = TD->getIntPtrType();
+
+        if (CE0->getOpcode() == Instruction::IntToPtr) {
+          // Convert the integer value to the right size to ensure we get the
+          // proper extension or truncation.
+          Constant *C0 = ConstantExpr::getIntegerCast(CE0->getOperand(0),
+                                                      IntPtrTy, false);
+          Constant *C1 = ConstantExpr::getIntegerCast(CE1->getOperand(0),
+                                                      IntPtrTy, false);
+          Constant *NewOps[] = { C0, C1 };
+          return ConstantFoldCompareInstOperands(Predicate, NewOps, 2, TD);
+        }
+
+        // Only do this transformation if the int is intptrty in size, otherwise
+        // there is a truncation or extension that we aren't modeling.
+        if ((CE0->getOpcode() == Instruction::PtrToInt &&
+             CE0->getType() == IntPtrTy &&
+             CE0->getOperand(0)->getType() == CE1->getOperand(0)->getType())) {
+          Constant *NewOps[] = { 
+            CE0->getOperand(0), CE1->getOperand(0) 
+          };
+          return ConstantFoldCompareInstOperands(Predicate, NewOps, 2, TD);
+        }
       }
     }
   }
index a6cbc20163762154daa28ef2509245d8bf6f47b1..20204154d0e8006fad405f6b006833fd94570a77 100644 (file)
@@ -11887,6 +11887,16 @@ bool InstCombiner::DoOneIteration(Function &F, unsigned Iteration) {
       continue;
     }
 
+    if (TD && I->getType()->getTypeID() == Type::VoidTyID) {
+      // See if we can constant fold its operands.
+      for (User::op_iterator i = I->op_begin(), e = I->op_end(); i != e; ++i) {
+        if (ConstantExpr *CE = dyn_cast<ConstantExpr>(i)) {
+          if (Constant *NewC = ConstantFoldConstantExpression(CE, TD))
+            i->set(NewC);
+        }
+      }
+    }
+
     // See if we can trivially sink this instruction to a successor basic block.
     // FIXME: Remove GetResultInst test when first class support for aggregates
     // is implemented.
diff --git a/test/Transforms/InstCombine/2008-05-18-FoldIntToPtr.ll b/test/Transforms/InstCombine/2008-05-18-FoldIntToPtr.ll
new file mode 100644 (file)
index 0000000..e994399
--- /dev/null
@@ -0,0 +1,13 @@
+; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep {ret i1 false} | count 2
+; PR2329
+
+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:32:32"
+target triple = "i386-pc-linux-gnu"
+
+define i1 @f1() {
+  ret i1 icmp eq (i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 2 to i8*))
+}
+
+define i1 @f2() {
+  ret i1 icmp eq (i8* inttoptr (i16 1 to i8*), i8* inttoptr (i16 2 to i8*))
+}