[llvm] 072b03c - [InstCombine] fold pow(X,Y) / X -> pow(X, Y-1)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 13 14:23:17 PST 2023


Author: Sanjay Patel
Date: 2023-01-13T17:13:46-05:00
New Revision: 072b03c4714ea43af56bbfa6e5a271ef1a1c9e0a

URL: https://github.com/llvm/llvm-project/commit/072b03c4714ea43af56bbfa6e5a271ef1a1c9e0a
DIFF: https://github.com/llvm/llvm-project/commit/072b03c4714ea43af56bbfa6e5a271ef1a1c9e0a.diff

LOG: [InstCombine] fold pow(X,Y) / X -> pow(X, Y-1)

This is one of the patterns suggested in issue #34943.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
    llvm/test/Transforms/InstCombine/fmul-pow.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index d685dd0b7bc0..460731d29c8b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -1666,6 +1666,16 @@ Instruction *InstCombinerImpl::visitFDiv(BinaryOperator &I) {
   if (Instruction *Mul = foldFDivPowDivisor(I, Builder))
     return Mul;
 
+  // pow(X, Y) / X --> pow(X, Y-1)
+  if (I.hasAllowReassoc() &&
+      match(Op0, m_OneUse(m_Intrinsic<Intrinsic::pow>(m_Specific(Op1),
+                                                      m_Value(Y))))) {
+    Value *Y1 =
+        Builder.CreateFAddFMF(Y, ConstantFP::get(I.getType(), -1.0), &I);
+    Value *Pow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, Op1, Y1, &I);
+    return replaceInstUsesWith(I, Pow);
+  }
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstCombine/fmul-pow.ll b/llvm/test/Transforms/InstCombine/fmul-pow.ll
index 598464138414..63458e136074 100644
--- a/llvm/test/Transforms/InstCombine/fmul-pow.ll
+++ b/llvm/test/Transforms/InstCombine/fmul-pow.ll
@@ -61,6 +61,9 @@ define double @pow_ab_a_reassoc_use(double %a, double %b)  {
   ret double %m
 }
 
+; negative test for:
+; pow(a,b) * 1.0/a --> pow(a, b-1) (requires reassoc)
+
 define double @pow_ab_recip_a(double %a, double %b)  {
 ; CHECK-LABEL: @pow_ab_recip_a(
 ; CHECK-NEXT:    [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]
@@ -74,10 +77,12 @@ define double @pow_ab_recip_a(double %a, double %b)  {
   ret double %m
 }
 
+; pow(a,b) / a --> pow(a, b-1) (requires reassoc)
+
 define double @pow_ab_recip_a_reassoc(double %a, double %b)  {
 ; CHECK-LABEL: @pow_ab_recip_a_reassoc(
-; CHECK-NEXT:    [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT:    [[M:%.*]] = fdiv reassoc double [[P]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+00
+; CHECK-NEXT:    [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
 ; CHECK-NEXT:    ret double [[M]]
 ;
   %r = fdiv double 1.0, %a
@@ -86,10 +91,12 @@ define double @pow_ab_recip_a_reassoc(double %a, double %b)  {
   ret double %m
 }
 
+; pow(a,b) / a --> pow(a, b-1) (requires reassoc)
+
 define double @pow_ab_recip_a_reassoc_commute(double %a, double %b)  {
 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_commute(
-; CHECK-NEXT:    [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT:    [[M:%.*]] = fdiv reassoc double [[P]], [[A]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd reassoc double [[B:%.*]], -1.000000e+00
+; CHECK-NEXT:    [[M:%.*]] = call reassoc double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
 ; CHECK-NEXT:    ret double [[M]]
 ;
   %r = fdiv double 1.0, %a
@@ -98,6 +105,8 @@ define double @pow_ab_recip_a_reassoc_commute(double %a, double %b)  {
   ret double %m
 }
 
+; TODO: extra use prevents conversion to fmul, so this needs a 
diff erent pattern match.
+
 define double @pow_ab_recip_a_reassoc_use1(double %a, double %b)  {
 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_use1(
 ; CHECK-NEXT:    [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]
@@ -113,6 +122,8 @@ define double @pow_ab_recip_a_reassoc_use1(double %a, double %b)  {
   ret double %m
 }
 
+; negative test - extra pow uses not allowed
+
 define double @pow_ab_recip_a_reassoc_use2(double %a, double %b)  {
 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_use2(
 ; CHECK-NEXT:    [[P:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
@@ -127,6 +138,8 @@ define double @pow_ab_recip_a_reassoc_use2(double %a, double %b)  {
   ret double %m
 }
 
+; negative test - extra pow uses not allowed
+
 define double @pow_ab_recip_a_reassoc_use3(double %a, double %b)  {
 ; CHECK-LABEL: @pow_ab_recip_a_reassoc_use3(
 ; CHECK-NEXT:    [[R:%.*]] = fdiv double 1.000000e+00, [[A:%.*]]


        


More information about the llvm-commits mailing list