Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10943,13 +10943,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 'unsafe math' is enabled, fold lots of things. - if (Options.UnsafeFPMath) { + if (Options.UnsafeFPMath || + (Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) { // (fsub x, (fadd x, y)) -> (fneg y) // (fsub x, (fadd y, x)) -> (fneg y) if (N1.getOpcode() == ISD::FADD) { @@ -10964,6 +10960,11 @@ } } + // 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 @@ -88,6 +88,17 @@ ret float %r } +define float @fsub_neg_y(float %x, float %y) { +; ANY-LABEL: fsub_neg_y: +; ANY: # %bb.0: +; ANY-NEXT: mulss {{.*}}(%rip), %xmm0 +; ANY-NEXT: retq + %mul = fmul float %x, 5.000000e+00 + %add = fadd float %mul, 1.0 + %r = fsub nsz reassoc float 1.0, %add + ret float %r +} + define float @fsub_negzero(float %x) { ; STRICT-LABEL: fsub_negzero: ; STRICT: # %bb.0: @@ -153,3 +164,5 @@ %r = fmul reassoc float %mul, 4.0 ret float %r } + +declare float @llvm.fabs.f32(float) #1 Index: test/Transforms/InstCombine/fsub.ll =================================================================== --- test/Transforms/InstCombine/fsub.ll +++ test/Transforms/InstCombine/fsub.ll @@ -60,6 +60,19 @@ ret float %t2 } +; With nsz and reassoc: Y - (X + Y) --> -X +define float @sub_add_neg_x(float %x, float %y) { +; CHECK-LABEL: @sub_add_neg_x( +; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X:%.*]], 5.000000e+00 +; CHECK-NEXT: [[T2:%.*]] = fsub reassoc nsz float -0.000000e+00, [[TMP1]] +; CHECK-NEXT: ret float [[T2]] +; + %mul = fmul float %x, 5.000000e+00 + %add = fadd float %mul, 1.0 + %r = fsub nsz reassoc float 1.0, %add + ret float %r +} + ; Same as above: if 'Z' is not -0.0, swap fsub operands and convert to fadd. define float @sub_sub_known_not_negzero(float %x, float %y) {