Author: lattner Date: Mon Dec 10 16:53:04 2007 New Revision: 44817 URL: http://llvm.org/viewvc/llvm-project?rev=44817&view=rev Log: Fix PR1850 by removing an unsafe transformation from VMCore/ConstantFold.cpp. Reimplement the xform in Analysis/ConstantFolding.cpp where we can use targetdata to validate that it is safe. While I'm in there, fix some const correctness issues and generalize the interface to the "operand folder".
Added: llvm/trunk/test/Transforms/InstCombine/2007-12-10-ConstFoldCompare.ll Modified: llvm/trunk/include/llvm/Analysis/ConstantFolding.h llvm/trunk/lib/Analysis/ConstantFolding.cpp llvm/trunk/lib/Analysis/ScalarEvolution.cpp llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp llvm/trunk/lib/VMCore/ConstantFold.cpp llvm/trunk/test/Assembler/ConstantExprFold.llx Modified: llvm/trunk/include/llvm/Analysis/ConstantFolding.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ConstantFolding.h?rev=44817&r1=44816&r2=44817&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ConstantFolding.h (original) +++ llvm/trunk/include/llvm/Analysis/ConstantFolding.h Mon Dec 10 16:53:04 2007 @@ -21,6 +21,7 @@ class Instruction; class TargetData; class Function; + class Type; /// ConstantFoldInstruction - Attempt to constant fold the specified /// instruction. If successful, the constant result is returned, if not, null @@ -35,12 +36,17 @@ /// fold instructions like loads and stores, which have no constant expression /// form. /// -Constant *ConstantFoldInstOperands( - const Instruction *I, ///< The model instruction - Constant** Ops, ///< The array of constant operands to use. - unsigned NumOps, ///< The number of operands provided. - const TargetData *TD = 0 ///< Optional target information. -); +Constant *ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, + Constant*const * Ops, unsigned NumOps, + const TargetData *TD = 0); + +/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare +/// instruction (icmp/fcmp) with the specified operands. If it fails, it +/// returns a constant expression of the specified operands. +/// +Constant *ConstantFoldCompareInstOperands(unsigned Predicate, + Constant*const * Ops, unsigned NumOps, + const TargetData *TD = 0); /// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a @@ -55,7 +61,7 @@ /// ConstantFoldCall - Attempt to constant fold a call to the specified function /// with the specified arguments, returning null if unsuccessful. Constant * -ConstantFoldCall(Function *F, Constant** Operands, unsigned NumOperands); +ConstantFoldCall(Function *F, Constant* const* Operands, unsigned NumOperands); } #endif Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=44817&r1=44816&r2=44817&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original) +++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Mon Dec 10 16:53:04 2007 @@ -55,7 +55,8 @@ if (CE->getOpcode() == Instruction::GetElementPtr) { // Cannot compute this if the element type of the pointer is missing size // info. - if (!cast<PointerType>(CE->getOperand(0)->getType())->getElementType()->isSized()) + if (!cast<PointerType>(CE->getOperand(0)->getType()) + ->getElementType()->isSized()) return false; // If the base isn't a global+constant, we aren't either. @@ -117,7 +118,7 @@ /// SymbolicallyEvaluateGEP - If we can symbolically evaluate the specified GEP /// constant expression, do so. -static Constant *SymbolicallyEvaluateGEP(Constant** Ops, unsigned NumOps, +static Constant *SymbolicallyEvaluateGEP(Constant* const* Ops, unsigned NumOps, const Type *ResultTy, const TargetData *TD) { Constant *Ptr = Ops[0]; @@ -181,7 +182,12 @@ else return 0; // All operands not constant! - return ConstantFoldInstOperands(I, &Ops[0], Ops.size(), TD); + if (const CmpInst *CI = dyn_cast<CmpInst>(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), + &Ops[0], Ops.size(), TD); + else + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Ops[0], Ops.size(), TD); } /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the @@ -190,23 +196,19 @@ /// attempting to fold instructions like loads and stores, which have no /// constant expression form. /// -Constant *llvm::ConstantFoldInstOperands(const Instruction* I, - Constant** Ops, unsigned NumOps, +Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, + Constant* const* Ops, unsigned NumOps, const TargetData *TD) { - unsigned Opc = I->getOpcode(); - const Type *DestTy = I->getType(); - // Handle easy binops first. - if (isa<BinaryOperator>(I)) { + if (Instruction::isBinaryOp(Opcode)) { if (isa<ConstantExpr>(Ops[0]) || isa<ConstantExpr>(Ops[1])) - if (Constant *C = SymbolicallyEvaluateBinop(I->getOpcode(), Ops[0], - Ops[1], TD)) + if (Constant *C = SymbolicallyEvaluateBinop(Opcode, Ops[0], Ops[1], TD)) return C; - return ConstantExpr::get(Opc, Ops[0], Ops[1]); + return ConstantExpr::get(Opcode, Ops[0], Ops[1]); } - switch (Opc) { + switch (Opcode) { default: return 0; case Instruction::Call: if (Function *F = dyn_cast<Function>(Ops[0])) @@ -215,8 +217,7 @@ return 0; case Instruction::ICmp: case Instruction::FCmp: - return ConstantExpr::getCompare(cast<CmpInst>(I)->getPredicate(), Ops[0], - Ops[1]); + assert(0 &&"This function is invalid for compares: no predicate specified"); case Instruction::PtrToInt: // If the input is a inttoptr, eliminate the pair. This requires knowing // the width of a pointer, so it can't be done in ConstantExpr::getCast. @@ -229,7 +230,7 @@ TD->getPointerSizeInBits())); Input = ConstantExpr::getAnd(Input, Mask); // Do a zext or trunc to get to the dest size. - return ConstantExpr::getIntegerCast(Input, I->getType(), false); + return ConstantExpr::getIntegerCast(Input, DestTy, false); } } // FALL THROUGH. @@ -244,7 +245,7 @@ case Instruction::FPToUI: case Instruction::FPToSI: case Instruction::BitCast: - return ConstantExpr::getCast(Opc, Ops[0], DestTy); + return ConstantExpr::getCast(Opcode, Ops[0], DestTy); case Instruction::Select: return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); case Instruction::ExtractElement: @@ -254,13 +255,73 @@ case Instruction::ShuffleVector: return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); case Instruction::GetElementPtr: - if (Constant *C = SymbolicallyEvaluateGEP(Ops, NumOps, I->getType(), TD)) + if (Constant *C = SymbolicallyEvaluateGEP(Ops, NumOps, DestTy, TD)) return C; return ConstantExpr::getGetElementPtr(Ops[0], Ops+1, NumOps-1); } } +/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare +/// instruction (icmp/fcmp) with the specified operands. If it fails, it +/// returns a constant expression of the specified operands. +/// +Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate, + Constant*const * Ops, + unsigned NumOps, + 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 (ptrtoint x), (ptrtoint y) -> icmp x, y + // + // ConstantExpr::getCompare cannot do this, because it doesn't have TD + // around to know if bit truncation is happening. + if (ConstantExpr *CE0 = dyn_cast<ConstantExpr>(Ops[0])) { + if (TD && Ops[1]->isNullValue()) { + 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 *C = ConstantExpr::getIntegerCast(CE0->getOperand(0), + IntPtrTy, false); + Constant *NewOps[] = { C, Constant::getNullValue(C->getType()) }; + 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) { + Constant *C = CE0->getOperand(0); + Constant *NewOps[] = { C, Constant::getNullValue(C->getType()) }; + // FIXME! + return ConstantFoldCompareInstOperands(Predicate, NewOps, 2, TD); + } + } + + 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 && + CE0->getOperand(1)->getType() == IntPtrTy) || + (CE0->getOpcode() == Instruction::PtrToInt && + CE0->getType() == IntPtrTy && + CE0->getOperand(0)->getType() == CE0->getOperand(1)->getType())) { + Constant *NewOps[] = { + CE0->getOperand(0), cast<ConstantExpr>(Ops[1])->getOperand(0) + }; + return ConstantFoldCompareInstOperands(Predicate, NewOps, 2, TD); + } + } + } + return ConstantExpr::getCompare(Predicate, Ops[0], Ops[1]); +} + + /// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a /// getelementptr constantexpr, return the constant value being addressed by the /// constant expression, or null if something is funny and we can't decide. @@ -438,7 +499,8 @@ /// with the specified arguments, returning null if unsuccessful. Constant * -llvm::ConstantFoldCall(Function *F, Constant** Operands, unsigned NumOperands) { +llvm::ConstantFoldCall(Function *F, + Constant* const* Operands, unsigned NumOperands) { const ValueName *NameVal = F->getValueName(); if (NameVal == 0) return 0; const char *Str = NameVal->getKeyData(); Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=44817&r1=44816&r2=44817&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Dec 10 16:53:04 2007 @@ -2043,7 +2043,12 @@ if (Operands[i] == 0) return 0; } - return ConstantFoldInstOperands(I, &Operands[0], Operands.size()); + if (const CmpInst *CI = dyn_cast<CmpInst>(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), + &Operands[0], Operands.size()); + else + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Operands[0], Operands.size()); } /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is @@ -2213,7 +2218,14 @@ } } } - Constant *C =ConstantFoldInstOperands(I, &Operands[0], Operands.size()); + + Constant *C; + if (const CmpInst *CI = dyn_cast<CmpInst>(I)) + C = ConstantFoldCompareInstOperands(CI->getPredicate(), + &Operands[0], Operands.size()); + else + C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Operands[0], Operands.size()); return SE.getUnknown(C); } } Modified: llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp?rev=44817&r1=44816&r2=44817&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp Mon Dec 10 16:53:04 2007 @@ -299,7 +299,13 @@ else return 0; // All operands not constant! - return ConstantFoldInstOperands(I, &Ops[0], Ops.size(), TD); + + if (const CmpInst *CI = dyn_cast<CmpInst>(I)) + return ConstantFoldCompareInstOperands(CI->getPredicate(), + &Ops[0], Ops.size(), TD); + else + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), + &Ops[0], Ops.size(), TD); } /// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, Modified: llvm/trunk/lib/VMCore/ConstantFold.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ConstantFold.cpp?rev=44817&r1=44816&r2=44817&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/ConstantFold.cpp (original) +++ llvm/trunk/lib/VMCore/ConstantFold.cpp Mon Dec 10 16:53:04 2007 @@ -985,20 +985,19 @@ case Instruction::UIToFP: case Instruction::SIToFP: - case Instruction::IntToPtr: case Instruction::BitCast: case Instruction::ZExt: case Instruction::SExt: - case Instruction::PtrToInt: // If the cast is not actually changing bits, and the second operand is a // null pointer, do the comparison with the pre-casted value. if (V2->isNullValue() && (isa<PointerType>(CE1->getType()) || CE1->getType()->isInteger())) { - bool sgnd = CE1->getOpcode() == Instruction::ZExt ? false : - (CE1->getOpcode() == Instruction::SExt ? true : - (CE1->getOpcode() == Instruction::PtrToInt ? false : isSigned)); - return evaluateICmpRelation( - CE1Op0, Constant::getNullValue(CE1Op0->getType()), sgnd); + bool sgnd = isSigned; + if (CE1->getOpcode() == Instruction::ZExt) isSigned = false; + if (CE1->getOpcode() == Instruction::SExt) isSigned = true; + return evaluateICmpRelation(CE1Op0, + Constant::getNullValue(CE1Op0->getType()), + sgnd); } // If the dest type is a pointer type, and the RHS is a constantexpr cast @@ -1009,11 +1008,11 @@ if (CE2->isCast() && isa<PointerType>(CE1->getType()) && CE1->getOperand(0)->getType() == CE2->getOperand(0)->getType() && CE1->getOperand(0)->getType()->isInteger()) { - bool sgnd = CE1->getOpcode() == Instruction::ZExt ? false : - (CE1->getOpcode() == Instruction::SExt ? true : - (CE1->getOpcode() == Instruction::PtrToInt ? false : isSigned)); + bool sgnd = isSigned; + if (CE1->getOpcode() == Instruction::ZExt) isSigned = false; + if (CE1->getOpcode() == Instruction::SExt) isSigned = true; return evaluateICmpRelation(CE1->getOperand(0), CE2->getOperand(0), - sgnd); + sgnd); } break; Modified: llvm/trunk/test/Assembler/ConstantExprFold.llx URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/ConstantExprFold.llx?rev=44817&r1=44816&r2=44817&view=diff ============================================================================== --- llvm/trunk/test/Assembler/ConstantExprFold.llx (original) +++ llvm/trunk/test/Assembler/ConstantExprFold.llx Mon Dec 10 16:53:04 2007 @@ -24,6 +24,3 @@ int* getelementptr (%Ty* %B, long 0, uint 1)) ; true ;global bool setne (long* %A, long* cast (%Ty* %B to long*)) ; true -global bool seteq ({ short }* cast (int 1 to { short }*), { short }* null) -global bool setlt ({ short }* cast (int 1 to { short }*), { short }* cast (int 2 to { short }*)) - Added: llvm/trunk/test/Transforms/InstCombine/2007-12-10-ConstFoldCompare.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2007-12-10-ConstFoldCompare.ll?rev=44817&view=auto ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/2007-12-10-ConstFoldCompare.ll (added) +++ llvm/trunk/test/Transforms/InstCombine/2007-12-10-ConstFoldCompare.ll Mon Dec 10 16:53:04 2007 @@ -0,0 +1,9 @@ +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 = "i686-pc-linux-gnu" +; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep {ret i1 0} +; PR1850 + +define i1 @test() { + %cond = icmp ule i8* inttoptr (i64 4294967297 to i8*), inttoptr (i64 5 to i8*) + ret i1 %cond +} _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits