[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