diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -13185,11 +13185,11 @@ if (N1CFP && N1CFP->isZero()) return N2; } - // TODO: The FMA node should have flags that propagate to these nodes. + if (N0CFP && N0CFP->isExactlyValue(1.0)) - return DAG.getNode(ISD::FADD, SDLoc(N), VT, N1, N2); + return DAG.getNode(ISD::FADD, SDLoc(N), VT, N1, N2, Flags); if (N1CFP && N1CFP->isExactlyValue(1.0)) - return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0, N2); + return DAG.getNode(ISD::FADD, SDLoc(N), VT, N0, N2, Flags); // Canonicalize (fma c, x, y) -> (fma x, c, y) if (isConstantFPBuildVectorOrConstantFP(N0) && @@ -13218,19 +13218,16 @@ } } - // (fma x, 1, y) -> (fadd x, y) // (fma x, -1, y) -> (fadd (fneg x), y) if (N1CFP) { if (N1CFP->isExactlyValue(1.0)) - // TODO: The FMA node should have flags that propagate to this node. - return DAG.getNode(ISD::FADD, DL, VT, N0, N2); + return DAG.getNode(ISD::FADD, DL, VT, N0, N2, Flags); if (N1CFP->isExactlyValue(-1.0) && (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))) { SDValue RHSNeg = DAG.getNode(ISD::FNEG, DL, VT, N0); AddToWorklist(RHSNeg.getNode()); - // TODO: The FMA node should have flags that propagate to this node. - return DAG.getNode(ISD::FADD, DL, VT, N2, RHSNeg); + return DAG.getNode(ISD::FADD, DL, VT, N2, RHSNeg, Flags); } // fma (fneg x), K, y -> fma x -K, y diff --git a/llvm/test/CodeGen/PowerPC/fma-combine.ll b/llvm/test/CodeGen/PowerPC/fma-combine.ll --- a/llvm/test/CodeGen/PowerPC/fma-combine.ll +++ b/llvm/test/CodeGen/PowerPC/fma-combine.ll @@ -243,17 +243,18 @@ define double @fma_flag_propagation(double %a) { ; CHECK-FAST-LABEL: fma_flag_propagation: ; CHECK-FAST: # %bb.0: # %entry -; CHECK-FAST-NEXT: xssubdp 1, 1, 1 +; CHECK-FAST-NEXT: xxlxor 1, 1, 1 ; CHECK-FAST-NEXT: blr ; ; CHECK-FAST-NOVSX-LABEL: fma_flag_propagation: ; CHECK-FAST-NOVSX: # %bb.0: # %entry -; CHECK-FAST-NOVSX-NEXT: fsub 1, 1, 1 +; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI6_0@toc@ha +; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI6_0@toc@l(3) ; CHECK-FAST-NOVSX-NEXT: blr ; ; CHECK-LABEL: fma_flag_propagation: ; CHECK: # %bb.0: # %entry -; CHECK-NEXT: xssubdp 1, 1, 1 +; CHECK-NEXT: xxlxor 1, 1, 1 ; CHECK-NEXT: blr entry: %0 = fneg double %a @@ -261,4 +262,56 @@ ret double %1 } +define double @neg_fma_flag_propagation(double %a) { +; CHECK-FAST-LABEL: neg_fma_flag_propagation: +; CHECK-FAST: # %bb.0: # %entry +; CHECK-FAST-NEXT: xxlxor 1, 1, 1 +; CHECK-FAST-NEXT: blr +; +; CHECK-FAST-NOVSX-LABEL: neg_fma_flag_propagation: +; CHECK-FAST-NOVSX: # %bb.0: # %entry +; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI7_0@toc@ha +; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI7_0@toc@l(3) +; CHECK-FAST-NOVSX-NEXT: blr +; +; CHECK-LABEL: neg_fma_flag_propagation: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: xxlxor 1, 1, 1 +; CHECK-NEXT: blr +entry: + %0 = call reassoc nnan double @llvm.fma.f64(double %a, double -1.0, double %a) + ret double %0 +} + +define <2 x double> @vec_neg_fma_flag_propagation(<2 x double> %a) { +; CHECK-FAST-LABEL: vec_neg_fma_flag_propagation: +; CHECK-FAST: # %bb.0: # %entry +; CHECK-FAST-NEXT: addis 3, 2, .LCPI8_0@toc@ha +; CHECK-FAST-NEXT: addi 3, 3, .LCPI8_0@toc@l +; CHECK-FAST-NEXT: lxvd2x 0, 0, 3 +; CHECK-FAST-NEXT: xxswapd 0, 0 +; CHECK-FAST-NEXT: xvmaddadp 34, 34, 0 +; CHECK-FAST-NEXT: blr +; +; CHECK-FAST-NOVSX-LABEL: vec_neg_fma_flag_propagation: +; CHECK-FAST-NOVSX: # %bb.0: # %entry +; CHECK-FAST-NOVSX-NEXT: addis 3, 2, .LCPI8_0@toc@ha +; CHECK-FAST-NOVSX-NEXT: lfs 1, .LCPI8_0@toc@l(3) +; CHECK-FAST-NOVSX-NEXT: fmr 2, 1 +; CHECK-FAST-NOVSX-NEXT: blr +; +; CHECK-LABEL: vec_neg_fma_flag_propagation: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: addis 3, 2, .LCPI8_0@toc@ha +; CHECK-NEXT: addi 3, 3, .LCPI8_0@toc@l +; CHECK-NEXT: lxvd2x 0, 0, 3 +; CHECK-NEXT: xxswapd 0, 0 +; CHECK-NEXT: xvmaddadp 34, 34, 0 +; CHECK-NEXT: blr +entry: + %0 = call reassoc nnan <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> , <2 x double> %a) + ret <2 x double> %0 +} + declare double @llvm.fma.f64(double, double, double) nounwind readnone +declare <2 x double> @llvm.fma.v2f64(<2 x double>, <2 x double>, <2 x double>) nounwind readnone