Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -15009,7 +15009,7 @@ // FMA nodes have flags that propagate to the created nodes. SelectionDAG::FlagInserter FlagsInserter(DAG, N); - bool UnsafeFPMath = + bool CanReassociate = Options.UnsafeFPMath || N->getFlags().hasAllowReassociation(); // Constant fold FMA. @@ -15033,7 +15033,7 @@ CostN1 == TargetLowering::NegatibleCost::Cheaper)) return DAG.getNode(ISD::FMA, DL, VT, NegN0, NegN1, N2); - if (UnsafeFPMath) { + if (Options.UnsafeFPMath) { if (N0CFP && N0CFP->isZero()) return N2; if (N1CFP && N1CFP->isZero()) @@ -15050,7 +15050,7 @@ !DAG.isConstantFPBuildVectorOrConstantFP(N1)) return DAG.getNode(ISD::FMA, SDLoc(N), VT, N1, N0, N2); - if (UnsafeFPMath) { + if (CanReassociate) { // (fma x, c1, (fmul x, c2)) -> (fmul x, c1+c2) if (N2.getOpcode() == ISD::FMUL && N0 == N2.getOperand(0) && DAG.isConstantFPBuildVectorOrConstantFP(N1) && @@ -15091,7 +15091,7 @@ } } - if (UnsafeFPMath) { + if (CanReassociate) { // (fma x, c, x) -> (fmul x, (c+1)) if (N1CFP && N0 == N2) { return DAG.getNode( Index: llvm/test/CodeGen/AArch64/neon-fma-FMF.ll =================================================================== --- llvm/test/CodeGen/AArch64/neon-fma-FMF.ll +++ llvm/test/CodeGen/AArch64/neon-fma-FMF.ll @@ -54,3 +54,16 @@ %tmp2 = fsub <2 x float> %C, %tmp1; ret <2 x float> %tmp2 } + +; Regression test: contract FMF allows folding (A * 0 + B) to FMA(A, 0, B), but +; reassoc FMF must not allow further folding to just (B) without additional +; FMFs (ninf, nnan) +define float @fma_zero(float %A, float %B) { +; CHECK-LABEL: fma_zero: +; CHECK: fmadd +; CHECK-NOT: fadd +; CHECK-NOT: fsub + %tmp1 = fmul contract reassoc float %A, 0.0e+0; + %tmp2 = fadd contract reassoc float %B, %tmp1; + ret float %tmp2 +}