Index: llvm/lib/Transforms/Utils/BuildLibCalls.cpp =================================================================== --- llvm/lib/Transforms/Utils/BuildLibCalls.cpp +++ llvm/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1269,7 +1269,7 @@ assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall"); Module *M = B.GetInsertBlock()->getModule(); - FunctionCallee Callee = M->getOrInsertFunction(Name, Op1->getType(), + FunctionCallee Callee = M->getOrInsertFunction(Name, Attrs, Op1->getType(), Op1->getType(), Op2->getType()); CallInst *CI = B.CreateCall(Callee, { Op1, Op2 }, Name); Index: llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1450,12 +1450,25 @@ return nullptr; } +// Return an AttributeList containing SExt or ZExt for argument ArgNo, +// depending on the opcode of Op. +static AttributeList getExtAttrForArg(unsigned ArgNo, Value *Op) { + assert((isa(Op) || isa(Op)) && + "Op expected to be an sitofp/uitfp instruction."); + Attribute::AttrKind A = isa(Op) ? Attribute::AttrKind::SExt + : Attribute::AttrKind::ZExt; + SmallVector, 1> ArgAttrs; + ArgAttrs.push_back(std::make_pair(AttributeList::FirstArgIndex + ArgNo, + Attribute::get(Op->getContext(), A))); + return AttributeList::get(Op->getContext(), ArgAttrs); +} + /// Use exp{,2}(x * y) for pow(exp{,2}(x), y); /// ldexp(1.0, x) for pow(2.0, itofp(x)); exp2(n * x) for pow(2.0 ** n, x); /// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x). Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); - AttributeList Attrs; // Attributes are only meaningful on the original call + AttributeList NoAttrs; Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); bool Ignored; @@ -1536,8 +1549,8 @@ hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *ExpoI = getIntToFPVal(Expo, B)) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), ExpoI, TLI, - LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, - B, Attrs); + LibFunc_ldexp, LibFunc_ldexpf, + LibFunc_ldexpl, B, getExtAttrForArg(1, Expo)); } // pow(2.0 ** n, x) -> exp2(n * x) @@ -1559,7 +1572,7 @@ FMul, "exp2"); else return emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, - LibFunc_exp2l, B, Attrs); + LibFunc_exp2l, B, NoAttrs); } } @@ -1568,7 +1581,7 @@ if (match(Base, m_SpecificFP(10.0)) && hasFloatFn(TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) return emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f, - LibFunc_exp10l, B, Attrs); + LibFunc_exp10l, B, NoAttrs); // pow(x, y) -> exp2(log2(x) * y) if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && BaseF->isFiniteNonZero() && @@ -1591,7 +1604,7 @@ FMul, "exp2"); else if (hasFloatFn(TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) return emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, - LibFunc_exp2l, B, Attrs); + LibFunc_exp2l, B, NoAttrs); } } @@ -1803,7 +1816,6 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { Function *Callee = CI->getCalledFunction(); - AttributeList Attrs; // Attributes are only meaningful on the original call StringRef Name = Callee->getName(); Value *Ret = nullptr; if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) && @@ -1819,8 +1831,8 @@ hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { if (Value *Exp = getIntToFPVal(Op, B)) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, - LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, - B, Attrs); + LibFunc_ldexp, LibFunc_ldexpf, + LibFunc_ldexpl, B, getExtAttrForArg(1, Op)); } return Ret; Index: llvm/test/Transforms/InstCombine/pow_fp_int.ll =================================================================== --- llvm/test/Transforms/InstCombine/pow_fp_int.ll +++ llvm/test/Transforms/InstCombine/pow_fp_int.ll @@ -51,7 +51,7 @@ define double @pow_sitofp_double_const_base_2_fast(i32 %x) { ; CHECK-LABEL: @pow_sitofp_double_const_base_2_fast( -; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) +; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 signext [[X:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double ; CHECK-NEXT: ret double [[RES]] ; @@ -78,7 +78,7 @@ define double @pow_uitofp_const_base_2_fast(i31 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_2_fast( ; CHECK-NEXT: [[TMP1:%.*]] = zext i31 [[X:%.*]] to i32 -; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) +; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 zeroext [[TMP1]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double ; CHECK-NEXT: ret double [[RES]] ; @@ -343,7 +343,7 @@ define double @pow_sitofp_const_base_2_no_fast(i32 %x) { ; CHECK-LABEL: @pow_sitofp_const_base_2_no_fast( -; CHECK-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) +; CHECK-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 signext [[X:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double ; CHECK-NEXT: ret double [[RES]] ; Index: llvm/test/Transforms/InstCombine/simplify-libcalls.ll =================================================================== --- llvm/test/Transforms/InstCombine/simplify-libcalls.ll +++ llvm/test/Transforms/InstCombine/simplify-libcalls.ll @@ -189,7 +189,7 @@ } define double @fake_ldexp(i32 %x) { ; CHECK-LABEL: @fake_ldexp( -; CHECK-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 %x) +; CHECK-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 signext %x) ; CHECK-NEXT: ret double [[Z]] %y = sitofp i32 %x to double