[llvm] r340948 - [InstCombine] Expand the simplification of pow() with nested exp{, 2}()

Evandro Menezes via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 29 10:59:48 PDT 2018


Author: evandro
Date: Wed Aug 29 10:59:48 2018
New Revision: 340948

URL: http://llvm.org/viewvc/llvm-project?rev=340948&view=rev
Log:
[InstCombine] Expand the simplification of pow() with nested exp{,2}()

Expand the simplification of `pow(exp{,2}(x), y)` to all FP types.

This improvement helps some benchmarks in SPEC CPU2000 and CPU2006, such as
252.eon, 447.dealII, 453.povray.  Otherwise, no significant regressions on
x86-64 or A64.

Differential revision: https://reviews.llvm.org/D51195

Modified:
    llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/trunk/test/Transforms/InstCombine/pow-exp.ll

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp?rev=340948&r1=340947&r2=340948&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp Wed Aug 29 10:59:48 2018
@@ -1212,14 +1212,31 @@ Value *LibCallSimplifier::replacePowWith
     LibFunc LibFn;
 
     Function *CalleeFn = BaseFn->getCalledFunction();
-    if (CalleeFn && TLI->getLibFunc(CalleeFn->getName(), LibFn) &&
-        (LibFn == LibFunc_exp || LibFn == LibFunc_exp2) && TLI->has(LibFn)) {
+    if (CalleeFn &&
+        TLI->getLibFunc(CalleeFn->getName(), LibFn) && TLI->has(LibFn)) {
+      StringRef ExpName;
+      Intrinsic::ID ID;
       Value *ExpFn;
 
+      switch (LibFn) {
+      default:
+        return nullptr;
+      case LibFunc_expf:  case LibFunc_exp:  case LibFunc_expl:
+        ExpName = TLI->getName(LibFunc_exp);
+        ID = Intrinsic::exp;
+        break;
+      case LibFunc_exp2f: case LibFunc_exp2: case LibFunc_exp2l:
+        ExpName = TLI->getName(LibFunc_exp2);
+        ID = Intrinsic::exp2;
+        break;
+      }
+
       // Create new exp{,2}() with the product as its argument.
       Value *FMul = B.CreateFMul(BaseFn->getArgOperand(0), Expo, "mul");
-      ExpFn = emitUnaryFloatFnCall(FMul, CalleeFn->getName(), B,
-                                   BaseFn->getAttributes());
+      ExpFn = BaseFn->doesNotAccessMemory()
+              ? B.CreateCall(Intrinsic::getDeclaration(Mod, ID, Ty),
+                             FMul, ExpName)
+              : emitUnaryFloatFnCall(FMul, ExpName, B, BaseFn->getAttributes());
 
       // Since the new exp{,2}() is different from the original one, dead code
       // elimination cannot be trusted to remove it, since it may have side

Modified: llvm/trunk/test/Transforms/InstCombine/pow-exp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/pow-exp.ll?rev=340948&r1=340947&r2=340948&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/pow-exp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/pow-exp.ll Wed Aug 29 10:59:48 2018
@@ -1,35 +1,32 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 ; RUN: opt < %s -instcombine -S | FileCheck %s
 
-; TODO: Should result in expf(x * y).
 define float @powf_expf(float %x, float %y) {
 ; CHECK-LABEL: @powf_expf(
-; CHECK-NEXT:    [[CALL:%.*]] = call fast float @expf(float [[X:%.*]]) #1
-; CHECK-NEXT:    [[POW:%.*]] = call fast float @llvm.pow.f32(float [[CALL]], float [[Y:%.*]])
-; CHECK-NEXT:    ret float [[POW]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[EXP:%.*]] = call fast float @llvm.exp.f32(float [[MUL]])
+; CHECK-NEXT:    ret float [[EXP]]
 ;
   %call = call fast float @expf(float %x) nounwind readnone
   %pow = call fast float @llvm.pow.f32(float %call, float %y)
   ret float %pow
 }
 
-; TODO: Should result in expf(x * y).
 define float @powf_expf_libcall(float %x, float %y) {
 ; CHECK-LABEL: @powf_expf_libcall(
-; CHECK-NEXT:    [[CALL:%.*]] = call fast float @expf(float [[X:%.*]])
-; CHECK-NEXT:    [[POW:%.*]] = call fast float @powf(float [[CALL]], float [[Y:%.*]])
-; CHECK-NEXT:    ret float [[POW]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[EXPF:%.*]] = call fast float @expf(float [[MUL]])
+; CHECK-NEXT:    ret float [[EXPF]]
 ;
   %call = call fast float @expf(float %x)
   %pow = call fast float @powf(float %call, float %y)
   ret float %pow
 }
 
-; TODO: Should result in intrinsic call to exp().
 define double @pow_exp(double %x, double %y) {
 ; CHECK-LABEL: @pow_exp(
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[EXP:%.*]] = call fast double @exp(double [[MUL]]) #1
+; CHECK-NEXT:    [[EXP:%.*]] = call fast double @llvm.exp.f64(double [[MUL]])
 ; CHECK-NEXT:    ret double [[EXP]]
 ;
   %call = call fast double @exp(double %x) nounwind readnone
@@ -37,11 +34,10 @@ define double @pow_exp(double %x, double
   ret double %pow
 }
 
-; TODO: Should result in intrinsic call to exp().
 define double @pow_exp_not_intrinsic(double %x, double %y) {
 ; CHECK-LABEL: @pow_exp_not_intrinsic(
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[EXP:%.*]] = call fast double @exp(double [[MUL]])
+; CHECK-NEXT:    [[EXP:%.*]] = call fast double @llvm.exp.f64(double [[MUL]])
 ; CHECK-NEXT:    ret double [[EXP]]
 ;
   %call = call fast double @exp(double %x) nounwind readnone
@@ -49,12 +45,11 @@ define double @pow_exp_not_intrinsic(dou
   ret double %pow
 }
 
-; TODO: Should result in expl(x * y).
 define fp128 @powl_expl(fp128 %x, fp128 %y) {
 ; CHECK-LABEL: @powl_expl(
-; CHECK-NEXT:    [[CALL:%.*]] = call fast fp128 @expl(fp128 [[X:%.*]]) #1
-; CHECK-NEXT:    [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]])
-; CHECK-NEXT:    ret fp128 [[POW]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast fp128 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[EXP:%.*]] = call fast fp128 @llvm.exp.f128(fp128 [[MUL]])
+; CHECK-NEXT:    ret fp128 [[EXP]]
 ;
   %call = call fast fp128 @expl(fp128 %x) nounwind readnone
   %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)
@@ -72,35 +67,32 @@ define fp128 @powl_expl_not_fast(fp128 %
   ret fp128 %pow
 }
 
-; TODO: Should result in exp2f(x * y).
 define float @powf_exp2f(float %x, float %y) {
 ; CHECK-LABEL: @powf_exp2f(
-; CHECK-NEXT:    [[CALL:%.*]] = call fast float @exp2f(float [[X:%.*]]) #1
-; CHECK-NEXT:    [[POW:%.*]] = call fast float @llvm.pow.f32(float [[CALL]], float [[Y:%.*]])
-; CHECK-NEXT:    ret float [[POW]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]])
+; CHECK-NEXT:    ret float [[EXP2]]
 ;
   %call = call fast float @exp2f(float %x) nounwind readnone
   %pow = call fast float @llvm.pow.f32(float %call, float %y)
   ret float %pow
 }
 
-; TODO: Should result in exp2f(x * y).
 define float @powf_exp2f_not_intrinsic(float %x, float %y) {
 ; CHECK-LABEL: @powf_exp2f_not_intrinsic(
-; CHECK-NEXT:    [[CALL:%.*]] = call fast float @exp2f(float [[X:%.*]]) #1
-; CHECK-NEXT:    [[POW:%.*]] = call fast float @powf(float [[CALL]], float [[Y:%.*]]) #1
-; CHECK-NEXT:    ret float [[POW]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]])
+; CHECK-NEXT:    ret float [[EXP2]]
 ;
   %call = call fast float @exp2f(float %x) nounwind readnone
   %pow = call fast float @powf(float %call, float %y) nounwind readnone
   ret float %pow
 }
 
-; TODO: Should result in intrinsic call to exp2().
 define double @pow_exp2(double %x, double %y) {
 ; CHECK-LABEL: @pow_exp2(
 ; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[EXP2:%.*]] = call fast double @exp2(double [[MUL]]) #1
+; CHECK-NEXT:    [[EXP2:%.*]] = call fast double @llvm.exp2.f64(double [[MUL]])
 ; CHECK-NEXT:    ret double [[EXP2]]
 ;
   %call = call fast double @exp2(double %x) nounwind readnone
@@ -110,7 +102,7 @@ define double @pow_exp2(double %x, doubl
 
 define double @pow_exp2_libcall(double %x, double %y) {
 ; CHECK-LABEL: @pow_exp2_libcall(
-; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[X]], [[Y:%.*]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast double [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[EXP2:%.*]] = call fast double @exp2(double [[MUL]])
 ; CHECK-NEXT:    ret double [[EXP2]]
 ;
@@ -119,12 +111,11 @@ define double @pow_exp2_libcall(double %
   ret double %pow
 }
 
-; TODO: Should result in intrinsic call to exp2l().
 define fp128 @powl_exp2l(fp128 %x, fp128 %y) {
 ; CHECK-LABEL: @powl_exp2l(
-; CHECK-NEXT:    [[CALL:%.*]] = call fast fp128 @exp2l(fp128 [[X:%.*]]) #1
-; CHECK-NEXT:    [[POW:%.*]] = call fast fp128 @llvm.pow.f128(fp128 [[CALL]], fp128 [[Y:%.*]])
-; CHECK-NEXT:    ret fp128 [[POW]]
+; CHECK-NEXT:    [[MUL:%.*]] = fmul fast fp128 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[EXP2:%.*]] = call fast fp128 @llvm.exp2.f128(fp128 [[MUL]])
+; CHECK-NEXT:    ret fp128 [[EXP2]]
 ;
   %call = call fast fp128 @exp2l(fp128 %x) nounwind readnone
   %pow = call fast fp128 @llvm.pow.f128(fp128 %call, fp128 %y)




More information about the llvm-commits mailing list