diff options
Diffstat (limited to 'lib/Analysis/ConstantFolding.cpp')
-rw-r--r-- | lib/Analysis/ConstantFolding.cpp | 61 |
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); + } } } } |