Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1529,10 +1529,6 @@ bool AllowApprox = Pow->hasApproxFunc(); bool Ignored; - // Bail out if simplifying libcalls to pow() is disabled. - if (!hasFloatFn(TLI, Ty, LibFunc_pow, LibFunc_powf, LibFunc_powl)) - return nullptr; - // Propagate the math semantics from the call to any created instructions. IRBuilder<>::FastMathFlagGuard Guard(B); B.setFastMathFlags(Pow->getFastMathFlags()); @@ -1573,6 +1569,8 @@ if (Value *Sqrt = replacePowWithSqrt(Pow, B)) return Sqrt; + bool HasLibPow = hasFloatFn(TLI, Ty, LibFunc_pow, LibFunc_powf, LibFunc_powl); + // pow(x, n) -> x * x * x * ... const APFloat *ExpoF; if (AllowApprox && match(Expo, m_APFloat(ExpoF))) { @@ -1608,6 +1606,10 @@ InnerChain[1] = Base; InnerChain[2] = B.CreateFMul(Base, Base, "square"); + // Bail out if simplifying libcalls to pow() is disabled. + if (!HasLibPow) + return nullptr; + // We cannot readily convert a non-double type (like float) to a double. // So we first convert it to something which could be converted to double. ExpoA.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &Ignored); @@ -1624,6 +1626,10 @@ return FMul; } + // Bail out if simplifying libcalls to pow() is disabled. + if (!HasLibPow) + return nullptr; + APSInt IntExpo(32, /*isUnsigned=*/false); // powf(x, n) -> powi(x, n) if n is a constant signed integer value if (ExpoF->isInteger() && @@ -1634,6 +1640,10 @@ } } + // Bail out if simplifying libcalls to pow() is disabled. + if (!HasLibPow) + return nullptr; + // powf(x, itofp(y)) -> powi(x, y) if (AllowApprox && (isa(Expo) || isa(Expo))) { if (Value *ExpoI = getIntToFPVal(Expo, B)) Index: test/Transforms/InstCombine/pow-amdgcn.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/pow-amdgcn.ll @@ -0,0 +1,55 @@ +; RUN: opt < %s -mtriple=amdgcn-- -targetlibinfo -instcombine -S | FileCheck %s + +; Check that a transform of llvm.pow to multiplies or divides happens for amdgcn (for which +; TLI says no lib functions). + +define float @pow_of_1(float %x) { +; CHECK-LABEL: @pow_of_1( +; CHECK-NEXT: ret float +; + %pow = call float @llvm.pow.f32(float 1.0, float %x) + ret float %pow +} + +define float @pow_minus_1(float %x) { +; CHECK-LABEL: @pow_minus_1( +; CHECK: = fdiv float +; + %pow = call float @llvm.pow.f32(float %x, float -1.0) + ret float %pow +} + +define float @pow_0(float %x) { +; CHECK-LABEL: @pow_0( +; CHECK-NEXT: ret float +; + %pow = call float @llvm.pow.f32(float %x, float 0.0) + ret float %pow +} + +define float @pow_1(float %x) { +; CHECK-LABEL: @pow_1( +; CHECK-NEXT: ret float +; + %pow = call float @llvm.pow.f32(float %x, float 1.0) + ret float %pow +} + +define float @pow_half(float %x) { +; CHECK-LABEL: @pow_half( +; CHECK: @llvm.sqrt +; + %pow = call float @llvm.pow.f32(float %x, float 0.5) + ret float %pow +} + +define float @pow_2(float %x) { +; CHECK-LABEL: @pow_2( +; CHECK: = fmul float +; + %pow = call float @llvm.pow.f32(float %x, float 2.0) + ret float %pow +} + +declare float @llvm.pow.f32(float, float) +