[PATCH] D102574: [InstCombine] Missed optimization for pow(x, y) * pow(x, z) with fast-math

Daniil Seredkin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun May 16 04:36:52 PDT 2021


vdsered updated this revision to Diff 345698.
vdsered added a comment.

Calling CreateBinaryIntrinsic instead of CreateIntrinsic for better readability


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102574/new/

https://reviews.llvm.org/D102574

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


Index: llvm/test/Transforms/InstCombine/fmul-pow.ll
===================================================================
--- llvm/test/Transforms/InstCombine/fmul-pow.ll
+++ llvm/test/Transforms/InstCombine/fmul-pow.ll
@@ -78,13 +78,23 @@
 
 define double @pow_ab_x_pow_ac_reassoc(double %a, double %b, double %c) {
 ; CHECK-LABEL: @pow_ab_x_pow_ac_reassoc(
-; CHECK-NEXT:    [[TMP1:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[B:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A]], double [[C:%.*]])
-; CHECK-NEXT:    [[MUL:%.*]] = fmul reassoc double [[TMP2]], [[TMP1]]
-; CHECK-NEXT:    ret double [[MUL]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[C:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
 ;
   %1 = call double @llvm.pow.f64(double %a, double %b)
   %2 = call double @llvm.pow.f64(double %a, double %c)
   %mul = fmul reassoc double %2, %1
   ret double %mul
 }
+
+define double @pow_ab_reassoc(double %a, double %b) {
+; CHECK-LABEL: @pow_ab_reassoc(
+; CHECK-NEXT:    [[TMP1:%.*]] = fadd double [[B:%.*]], [[B]]
+; CHECK-NEXT:    [[TMP2:%.*]] = call double @llvm.pow.f64(double [[A:%.*]], double [[TMP1]])
+; CHECK-NEXT:    ret double [[TMP2]]
+;
+  %1 = call double @llvm.pow.f64(double %a, double %b)
+  %mul = fmul reassoc double %1, %1
+  ret double %mul
+}
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -462,6 +462,27 @@
     return replaceInstUsesWith(I, V);
 
   if (I.hasAllowReassoc()) {
+    // pow(x, y) * pow(x, z) -> pow(x, y + z)
+    // If operands of fmul are equal and they have exactly two uses, then
+    // they have one user. It is useful for a case like the one below
+    //
+    // %2 = pow %0, %1
+    // %3 = fmul %2, %2
+    // -->
+    // %2 = fadd %1, %1
+    // %3 = pow %0, %2
+    if (Op0->hasOneUse() || Op1->hasOneUse() ||
+        (Op1 == Op0 && Op1->hasNUses(2))) {
+      Value *X, *Y, *Z;
+      if (match(Op0, m_Intrinsic<Intrinsic::pow>(m_Value(X), m_Value(Y))))
+        if (match(Op1,
+                  m_Intrinsic<Intrinsic::pow>(m_Specific(X), m_Value(Z)))) {
+          auto *Expo = Builder.CreateFAdd(Y, Z);
+          auto *NewPow = Builder.CreateBinaryIntrinsic(Intrinsic::pow, X, Expo);
+          return replaceInstUsesWith(I, NewPow);
+        }
+    }
+
     // Reassociate constant RHS with another constant to form constant
     // expression.
     if (match(Op1, m_Constant(C)) && C->isFiniteNonZeroFP()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D102574.345698.patch
Type: text/x-patch
Size: 2737 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210516/dfa5e557/attachment.bin>


More information about the llvm-commits mailing list