[PATCH] D102698: [InstCombine] Relaxed constraints of uses for exp(X) * exp(Y) -> exp(X + Y) and exp2(X) * exp2(Y) -> exp2(X + Y)

Daniil Seredkin via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu May 27 20:11:13 PDT 2021


vdsered updated this revision to Diff 348437.

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

https://reviews.llvm.org/D102698

Files:
  llvm/include/llvm/IR/Instruction.h
  llvm/lib/IR/Instruction.cpp
  llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
  llvm/test/Transforms/InstCombine/fmul-exp.ll
  llvm/test/Transforms/InstCombine/fmul-exp2.ll


Index: llvm/test/Transforms/InstCombine/fmul-exp2.ll
===================================================================
--- llvm/test/Transforms/InstCombine/fmul-exp2.ll
+++ llvm/test/Transforms/InstCombine/fmul-exp2.ll
@@ -34,13 +34,11 @@
   ret double %mul
 }
 
-; TODO: Multiple uses, but only 1 user.
-
 define double @exp2_a_a(double %a) {
 ; CHECK-LABEL: @exp2_a_a(
-; CHECK-NEXT:    [[T:%.*]] = call double @llvm.exp2.f64(double [[A:%.*]])
-; CHECK-NEXT:    [[M:%.*]] = fmul reassoc double [[T]], [[T]]
-; CHECK-NEXT:    ret double [[M]]
+; CHECK-NEXT:    [[T:%.*]] = fadd reassoc double [[A:%.*]], [[A]]
+; CHECK-NEXT:    [[E:%.*]] = call reassoc double @llvm.exp2.f64(double [[T]])
+; CHECK-NEXT:    ret double [[E]]
 ;
   %t = call double @llvm.exp2.f64(double %a)
   %m = fmul reassoc double %t, %t
Index: llvm/test/Transforms/InstCombine/fmul-exp.ll
===================================================================
--- llvm/test/Transforms/InstCombine/fmul-exp.ll
+++ llvm/test/Transforms/InstCombine/fmul-exp.ll
@@ -65,13 +65,11 @@
   ret double %mul
 }
 
-; TODO: Multiple uses, but only 1 user.
-
 define double @exp_a_a(double %a) {
 ; CHECK-LABEL: @exp_a_a(
-; CHECK-NEXT:    [[T:%.*]] = call double @llvm.exp.f64(double [[A:%.*]])
-; CHECK-NEXT:    [[M:%.*]] = fmul reassoc double [[T]], [[T]]
-; CHECK-NEXT:    ret double [[M]]
+; CHECK-NEXT:    [[T:%.*]] = fadd reassoc double [[A:%.*]], [[A]]
+; CHECK-NEXT:    [[E:%.*]] = call reassoc double @llvm.exp.f64(double [[T]])
+; CHECK-NEXT:    ret double [[E]]
 ;
   %t = call double @llvm.exp.f64(double %a)
   %m = fmul reassoc double %t, %t
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -556,20 +556,18 @@
     }
 
     // exp(X) * exp(Y) -> exp(X + Y)
-    // Match as long as at least one of exp has only one use.
     if (match(Op0, m_Intrinsic<Intrinsic::exp>(m_Value(X))) &&
         match(Op1, m_Intrinsic<Intrinsic::exp>(m_Value(Y))) &&
-        (Op0->hasOneUse() || Op1->hasOneUse())) {
+        I.isOnlyUserOfAnyOperand()) {
       Value *XY = Builder.CreateFAddFMF(X, Y, &I);
       Value *Exp = Builder.CreateUnaryIntrinsic(Intrinsic::exp, XY, &I);
       return replaceInstUsesWith(I, Exp);
     }
 
     // exp2(X) * exp2(Y) -> exp2(X + Y)
-    // Match as long as at least one of exp2 has only one use.
     if (match(Op0, m_Intrinsic<Intrinsic::exp2>(m_Value(X))) &&
         match(Op1, m_Intrinsic<Intrinsic::exp2>(m_Value(Y))) &&
-        (Op0->hasOneUse() || Op1->hasOneUse())) {
+        I.isOnlyUserOfAnyOperand()) {
       Value *XY = Builder.CreateFAddFMF(X, Y, &I);
       Value *Exp2 = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, XY, &I);
       return replaceInstUsesWith(I, Exp2);
Index: llvm/lib/IR/Instruction.cpp
===================================================================
--- llvm/lib/IR/Instruction.cpp
+++ llvm/lib/IR/Instruction.cpp
@@ -117,6 +117,10 @@
   return Order < Other->Order;
 }
 
+bool Instruction::isOnlyUserOfAnyOperand() {
+  return any_of(operands(), [](Value *V) { return V->hasOneUser(); });
+}
+
 void Instruction::setHasNoUnsignedWrap(bool b) {
   cast<OverflowingBinaryOperator>(this)->setHasNoUnsignedWrap(b);
 }
Index: llvm/include/llvm/IR/Instruction.h
===================================================================
--- llvm/include/llvm/IR/Instruction.h
+++ llvm/include/llvm/IR/Instruction.h
@@ -170,6 +170,11 @@
   bool isExceptionalTerminator() const {
     return isExceptionalTerminator(getOpcode());
   }
+
+  /// It checks if this instruction is the only user of at least one of
+  /// its operands.
+  bool isOnlyUserOfAnyOperand();
+
   bool isIndirectTerminator() const {
     return isIndirectTerminator(getOpcode());
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D102698.348437.patch
Type: text/x-patch
Size: 3890 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210528/56467123/attachment.bin>


More information about the llvm-commits mailing list