diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1449,6 +1449,22 @@ Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); AttributeList Attrs = Pow->getCalledFunction()->getAttributes(); + AttributeList ConstantBaseExpAttrs = + AttributeList() + .addAttributes(B.getContext(), AttributeList::FunctionIndex, + Attrs.getAttributes(AttributeList::FunctionIndex)) + .addAttributes(B.getContext(), AttributeList::ReturnIndex, + Attrs.getAttributes(AttributeList::ReturnIndex)) + .addAttributes(B.getContext(), AttributeList::FirstArgIndex + 0, + Attrs.getAttributes(AttributeList::FirstArgIndex + 1)); + // Where we combine the two pow parameters in some way, it's not trivial to + // determine which attributes should belong to the output. + AttributeList GenericExpAttrs = + AttributeList() + .addAttributes(B.getContext(), AttributeList::FunctionIndex, + Attrs.getAttributes(AttributeList::FunctionIndex)) + .addAttributes(B.getContext(), AttributeList::ReturnIndex, + Attrs.getAttributes(AttributeList::ReturnIndex)); Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); bool Ignored; @@ -1552,7 +1568,7 @@ FMul, "exp2"); else return emitUnaryFloatFnCall(FMul, TLI, LibFunc_exp2, LibFunc_exp2f, - LibFunc_exp2l, B, Attrs); + LibFunc_exp2l, B, GenericExpAttrs); } } @@ -1561,7 +1577,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, ConstantBaseExpAttrs); // pow(x, y) -> exp2(log2(x) * y) if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && BaseF->isFiniteNonZero() && @@ -1584,7 +1600,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, GenericExpAttrs); } } @@ -1616,6 +1632,14 @@ Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) { Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); AttributeList Attrs = Pow->getCalledFunction()->getAttributes(); + AttributeList SqrtAttrs = + AttributeList() + .addAttributes(B.getContext(), AttributeList::FunctionIndex, + Attrs.getAttributes(AttributeList::FunctionIndex)) + .addAttributes(B.getContext(), AttributeList::ReturnIndex, + Attrs.getAttributes(AttributeList::ReturnIndex)) + .addAttributes(B.getContext(), AttributeList::FirstArgIndex + 0, + Attrs.getAttributes(AttributeList::FirstArgIndex + 0)); Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); @@ -1629,7 +1653,7 @@ if (ExpoF->isNegative() && (!Pow->hasApproxFunc() && !Pow->hasAllowReassoc())) return nullptr; - Sqrt = getSqrtCall(Base, Attrs, Pow->doesNotAccessMemory(), Mod, B, TLI); + Sqrt = getSqrtCall(Base, SqrtAttrs, Pow->doesNotAccessMemory(), Mod, B, TLI); if (!Sqrt) return nullptr; @@ -1798,10 +1822,25 @@ // Turn exp2(uitofp(x)) -> ldexp(1.0, zext(x)) if sizeof(x) < 32 if ((isa(Op) || isa(Op)) && hasFloatFn(TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl)) { - if (Value *Exp = getIntToFPVal(Op, B)) + if (Value *Exp = getIntToFPVal(Op, B)) { + AttributeList Attrs = CI->getCalledFunction()->getAttributes(); + AttributeList LdexpAttrs = + AttributeList() + .addAttributes(B.getContext(), AttributeList::FunctionIndex, + Attrs.getAttributes(AttributeList::FunctionIndex)) + .addAttributes(B.getContext(), AttributeList::ReturnIndex, + Attrs.getAttributes(AttributeList::ReturnIndex)) + .addAttributes( + B.getContext(), AttributeList::FirstArgIndex + 0, + Attrs.getAttributes(AttributeList::FirstArgIndex + 0)) + .addAttributes( + B.getContext(), AttributeList::FirstArgIndex + 1, + Attrs.getAttributes(AttributeList::FirstArgIndex + 0)); + return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, - LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, - B, CI->getCalledFunction()->getAttributes()); + LibFunc_ldexp, LibFunc_ldexpf, + LibFunc_ldexpl, B, LdexpAttrs); + } } return Ret; diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll --- a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll @@ -175,6 +175,28 @@ ret i32 %y } +declare inreg double @pow(double inreg, double inreg) +declare inreg double @exp2(double inreg) + +; check to make sure parameter attributes are correctly applied +define double @fake_exp2(double %x) { +; CHECK-LABEL: @fake_exp2( +; CHECK-NEXT: [[Y:%.*]] = call inreg double @exp2(double inreg %x) +; CHECK-NEXT: ret double [[Y]] + + %y = call inreg double @pow(double inreg 2.0, double inreg %x) + ret double %y +} +define double @fake_ldexp(i32 %x) { +; CHECK-LABEL: @fake_ldexp( +; CHECK-NEXT: [[Z:%.*]] = call inreg double @ldexp(double inreg 1.0{{.*}}, i32 inreg %x) +; CHECK-NEXT: ret double [[Z]] + + %y = sitofp i32 %x to double + %z = call inreg double @exp2(double %y) + ret double %z +} + attributes #0 = { nobuiltin } attributes #1 = { builtin }