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()); } 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(this)->setHasNoUnsignedWrap(b); } 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(m_Value(X))) && match(Op1, m_Intrinsic(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(m_Value(X))) && match(Op1, m_Intrinsic(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/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/test/Transforms/InstCombine/fmul-exp2.ll =================================================================== --- llvm/test/Transforms/InstCombine/fmul-exp2.ll +++ llvm/test/Transforms/InstCombine/fmul-exp2.ll @@ -38,9 +38,9 @@ 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 @@ -68,9 +68,9 @@ ; exp2(a) * exp2(b) => exp2(a+b) with reassoc define double @exp2_a_exp2_b_reassoc(double %a, double %b) { ; CHECK-LABEL: @exp2_a_exp2_b_reassoc( -; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc double [[A:%.*]], [[B:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = call reassoc double @llvm.exp2.f64(double [[TMP1]]) -; CHECK-NEXT: ret double [[TMP2]] +; CHECK-NEXT: [[T:%.*]] = fadd reassoc double [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[E:%.*]] = call reassoc double @llvm.exp2.f64(double [[T]]) +; CHECK-NEXT: ret double [[E]] ; %t = call double @llvm.exp2.f64(double %a) %t1 = call double @llvm.exp2.f64(double %b)