From 472684eaf5b3e8aba189b38956912b4ee802c526 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Mon, 9 Jan 2017 21:55:23 +0000 Subject: [PATCH] [SimplifyLibCalls] pow(x, -0.5) -> 1.0 / sqrt(x). Differential Revision: https://reviews.llvm.org/D28479 llvm-svn: 291486 --- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 18 ++++++++++++++++++ llvm/test/Transforms/InstCombine/pow-sqrt.ll | 11 ++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 11d54bcf4f89d..5237ce5b399ba 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1074,6 +1074,24 @@ Value *LibCallSimplifier::optimizePow(CallInst *CI, IRBuilder<> &B) { if (Op2C->getValueAPF().isZero()) // pow(x, 0.0) -> 1.0 return ConstantFP::get(CI->getType(), 1.0); + if (Op2C->isExactlyValue(-0.5) && + hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt, LibFunc::sqrtf, + LibFunc::sqrtl)) { + // If -ffast-math: + // pow(x, -0.5) -> 1.0 / sqrt(x) + if (CI->hasUnsafeAlgebra()) { + IRBuilder<>::FastMathFlagGuard Guard(B); + B.setFastMathFlags(CI->getFastMathFlags()); + + // Here we cannot lower to an intrinsic because C99 sqrt() and llvm.sqrt + // are not guaranteed to have the same semantics. + Value *Sqrt = emitUnaryFloatFnCall(Op1, TLI->getName(LibFunc::sqrt), B, + Callee->getAttributes()); + + return B.CreateFDiv(ConstantFP::get(CI->getType(), 1.0), Sqrt, "sqrtrecip"); + } + } + if (Op2C->isExactlyValue(0.5) && hasUnaryFloatFn(TLI, Op2->getType(), LibFunc::sqrt, LibFunc::sqrtf, LibFunc::sqrtl) && diff --git a/llvm/test/Transforms/InstCombine/pow-sqrt.ll b/llvm/test/Transforms/InstCombine/pow-sqrt.ll index 1e6166c5f1142..52175f1b12479 100644 --- a/llvm/test/Transforms/InstCombine/pow-sqrt.ll +++ b/llvm/test/Transforms/InstCombine/pow-sqrt.ll @@ -9,5 +9,14 @@ define double @pow_half(double %x) { ; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x) ; CHECK-NEXT: ret double %sqrt -declare double @llvm.pow.f64(double, double) +define double @pow_neghalf(double %x) { + %pow = call fast double @llvm.pow.f64(double %x, double -5.000000e-01) + ret double %pow +} +; CHECK-LABEL: define double @pow_neghalf( +; CHECK-NEXT: %sqrt = call fast double @sqrt(double %x) #0 +; CHECK-NEXT: %sqrtrecip = fdiv fast double 1.000000e+00, %sqrt +; CHECK-NEXT: ret double %sqrtrecip + +declare double @llvm.pow.f64(double, double)