aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/ConstantFolding.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/ConstantFolding.cpp')
-rw-r--r--lib/Analysis/ConstantFolding.cpp61
1 files changed, 45 insertions, 16 deletions
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index d933dd8d40..43597c85f1 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -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);
+ }
}
}
}