diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2240,6 +2240,22 @@ if (Instruction *I = canonicalizeConstantArg0ToArg1(CI)) return I; + // Try to simplify the underlying FMul. + if (Value *V = SimplifyFMulInst(II->getArgOperand(0), II->getArgOperand(1), + II->getFastMathFlags(), + SQ.getWithInstruction(II))) { + Value *RHS, *LHS; + if (match(V, m_FMul(m_Value(LHS), m_Value(RHS)))) { + II->setArgOperand(0, LHS); + II->setArgOperand(1, LHS); + return II; + } + + auto *FAdd = BinaryOperator::CreateFAdd(V, II->getArgOperand(2)); + FAdd->copyFastMathFlags(II); + return FAdd; + } + // fma fneg(x), fneg(y), z -> fma x, y, z Value *Src0 = II->getArgOperand(0); Value *Src1 = II->getArgOperand(1); @@ -2258,15 +2274,9 @@ return II; } - // fma x, 1, z -> fadd x, z - if (match(Src1, m_FPOne())) { - auto *FAdd = BinaryOperator::CreateFAdd(Src0, II->getArgOperand(2)); - FAdd->copyFastMathFlags(II); - return FAdd; - } - break; } + case Intrinsic::fabs: { Value *Cond; Constant *LHS, *RHS; diff --git a/llvm/test/Transforms/InstCombine/fma.ll b/llvm/test/Transforms/InstCombine/fma.ll --- a/llvm/test/Transforms/InstCombine/fma.ll +++ b/llvm/test/Transforms/InstCombine/fma.ll @@ -182,7 +182,7 @@ define float @fmuladd_fneg_x_fneg_y_fast(float %x, float %y, float %z) { ; CHECK-LABEL: @fmuladd_fneg_x_fneg_y_fast( -; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[FMULADD:%.*]] = fadd fast float [[TMP1]], [[Z:%.*]] ; CHECK-NEXT: ret float [[FMULADD]] ; @@ -194,7 +194,7 @@ define float @fmuladd_unary_fneg_x_unary_fneg_y_fast(float %x, float %y, float %z) { ; CHECK-LABEL: @fmuladd_unary_fneg_x_unary_fneg_y_fast( -; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[FMULADD:%.*]] = fadd fast float [[TMP1]], [[Z:%.*]] ; CHECK-NEXT: ret float [[FMULADD]] ; @@ -369,5 +369,72 @@ ret float %fmuladd } +define <2 x double> @fmuladd_a_0_b(<2 x double> %a, <2 x double> %b) { +; CHECK-LABEL: @fmuladd_a_0_b( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x double> [[B:%.*]] +; +entry: + %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b) + ret <2 x double> %res +} + +define <2 x double> @fmuladd_0_a_b(<2 x double> %a, <2 x double> %b) { +; CHECK-LABEL: @fmuladd_0_a_b( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x double> [[B:%.*]] +; +entry: + %res = call nnan nsz <2 x double> @llvm.fmuladd.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b) + ret <2 x double> %res +} + +define <2 x double> @fmuladd_a_0_b_missing_flags(<2 x double> %a, <2 x double> %b) { +; CHECK-LABEL: @fmuladd_a_0_b_missing_flags( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RES:%.*]] = call nnan <2 x double> @llvm.fmuladd.v2f64(<2 x double> [[A:%.*]], <2 x double> zeroinitializer, <2 x double> [[B:%.*]]) +; CHECK-NEXT: ret <2 x double> [[RES]] +; +entry: + %res = call nnan <2 x double> @llvm.fmuladd.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b) + ret <2 x double> %res +} + +declare <2 x double> @llvm.fmuladd.v2f64(<2 x double>, <2 x double>, <2 x double>) + +define <2 x double> @fma_a_0_b(<2 x double> %a, <2 x double> %b) { +; CHECK-LABEL: @fma_a_0_b( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x double> [[B:%.*]] +; +entry: + %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> zeroinitializer, <2 x double> %b) + ret <2 x double> %res +} + +define <2 x double> @fma_0_a_b(<2 x double> %a, <2 x double> %b) { +; CHECK-LABEL: @fma_0_a_b( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret <2 x double> [[B:%.*]] +; +entry: + %res = call nnan nsz <2 x double> @llvm.fma.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b) + ret <2 x double> %res +} + +define <2 x double> @fma_0_a_b_missing_flags(<2 x double> %a, <2 x double> %b) { +; CHECK-LABEL: @fma_0_a_b_missing_flags( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[RES:%.*]] = call nsz <2 x double> @llvm.fma.v2f64(<2 x double> [[A:%.*]], <2 x double> zeroinitializer, <2 x double> [[B:%.*]]) +; CHECK-NEXT: ret <2 x double> [[RES]] +; +entry: + %res = call nsz <2 x double> @llvm.fma.v2f64(<2 x double> zeroinitializer, <2 x double> %a, <2 x double> %b) + ret <2 x double> %res +} + +declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) + + attributes #0 = { nounwind } attributes #1 = { nounwind readnone }