[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