X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FAnalysis%2FConstantFolding.cpp;h=55a10d716b95503c59e0a8c5791198d4f88394e2;hb=0e3fae27a1634f51943d06588e32a550dae6a4b9;hp=70ee9ddfa605031311698c980457f7116bad245c;hpb=3ee0af35842999c1781052fe74fdcb19997de950;p=oota-llvm.git diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index 70ee9ddfa60..55a10d716b9 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -467,7 +467,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C, // If this load comes from anywhere in a constant global, and if the global // is all undef or zero, we know what it loads. - if (GlobalVariable *GV = dyn_cast(CE->getUnderlyingObject())){ + if (GlobalVariable *GV = dyn_cast(GetUnderlyingObject(CE))){ if (GV->isConstant() && GV->hasDefinitiveInitializer()) { const Type *ResTy = cast(C->getType())->getElementType(); if (GV->getInitializer()->isNullValue()) @@ -568,16 +568,35 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps, Constant *Ptr = Ops[0]; if (!TD || !cast(Ptr->getType())->getElementType()->isSized()) return 0; - - unsigned BitWidth = - TD->getTypeSizeInBits(TD->getIntPtrType(Ptr->getContext())); + + const Type *IntPtrTy = TD->getIntPtrType(Ptr->getContext()); // If this is a constant expr gep that is effectively computing an // "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12' for (unsigned i = 1; i != NumOps; ++i) - if (!isa(Ops[i])) + if (!isa(Ops[i])) { + + // If this is "gep i8* Ptr, (sub 0, V)", fold this as: + // "inttoptr (sub (ptrtoint Ptr), V)" + if (NumOps == 2 && + cast(ResultTy)->getElementType()->isIntegerTy(8)) { + ConstantExpr *CE = dyn_cast(Ops[1]); + assert((CE == 0 || CE->getType() == IntPtrTy) && + "CastGEPIndices didn't canonicalize index types!"); + if (CE && CE->getOpcode() == Instruction::Sub && + CE->getOperand(0)->isNullValue()) { + Constant *Res = ConstantExpr::getPtrToInt(Ptr, CE->getType()); + Res = ConstantExpr::getSub(Res, CE->getOperand(1)); + Res = ConstantExpr::getIntToPtr(Res, ResultTy); + if (ConstantExpr *ResCE = dyn_cast(Res)) + Res = ConstantFoldConstantExpression(ResCE, TD); + return Res; + } + } return 0; + } + unsigned BitWidth = TD->getTypeSizeInBits(IntPtrTy); APInt Offset = APInt(BitWidth, TD->getIndexedOffset(Ptr->getType(), (Value**)Ops+1, NumOps-1)); @@ -610,10 +629,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); @@ -1030,6 +1047,14 @@ llvm::canConstantFoldCallTo(const Function *F) { case Intrinsic::smul_with_overflow: case Intrinsic::convert_from_fp16: case Intrinsic::convert_to_fp16: + case Intrinsic::x86_sse_cvtss2si: + case Intrinsic::x86_sse_cvtss2si64: + case Intrinsic::x86_sse_cvttss2si: + case Intrinsic::x86_sse_cvttss2si64: + case Intrinsic::x86_sse2_cvtsd2si: + case Intrinsic::x86_sse2_cvtsd2si64: + case Intrinsic::x86_sse2_cvttsd2si: + case Intrinsic::x86_sse2_cvttsd2si64: return true; default: return false; @@ -1099,6 +1124,36 @@ static Constant *ConstantFoldBinaryFP(double (*NativeFP)(double, double), return 0; // dummy return to suppress warning } +/// ConstantFoldConvertToInt - Attempt to an SSE floating point to integer +/// conversion of a constant floating point. If roundTowardZero is false, the +/// default IEEE rounding is used (toward nearest, ties to even). This matches +/// the behavior of the non-truncating SSE instructions in the default rounding +/// mode. The desired integer type Ty is used to select how many bits are +/// available for the result. Returns null if the conversion cannot be +/// performed, otherwise returns the Constant value resulting from the +/// conversion. +static Constant *ConstantFoldConvertToInt(ConstantFP *Op, bool roundTowardZero, + const Type *Ty) { + assert(Op && "Called with NULL operand"); + APFloat Val(Op->getValueAPF()); + + // All of these conversion intrinsics form an integer of at most 64bits. + unsigned ResultWidth = cast(Ty)->getBitWidth(); + assert(ResultWidth <= 64 && + "Can only constant fold conversions to 64 and 32 bit ints"); + + uint64_t UIntVal; + bool isExact = false; + APFloat::roundingMode mode = roundTowardZero? APFloat::rmTowardZero + : APFloat::rmNearestTiesToEven; + APFloat::opStatus status = Val.convertToInteger(&UIntVal, ResultWidth, + /*isSigned=*/true, mode, + &isExact); + if (status != APFloat::opOK && status != APFloat::opInexact) + return 0; + return ConstantInt::get(Ty, UIntVal, /*isSigned=*/true); +} + /// ConstantFoldCall - Attempt to constant fold a call to the specified function /// with the specified arguments, returning null if unsuccessful. Constant * @@ -1110,7 +1165,7 @@ llvm::ConstantFoldCall(Function *F, const Type *Ty = F->getReturnType(); if (NumOperands == 1) { if (ConstantFP *Op = dyn_cast(Operands[0])) { - if (Name == "llvm.convert.to.fp16") { + if (F->getIntrinsicID() == Intrinsic::convert_to_fp16) { APFloat Val(Op->getValueAPF()); bool lost = false; @@ -1168,8 +1223,8 @@ llvm::ConstantFoldCall(Function *F, return ConstantFoldFP(log, V, Ty); else if (Name == "log10" && V > 0) return ConstantFoldFP(log10, V, Ty); - else if (Name == "llvm.sqrt.f32" || - Name == "llvm.sqrt.f64") { + else if (F->getIntrinsicID() == Intrinsic::sqrt && + (Ty->isFloatTy() || Ty->isDoubleTy())) { if (V >= -0.0) return ConstantFoldFP(sqrt, V, Ty); else // Undefined @@ -1199,18 +1254,18 @@ llvm::ConstantFoldCall(Function *F, } return 0; } - - + if (ConstantInt *Op = dyn_cast(Operands[0])) { - if (Name.startswith("llvm.bswap")) + switch (F->getIntrinsicID()) { + case Intrinsic::bswap: return ConstantInt::get(F->getContext(), Op->getValue().byteSwap()); - else if (Name.startswith("llvm.ctpop")) + case Intrinsic::ctpop: return ConstantInt::get(Ty, Op->getValue().countPopulation()); - else if (Name.startswith("llvm.cttz")) + case Intrinsic::cttz: return ConstantInt::get(Ty, Op->getValue().countTrailingZeros()); - else if (Name.startswith("llvm.ctlz")) + case Intrinsic::ctlz: return ConstantInt::get(Ty, Op->getValue().countLeadingZeros()); - else if (Name == "llvm.convert.from.fp16") { + case Intrinsic::convert_from_fp16: { APFloat Val(Op->getValue()); bool lost = false; @@ -1218,24 +1273,44 @@ llvm::ConstantFoldCall(Function *F, Val.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &lost); // Conversion is always precise. - status = status; + (void)status; assert(status == APFloat::opOK && !lost && "Precision lost during fp16 constfolding"); return ConstantFP::get(F->getContext(), Val); } - return 0; + default: + return 0; + } } - + + if (ConstantVector *Op = dyn_cast(Operands[0])) { + switch (F->getIntrinsicID()) { + default: break; + case Intrinsic::x86_sse_cvtss2si: + case Intrinsic::x86_sse_cvtss2si64: + case Intrinsic::x86_sse2_cvtsd2si: + case Intrinsic::x86_sse2_cvtsd2si64: + if (ConstantFP *FPOp = dyn_cast(Op->getOperand(0))) + return ConstantFoldConvertToInt(FPOp, /*roundTowardZero=*/false, Ty); + case Intrinsic::x86_sse_cvttss2si: + case Intrinsic::x86_sse_cvttss2si64: + case Intrinsic::x86_sse2_cvttsd2si: + case Intrinsic::x86_sse2_cvttsd2si64: + if (ConstantFP *FPOp = dyn_cast(Op->getOperand(0))) + return ConstantFoldConvertToInt(FPOp, /*roundTowardZero=*/true, Ty); + } + } + if (isa(Operands[0])) { - if (Name.startswith("llvm.bswap")) + if (F->getIntrinsicID() == Intrinsic::bswap) return Operands[0]; return 0; } return 0; } - + if (NumOperands == 2) { if (ConstantFP *Op1 = dyn_cast(Operands[0])) { if (!Ty->isFloatTy() && !Ty->isDoubleTy()) @@ -1258,11 +1333,11 @@ llvm::ConstantFoldCall(Function *F, if (Name == "atan2") return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty); } else if (ConstantInt *Op2C = dyn_cast(Operands[1])) { - if (Name == "llvm.powi.f32") + if (F->getIntrinsicID() == Intrinsic::powi && Ty->isFloatTy()) return ConstantFP::get(F->getContext(), APFloat((float)std::pow((float)Op1V, (int)Op2C->getZExtValue()))); - if (Name == "llvm.powi.f64") + if (F->getIntrinsicID() == Intrinsic::powi && Ty->isDoubleTy()) return ConstantFP::get(F->getContext(), APFloat((double)std::pow((double)Op1V, (int)Op2C->getZExtValue()))); @@ -1315,4 +1390,3 @@ llvm::ConstantFoldCall(Function *F, } return 0; } -