From 072b03c4714ea43af56bbfa6e5a271ef1a1c9e0a Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 13 Jan 2023 15:55:40 -0500 Subject: [PATCH] [InstCombine] fold pow(X,Y) / X -> pow(X, Y-1) This is one of the patterns suggested in issue #34943. --- .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 10 ++++++++++ llvm/test/Transforms/InstCombine/fmul-pow.ll | 21 +++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index d685dd0..460731d 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(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 5984641..63458e1 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 different 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:%.*]] -- 2.7.4