[llvm] r251976 - [SimplifyLibCalls] Add a new transformation: pow(exp(x), y) -> exp(x*y)
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 3 12:32:23 PST 2015
Author: davide
Date: Tue Nov 3 14:32:23 2015
New Revision: 251976
URL: http://llvm.org/viewvc/llvm-project?rev=251976&view=rev
Log:
[SimplifyLibCalls] Add a new transformation: pow(exp(x), y) -> exp(x*y)
This one is enabled only under -ffast-math (due to rounding/overflows)
but allows us to emit shorter code.
Before (on FreeBSD x86-64):
4007f0: 50 push %rax
4007f1: f2 0f 11 0c 24 movsd %xmm1,(%rsp)
4007f6: e8 75 fd ff ff callq 400570 <exp2 at plt>
4007fb: f2 0f 10 0c 24 movsd (%rsp),%xmm1
400800: 58 pop %rax
400801: e9 7a fd ff ff jmpq 400580 <pow at plt>
400806: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
40080d: 00 00 00
After:
4007b0: f2 0f 59 c1 mulsd %xmm1,%xmm0
4007b4: e9 87 fd ff ff jmpq 400540 <exp2 at plt>
4007b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
Differential Revision: http://reviews.llvm.org/D14045
Added:
llvm/trunk/test/Transforms/InstCombine/pow-exp-nofastmath.ll
llvm/trunk/test/Transforms/InstCombine/pow-exp.ll
llvm/trunk/test/Transforms/InstCombine/pow-exp2.ll
Modified:
llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
Modified: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp?rev=251976&r1=251975&r2=251976&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp Tue Nov 3 14:32:23 2015
@@ -1103,6 +1103,32 @@ Value *LibCallSimplifier::optimizePow(Ca
Callee->getAttributes());
}
+ // pow(exp(x), y) -> exp(x*y)
+ // pow(exp2(x), y) -> exp2(x * y)
+ // We enable these only under fast-math. Besides rounding
+ // differences the transformation changes overflow and
+ // underflow behavior quite dramatically.
+ // Example: x = 1000, y = 0.001.
+ // pow(exp(x), y) = pow(inf, 0.001) = inf, whereas exp(x*y) = exp(1).
+ if (canUseUnsafeFPMath(CI->getParent()->getParent())) {
+ if (auto *OpC = dyn_cast<CallInst>(Op1)) {
+ IRBuilder<>::FastMathFlagGuard Guard(B);
+ FastMathFlags FMF;
+ FMF.setUnsafeAlgebra();
+ B.SetFastMathFlags(FMF);
+
+ LibFunc::Func Func;
+ Function *Callee = OpC->getCalledFunction();
+ StringRef FuncName = Callee->getName();
+
+ if (TLI->getLibFunc(FuncName, Func) && TLI->has(Func) &&
+ (Func == LibFunc::exp || Func == LibFunc::exp2))
+ return EmitUnaryFloatFnCall(
+ B.CreateFMul(OpC->getArgOperand(0), Op2, "mul"), FuncName, B,
+ Callee->getAttributes());
+ }
+ }
+
ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
if (!Op2C)
return Ret;
Added: llvm/trunk/test/Transforms/InstCombine/pow-exp-nofastmath.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pow-exp-nofastmath.ll?rev=251976&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/pow-exp-nofastmath.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/pow-exp-nofastmath.ll Tue Nov 3 14:32:23 2015
@@ -0,0 +1,17 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+define double @mypow(double %x, double %y) #0 {
+entry:
+ %call = call double @exp(double %x)
+ %pow = call double @llvm.pow.f64(double %call, double %y)
+ ret double %pow
+}
+
+; CHECK-LABEL: define double @mypow(
+; CHECK: %call = call double @exp(double %x)
+; CHECK: %pow = call double @llvm.pow.f64(double %call, double %y)
+; CHECK: ret double %pow
+; CHECK: }
+
+declare double @exp(double) #1
+declare double @llvm.pow.f64(double, double)
Added: llvm/trunk/test/Transforms/InstCombine/pow-exp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pow-exp.ll?rev=251976&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/pow-exp.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/pow-exp.ll Tue Nov 3 14:32:23 2015
@@ -0,0 +1,19 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+define double @mypow(double %x, double %y) #0 {
+entry:
+ %call = call double @exp(double %x)
+ %pow = call double @llvm.pow.f64(double %call, double %y)
+ ret double %pow
+}
+
+; CHECK-LABEL: define double @mypow(
+; CHECK: %mul = fmul fast double %x, %y
+; CHECK: %exp = call double @exp(double %mul) #0
+; CHECK: ret double %exp
+; CHECK: }
+
+declare double @exp(double) #1
+declare double @llvm.pow.f64(double, double)
+attributes #0 = { "unsafe-fp-math"="true" }
+attributes #1 = { "unsafe-fp-math"="true" }
Added: llvm/trunk/test/Transforms/InstCombine/pow-exp2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pow-exp2.ll?rev=251976&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/pow-exp2.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/pow-exp2.ll Tue Nov 3 14:32:23 2015
@@ -0,0 +1,19 @@
+; RUN: opt < %s -instcombine -S | FileCheck %s
+
+define double @mypow(double %x, double %y) #0 {
+entry:
+ %call = call double @exp2(double %x)
+ %pow = call double @llvm.pow.f64(double %call, double %y)
+ ret double %pow
+}
+
+; CHECK-LABEL: define double @mypow(
+; CHECK: %mul = fmul fast double %x, %y
+; CHECK: %exp2 = call double @exp2(double %mul) #0
+; CHECK: ret double %exp2
+; CHECK: }
+
+declare double @exp2(double) #1
+declare double @llvm.pow.f64(double, double)
+attributes #0 = { "unsafe-fp-math"="true" }
+attributes #1 = { "unsafe-fp-math"="true" }
More information about the llvm-commits
mailing list