[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
Mon May 24 05:12:06 PDT 2021
vdsered updated this revision to Diff 347353.
vdsered added a comment.
Replaced std::any_of with llvm::any_of and used I->operands() instead of making range directly via begin/end
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D102698/new/
https://reviews.llvm.org/D102698
Files:
llvm/include/llvm/Transforms/Utils/Local.h
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
llvm/lib/Transforms/Utils/Local.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,6 +34,17 @@
ret double %mul
}
+define double @exp2_a_multiple_uses_in_one_user(double %a) {
+; CHECK-LABEL: @exp2_a_multiple_uses_in_one_user(
+; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[A]]
+; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @llvm.exp2.f64(double [[TMP1]])
+; CHECK-NEXT: ret double [[TMP2]]
+;
+ %tmp = call double @llvm.exp2.f64(double %a)
+ %mul = fmul reassoc double %tmp, %tmp
+ ret double %mul
+}
+
; exp2(a) * exp2(b) reassoc, both with multiple uses
define double @exp2_a_exp2_b_multiple_uses_both(double %a, double %b) {
; CHECK-LABEL: @exp2_a_exp2_b_multiple_uses_both(
Index: llvm/test/Transforms/InstCombine/fmul-exp.ll
===================================================================
--- llvm/test/Transforms/InstCombine/fmul-exp.ll
+++ llvm/test/Transforms/InstCombine/fmul-exp.ll
@@ -65,6 +65,17 @@
ret double %mul
}
+define double @exp_a(double %a) {
+; CHECK-LABEL: @exp_a(
+; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[A]]
+; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @llvm.exp.f64(double [[TMP1]])
+; CHECK-NEXT: ret double [[TMP2]]
+;
+ %tmp = call double @llvm.exp.f64(double %a)
+ %mul = fmul reassoc double %tmp, %tmp
+ ret double %mul
+}
+
; exp(a) * exp(b) * exp(c) * exp(d) => exp(a+b+c+d) with reassoc
define double @exp_a_exp_b_exp_c_exp_d_fast(double %a, double %b, double %c, double %d) {
; CHECK-LABEL: @exp_a_exp_b_exp_c_exp_d_fast(
Index: llvm/lib/Transforms/Utils/Local.cpp
===================================================================
--- llvm/lib/Transforms/Utils/Local.cpp
+++ llvm/lib/Transforms/Utils/Local.cpp
@@ -3302,6 +3302,14 @@
}
}
+bool llvm::isOnlyUserOfAnyOperand(Instruction *I) {
+ assert(I->getNumOperands() && "Must have at least one operand");
+ auto *FirstOp = I->getOperand(0);
+ auto NumOps = I->getNumOperands();
+ return llvm::any_of(I->operands(), [](Value *V) { return V->hasOneUse(); }) ||
+ (FirstOp->hasNUses(NumOps) && llvm::is_splat(I->operands()));
+}
+
Value *llvm::invertCondition(Value *Condition) {
// First: Check if it's a constant
if (Constant *C = dyn_cast<Constant>(Condition))
Index: llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -559,7 +559,7 @@
// 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())) {
+ isOnlyUserOfAnyOperand(&I)) {
Value *XY = Builder.CreateFAddFMF(X, Y, &I);
Value *Exp = Builder.CreateUnaryIntrinsic(Intrinsic::exp, XY, &I);
return replaceInstUsesWith(I, Exp);
@@ -569,7 +569,7 @@
// 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())) {
+ isOnlyUserOfAnyOperand(&I)) {
Value *XY = Builder.CreateFAddFMF(X, Y, &I);
Value *Exp2 = Builder.CreateUnaryIntrinsic(Intrinsic::exp2, XY, &I);
return replaceInstUsesWith(I, Exp2);
Index: llvm/include/llvm/Transforms/Utils/Local.h
===================================================================
--- llvm/include/llvm/Transforms/Utils/Local.h
+++ llvm/include/llvm/Transforms/Utils/Local.h
@@ -465,6 +465,10 @@
/// value?
bool canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx);
+/// It checks if this instruction is the only user of at least one of
+/// its operands.
+bool isOnlyUserOfAnyOperand(Instruction *I);
+
//===----------------------------------------------------------------------===//
// Value helper functions
//
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D102698.347353.patch
Type: text/x-patch
Size: 4188 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210524/050ddfc9/attachment-0001.bin>
More information about the llvm-commits
mailing list