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 @@ -1563,9 +1563,13 @@ return emitUnaryFloatFnCall(Expo, TLI, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l, B, Attrs); - // pow(n, x) -> exp2(log2(n) * x) - if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && Pow->hasNoInfs() && - BaseF->isFiniteNonZero() && !BaseF->isNegative()) { + // pow(x, y) -> exp2(log2(x) * y) + // We can do this transformation for any positive finite n except 1.0, because + // pow has this behaviour: + // If x is +1, the result is 1.0 (even if y is a NaN). + // which is hard to preserve if y might be infinite or NaN. + if (Pow->hasApproxFunc() && Pow->hasNoNaNs() && BaseF->isFiniteNonZero() && + !BaseF->isNegative() && !match(Base, m_FPOne())) { Value *Log = nullptr; if (Ty->isFloatTy()) Log = ConstantFP::get(Ty, std::log2(BaseF->convertToFloat())); diff --git a/llvm/test/Transforms/InstCombine/pow-exp.ll b/llvm/test/Transforms/InstCombine/pow-exp.ll --- a/llvm/test/Transforms/InstCombine/pow-exp.ll +++ b/llvm/test/Transforms/InstCombine/pow-exp.ll @@ -400,8 +400,9 @@ define double @pow_ok_base_no_ninf(double %e) { ; CHECK-LABEL: @pow_ok_base_no_ninf( -; CHECK-NEXT: [[CALL:%.*]] = tail call nnan afn double @pow(double 0x3FE6666666666666, double [[E:%.*]]) -; CHECK-NEXT: ret double [[CALL]] +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan afn double [[E:%.*]], 0xBFE0776{{.*}} +; CHECK-NEXT: [[EXP2:%.*]] = call nnan afn double @exp2(double [[MUL]]) +; CHECK-NEXT: ret double [[EXP2]] ; %call = tail call afn nnan double @pow(double 0x3FE6666666666666, double %e) ret double %call