Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10935,12 +10935,9 @@ } } - // fold (fsub A, (fneg B)) -> (fadd A, B) - if (isNegatibleForFree(N1, LegalOperations, TLI, &Options)) - return DAG.getNode(ISD::FADD, DL, VT, N0, - GetNegatedExpression(N1, DAG, LegalOperations), Flags); - - if (Options.UnsafeFPMath && N1.getOpcode() == ISD::FADD) { + if ((Options.UnsafeFPMath || + (Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) + && N1.getOpcode() == ISD::FADD) { // X - (X + Y) -> -Y if (N0 == N1->getOperand(0)) return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(1)); @@ -10949,6 +10946,11 @@ return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(0)); } + // fold (fsub A, (fneg B)) -> (fadd A, B) + if (isNegatibleForFree(N1, LegalOperations, TLI, &Options)) + return DAG.getNode(ISD::FADD, DL, VT, N0, + GetNegatedExpression(N1, DAG, LegalOperations), Flags); + // FSUB -> FMA combines: if (SDValue Fused = visitFSUBForFMACombine(N)) { AddToWorklist(Fused.getNode()); Index: test/CodeGen/X86/fp-fold.ll =================================================================== --- test/CodeGen/X86/fp-fold.ll +++ test/CodeGen/X86/fp-fold.ll @@ -89,20 +89,10 @@ } define float @fsub_neg_y(float %x, float %y) { -; STRICT-LABEL: fsub_neg_y: -; STRICT: # %bb.0: -; STRICT-NEXT: mulss {{.*}}(%rip), %xmm0 -; STRICT-NEXT: addss %xmm1, %xmm0 -; STRICT-NEXT: subss %xmm0, %xmm1 -; STRICT-NEXT: movaps %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fsub_neg_y: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: mulss {{.*}}(%rip), %xmm0 -; UNSAFE-NEXT: subss %xmm1, %xmm0 -; UNSAFE-NEXT: addss %xmm1, %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fsub_neg_y: +; ANY: # %bb.0: +; ANY-NEXT: mulss {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq %mul = fmul float %x, 5.0 %add = fadd float %mul, %y %r = fsub nsz reassoc float %y, %add @@ -110,20 +100,10 @@ } define float @fsub_neg_y_commute(float %x, float %y) { -; STRICT-LABEL: fsub_neg_y_commute: -; STRICT: # %bb.0: -; STRICT-NEXT: mulss {{.*}}(%rip), %xmm0 -; STRICT-NEXT: addss %xmm1, %xmm0 -; STRICT-NEXT: subss %xmm0, %xmm1 -; STRICT-NEXT: movaps %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fsub_neg_y_commute: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: mulss {{.*}}(%rip), %xmm0 -; UNSAFE-NEXT: subss %xmm1, %xmm0 -; UNSAFE-NEXT: addss %xmm1, %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fsub_neg_y_commute: +; ANY: # %bb.0: +; ANY-NEXT: mulss {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq %mul = fmul float %x, 5.0 %add = fadd float %y, %mul %r = fsub nsz reassoc float %y, %add @@ -132,17 +112,10 @@ ; Y - (X + Y) --> -X define float @fsub_fadd_common_op_fneg(float %x, float %y) { -; STRICT-LABEL: fsub_fadd_common_op_fneg: -; STRICT: # %bb.0: -; STRICT-NEXT: addss %xmm1, %xmm0 -; STRICT-NEXT: subss %xmm0, %xmm1 -; STRICT-NEXT: movaps %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fsub_fadd_common_op_fneg: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fsub_fadd_common_op_fneg: +; ANY: # %bb.0: +; ANY-NEXT: xorps {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq %a = fadd float %x, %y %r = fsub reassoc nsz float %y, %a ret float %r @@ -151,17 +124,10 @@ ; Y - (X + Y) --> -X define <4 x float> @fsub_fadd_common_op_fneg_vec(<4 x float> %x, <4 x float> %y) { -; STRICT-LABEL: fsub_fadd_common_op_fneg_vec: -; STRICT: # %bb.0: -; STRICT-NEXT: addps %xmm1, %xmm0 -; STRICT-NEXT: subps %xmm0, %xmm1 -; STRICT-NEXT: movaps %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fsub_fadd_common_op_fneg_vec: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fsub_fadd_common_op_fneg_vec: +; ANY: # %bb.0: +; ANY-NEXT: xorps {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq %a = fadd <4 x float> %x, %y %r = fsub nsz reassoc <4 x float> %y, %a ret <4 x float> %r @@ -171,17 +137,10 @@ ; Commute operands of the 'add'. define float @fsub_fadd_common_op_fneg_commute(float %x, float %y) { -; STRICT-LABEL: fsub_fadd_common_op_fneg_commute: -; STRICT: # %bb.0: -; STRICT-NEXT: addss %xmm1, %xmm0 -; STRICT-NEXT: subss %xmm0, %xmm1 -; STRICT-NEXT: movaps %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fsub_fadd_common_op_fneg_commute: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fsub_fadd_common_op_fneg_commute: +; ANY: # %bb.0: +; ANY-NEXT: xorps {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq %a = fadd float %y, %x %r = fsub reassoc nsz float %y, %a ret float %r @@ -190,17 +149,10 @@ ; Y - (Y + X) --> -X define <4 x float> @fsub_fadd_common_op_fneg_commute_vec(<4 x float> %x, <4 x float> %y) { -; STRICT-LABEL: fsub_fadd_common_op_fneg_commute_vec: -; STRICT: # %bb.0: -; STRICT-NEXT: addps %xmm1, %xmm0 -; STRICT-NEXT: subps %xmm0, %xmm1 -; STRICT-NEXT: movaps %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fsub_fadd_common_op_fneg_commute_vec: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: xorps {{.*}}(%rip), %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fsub_fadd_common_op_fneg_commute_vec: +; ANY: # %bb.0: +; ANY-NEXT: xorps {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq %a = fadd <4 x float> %y, %x %r = fsub reassoc nsz <4 x float> %y, %a ret <4 x float> %r