Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1529,8 +1529,10 @@ 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)) + // Bail out if simplifying libcalls to pow() is disabled, and the present call + // is pow() rather than llvm.pow. + if (!Callee->isIntrinsic() && + !hasFloatFn(TLI, Ty, LibFunc_pow, LibFunc_powf, LibFunc_powl)) return nullptr; // Propagate the math semantics from the call to any created instructions. Index: test/Transforms/InstCombine/pow-1.ll =================================================================== --- test/Transforms/InstCombine/pow-1.ll +++ test/Transforms/InstCombine/pow-1.ll @@ -38,9 +38,7 @@ define <2 x float> @test_simplify1v(<2 x float> %x) { ; CHECK-LABEL: @test_simplify1v( -; ANY-NEXT: ret <2 x float> -; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; MSVC-NEXT: ret <2 x float> [[POW]] +; CHECK-NEXT: ret <2 x float> ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval @@ -56,9 +54,7 @@ define <2 x double> @test_simplify2v(<2 x double> %x) { ; CHECK-LABEL: @test_simplify2v( -; ANY-NEXT: ret <2 x double> -; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) -; MSVC-NEXT: ret <2 x double> [[POW]] +; CHECK-NEXT: ret <2 x double> ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval @@ -117,7 +113,6 @@ ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[MUL]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] ; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) -; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval @@ -198,9 +193,7 @@ define <2 x float> @test_simplify5v(<2 x float> %x) { ; CHECK-LABEL: @test_simplify5v( -; ANY-NEXT: ret <2 x float> -; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> zeroinitializer) -; MSVC-NEXT: ret <2 x float> [[POW]] +; CHECK-NEXT: ret <2 x float> ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval @@ -216,9 +209,7 @@ define <2 x double> @test_simplify6v(<2 x double> %x) { ; CHECK-LABEL: @test_simplify6v( -; ANY-NEXT: ret <2 x double> -; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> zeroinitializer) -; MSVC-NEXT: ret <2 x double> [[POW]] +; CHECK-NEXT: ret <2 x double> ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -306,9 +297,7 @@ define <2 x float> @test_simplify11v(<2 x float> %x) { ; CHECK-LABEL: @test_simplify11v( -; ANY-NEXT: ret <2 x float> [[X:%.*]] -; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) -; MSVC-NEXT: ret <2 x float> [[POW]] +; CHECK-NEXT: ret <2 x float> [[X:%.*]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval @@ -324,9 +313,7 @@ define <2 x double> @test_simplify12v(<2 x double> %x) { ; CHECK-LABEL: @test_simplify12v( -; ANY-NEXT: ret <2 x double> [[X:%.*]] -; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) -; MSVC-NEXT: ret <2 x double> [[POW]] +; CHECK-NEXT: ret <2 x double> [[X:%.*]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -353,10 +340,8 @@ define <2 x float> @pow2_strictv(<2 x float> %x) { ; CHECK-LABEL: @pow2_strictv( -; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x float> [[X:%.*]], [[X]] -; ANY-NEXT: ret <2 x float> [[SQUARE]] -; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) -; MSVC-NEXT: ret <2 x float> [[POW]] +; CHECK-NEXT: [[SQUARE:%.*]] = fmul <2 x float> [[X:%.*]], [[X]] +; CHECK-NEXT: ret <2 x float> [[SQUARE]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r @@ -373,10 +358,8 @@ define <2 x double> @pow2_double_strictv(<2 x double> %x) { ; CHECK-LABEL: @pow2_double_strictv( -; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x double> [[X:%.*]], [[X]] -; ANY-NEXT: ret <2 x double> [[SQUARE]] -; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) -; MSVC-NEXT: ret <2 x double> [[POW]] +; CHECK-NEXT: [[SQUARE:%.*]] = fmul <2 x double> [[X:%.*]], [[X]] +; CHECK-NEXT: ret <2 x double> [[SQUARE]] ; %r = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r @@ -422,10 +405,8 @@ define <2 x float> @pow_neg1_strictv(<2 x float> %x) { ; CHECK-LABEL: @pow_neg1_strictv( -; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv <2 x float> , [[X:%.*]] -; ANY-NEXT: ret <2 x float> [[RECIPROCAL]] -; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) -; MSVC-NEXT: ret <2 x float> [[POW]] +; CHECK-NEXT: [[RECIPROCAL:%.*]] = fdiv <2 x float> , [[X:%.*]] +; CHECK-NEXT: ret <2 x float> [[RECIPROCAL]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r @@ -442,10 +423,8 @@ define <2 x double> @pow_neg1_double_fastv(<2 x double> %x) { ; CHECK-LABEL: @pow_neg1_double_fastv( -; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast <2 x double> , [[X:%.*]] -; ANY-NEXT: ret <2 x double> [[RECIPROCAL]] -; MSVC-NEXT: [[POW:%.*]] = call fast <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) -; MSVC-NEXT: ret <2 x double> [[POW]] +; CHECK-NEXT: [[RECIPROCAL:%.*]] = fdiv fast <2 x double> , [[X:%.*]] +; CHECK-NEXT: ret <2 x double> [[RECIPROCAL]] ; %r = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r Index: test/Transforms/InstCombine/pow-3.ll =================================================================== --- test/Transforms/InstCombine/pow-3.ll +++ test/Transforms/InstCombine/pow-3.ll @@ -8,8 +8,7 @@ define double @test_simplify_unavailable1(double %x) { ; CHECK-LABEL: @test_simplify_unavailable1( -; CHECK-NEXT: [[RETVAL:%.*]] = call double @llvm.pow.f64(double [[X:%.*]], double 5.000000e-01) -; CHECK-NEXT: ret double [[RETVAL]] +; CHECK-NEXT: = call double @llvm.sqrt.f64 ; %retval = call double @llvm.pow.f64(double %x, double 0.5) ret double %retval 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) +