X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FConstantFolding.cpp;h=68a55b6b94d50b80b682522c29f8ec6c9b3b5ce2;hb=48f17ba2a611d197082d4de730b646a4ecf68df4;hp=69581ba5ecd8a2ac5d37f9a95f9fabde3dd724bd;hpb=8ee731f2ce62d936f81c12283a192375a87f323a;p=oota-llvm.git diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 69581ba5ecd..68a55b6b94d 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -30,9 +30,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/FEnv.h" #include #include -#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -538,7 +538,7 @@ static Constant *CastGEPIndices(Constant *const *Ops, unsigned NumOps, for (unsigned i = 1; i != NumOps; ++i) { if ((i == 1 || !isa(GetElementPtrInst::getIndexedType(Ops[0]->getType(), - reinterpret_cast(Ops+1), + reinterpret_cast(Ops+1), i-1))) && Ops[i]->getType() != IntPtrTy) { Any = true; @@ -610,10 +610,8 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, APInt BasePtr(BitWidth, 0); if (ConstantExpr *CE = dyn_cast(Ptr)) if (CE->getOpcode() == Instruction::IntToPtr) - if (ConstantInt *Base = dyn_cast(CE->getOperand(0))) { - BasePtr = Base->getValue(); - BasePtr.zextOrTrunc(BitWidth); - } + if (ConstantInt *Base = dyn_cast(CE->getOperand(0))) + BasePtr = Base->getValue().zextOrTrunc(BitWidth); if (Ptr->isNullValue() || BasePtr != 0) { Constant *C = ConstantInt::get(Ptr->getContext(), Offset+BasePtr); return ConstantExpr::getIntToPtr(C, ResultTy); @@ -639,12 +637,19 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, // Determine which element of the array the offset points into. APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType())); + const IntegerType *IntPtrTy = TD->getIntPtrType(Ty->getContext()); if (ElemSize == 0) - return 0; - APInt NewIdx = Offset.udiv(ElemSize); - Offset -= NewIdx * ElemSize; - NewIdxs.push_back(ConstantInt::get(TD->getIntPtrType(Ty->getContext()), - NewIdx)); + // The element size is 0. This may be [0 x Ty]*, so just use a zero + // index for this level and proceed to the next level to see if it can + // accommodate the offset. + NewIdxs.push_back(ConstantInt::get(IntPtrTy, 0)); + else { + // The element size is non-zero divide the offset by the element + // size (rounding down), to compute the index at this level. + APInt NewIdx = Offset.udiv(ElemSize); + Offset -= NewIdx * ElemSize; + NewIdxs.push_back(ConstantInt::get(IntPtrTy, NewIdx)); + } Ty = ATy->getElementType(); } else if (const StructType *STy = dyn_cast(Ty)) { // Determine which field of the struct the offset points into. The @@ -688,27 +693,34 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, // Constant Folding public APIs //===----------------------------------------------------------------------===// - -/// ConstantFoldInstruction - Attempt to constant fold the specified -/// instruction. If successful, the constant result is returned, if not, null -/// is returned. Note that this function can only fail when attempting to fold -/// instructions like loads and stores, which have no constant expression form. -/// +/// ConstantFoldInstruction - Try to constant fold the specified instruction. +/// If successful, the constant result is returned, if not, null is returned. +/// Note that this fails if not all of the operands are constant. Otherwise, +/// this function can only fail when attempting to fold instructions like loads +/// and stores, which have no constant expression form. Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { + // Handle PHI nodes quickly here... if (PHINode *PN = dyn_cast(I)) { - if (PN->getNumIncomingValues() == 0) - return UndefValue::get(PN->getType()); - - Constant *Result = dyn_cast(PN->getIncomingValue(0)); - if (Result == 0) return 0; - - // Handle PHI nodes specially here... - for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) - if (PN->getIncomingValue(i) != Result && PN->getIncomingValue(i) != PN) - return 0; // Not all the same incoming constants... + Constant *CommonValue = 0; + + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + Value *Incoming = PN->getIncomingValue(i); + // If the incoming value is undef then skip it. Note that while we could + // skip the value if it is equal to the phi node itself we choose not to + // because that would break the rule that constant folding only applies if + // all operands are constants. + if (isa(Incoming)) + continue; + // If the incoming value is not a constant, or is a different constant to + // the one we saw previously, then give up. + Constant *C = dyn_cast(Incoming); + if (!C || (CommonValue && C != CommonValue)) + return 0; + CommonValue = C; + } - // If we reach here, all incoming values are the same constant. - return Result; + // If we reach here, all incoming values are the same constant or undef. + return CommonValue ? CommonValue : UndefValue::get(PN->getType()); } // Scan the operand list, checking to see if they are all constants, if so, @@ -726,7 +738,18 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { if (const LoadInst *LI = dyn_cast(I)) return ConstantFoldLoadInst(LI, TD); - + + if (InsertValueInst *IVI = dyn_cast(I)) + return ConstantExpr::getInsertValue( + cast(IVI->getAggregateOperand()), + cast(IVI->getInsertedValueOperand()), + IVI->idx_begin(), IVI->getNumIndices()); + + if (ExtractValueInst *EVI = dyn_cast(I)) + return ConstantExpr::getExtractValue( + cast(EVI->getAggregateOperand()), + EVI->idx_begin(), EVI->getNumIndices()); + return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops.data(), Ops.size(), TD); } @@ -737,7 +760,8 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { Constant *llvm::ConstantFoldConstantExpression(const ConstantExpr *CE, const TargetData *TD) { SmallVector Ops; - for (User::const_op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) { + for (User::const_op_iterator i = CE->op_begin(), e = CE->op_end(); + i != e; ++i) { Constant *NewC = cast(*i); // Recursively fold the ConstantExpr's operands. if (ConstantExpr *NewCE = dyn_cast(NewC)) @@ -1001,6 +1025,7 @@ llvm::canConstantFoldCallTo(const Function *F) { case Intrinsic::usub_with_overflow: case Intrinsic::sadd_with_overflow: case Intrinsic::ssub_with_overflow: + case Intrinsic::smul_with_overflow: case Intrinsic::convert_from_fp16: case Intrinsic::convert_to_fp16: return true; @@ -1040,13 +1065,10 @@ llvm::canConstantFoldCallTo(const Function *F) { static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, const Type *Ty) { - feclearexcept(FE_ALL_EXCEPT); - errno = 0; + sys::llvm_fenv_clearexcept(); V = NativeFP(V); - if (errno != 0 || - fetestexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)) { - feclearexcept(FE_ALL_EXCEPT); - errno = 0; + if (sys::llvm_fenv_testexcept()) { + sys::llvm_fenv_clearexcept(); return 0; } @@ -1060,13 +1082,10 @@ static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, static Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), double V, double W, const Type *Ty) { - feclearexcept(FE_ALL_EXCEPT); - errno = 0; + sys::llvm_fenv_clearexcept(); V = NativeFP(V, W); - if (errno != 0 || - fetestexcept(FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)) { - feclearexcept(FE_ALL_EXCEPT); - errno = 0; + if (sys::llvm_fenv_testexcept()) { + sys::llvm_fenv_clearexcept(); return 0; } @@ -1100,6 +1119,13 @@ llvm::ConstantFoldCall(Function *F, if (!Ty->isFloatTy() && !Ty->isDoubleTy()) return 0; + + /// We only fold functions with finite arguments. Folding NaN and inf is + /// likely to be aborted with an exception anyway, and some host libms + /// have known errors raising exceptions. + if (Op->getValueAPF().isNaN() || Op->getValueAPF().isInfinity()) + return 0; + /// Currently APFloat versions of these functions do not exist, so we use /// the host native double versions. Float versions are not called /// directly but for all these it is true (float)(f((double)arg)) == @@ -1247,42 +1273,37 @@ llvm::ConstantFoldCall(Function *F, if (ConstantInt *Op2 = dyn_cast(Operands[1])) { switch (F->getIntrinsicID()) { default: break; - case Intrinsic::uadd_with_overflow: { - Constant *Res = ConstantExpr::getAdd(Op1, Op2); // result. - Constant *Ops[] = { - Res, ConstantExpr::getICmp(CmpInst::ICMP_ULT, Res, Op1) // overflow. - }; - return ConstantStruct::get(F->getContext(), Ops, 2, false); - } - case Intrinsic::usub_with_overflow: { - Constant *Res = ConstantExpr::getSub(Op1, Op2); // result. + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::smul_with_overflow: { + APInt Res; + bool Overflow; + switch (F->getIntrinsicID()) { + default: assert(0 && "Invalid case"); + case Intrinsic::sadd_with_overflow: + Res = Op1->getValue().sadd_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::uadd_with_overflow: + Res = Op1->getValue().uadd_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::ssub_with_overflow: + Res = Op1->getValue().ssub_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::usub_with_overflow: + Res = Op1->getValue().usub_ov(Op2->getValue(), Overflow); + break; + case Intrinsic::smul_with_overflow: + Res = Op1->getValue().smul_ov(Op2->getValue(), Overflow); + break; + } Constant *Ops[] = { - Res, ConstantExpr::getICmp(CmpInst::ICMP_UGT, Res, Op1) // overflow. + ConstantInt::get(F->getContext(), Res), + ConstantInt::get(Type::getInt1Ty(F->getContext()), Overflow) }; return ConstantStruct::get(F->getContext(), Ops, 2, false); } - case Intrinsic::sadd_with_overflow: { - Constant *Res = ConstantExpr::getAdd(Op1, Op2); // result. - Constant *Overflow = ConstantExpr::getSelect( - ConstantExpr::getICmp(CmpInst::ICMP_SGT, - ConstantInt::get(Op1->getType(), 0), Op1), - ConstantExpr::getICmp(CmpInst::ICMP_SGT, Res, Op2), - ConstantExpr::getICmp(CmpInst::ICMP_SLT, Res, Op2)); // overflow. - - Constant *Ops[] = { Res, Overflow }; - return ConstantStruct::get(F->getContext(), Ops, 2, false); - } - case Intrinsic::ssub_with_overflow: { - Constant *Res = ConstantExpr::getSub(Op1, Op2); // result. - Constant *Overflow = ConstantExpr::getSelect( - ConstantExpr::getICmp(CmpInst::ICMP_SGT, - ConstantInt::get(Op2->getType(), 0), Op2), - ConstantExpr::getICmp(CmpInst::ICMP_SLT, Res, Op1), - ConstantExpr::getICmp(CmpInst::ICMP_SGT, Res, Op1)); // overflow. - - Constant *Ops[] = { Res, Overflow }; - return ConstantStruct::get(F->getContext(), Ops, 2, false); - } } }