[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 04:00:51 PDT 2021
vdsered updated this revision to Diff 348217.
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.348217.patch
Type: text/x-patch
Size: 3890 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210527/15227aa0/attachment.bin>
More information about the llvm-commits
mailing list