Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -704,8 +704,8 @@ TLI.isFPImmLegal(neg(cast(Op)->getValueAPF()), VT); } case ISD::FADD: - // FIXME: determine better conditions for this xform. - if (!Options->UnsafeFPMath) return 0; + if (!Options->UnsafeFPMath && !Flags.hasNoSignedZeros()) + return 0; // After operation legalization, it might not be legal to create new FSUBs. if (LegalOperations && !TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) @@ -729,8 +729,6 @@ case ISD::FMUL: case ISD::FDIV: - if (Options->HonorSignDependentRoundingFPMath()) return 0; - // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y)) if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI, Options, Depth + 1)) @@ -766,8 +764,7 @@ return DAG.getConstantFP(V, SDLoc(Op), Op.getValueType()); } case ISD::FADD: - // FIXME: determine better conditions for this xform. - assert(Options.UnsafeFPMath); + assert(Options.UnsafeFPMath || Flags.hasNoSignedZeros()); // fold (fneg (fadd A, B)) -> (fsub (fneg A), B) if (isNegatibleForFree(Op.getOperand(0), LegalOperations, @@ -793,8 +790,6 @@ case ISD::FMUL: case ISD::FDIV: - assert(!Options.HonorSignDependentRoundingFPMath()); - // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) if (isNegatibleForFree(Op.getOperand(0), LegalOperations, DAG.getTargetLoweringInfo(), &Options, Depth+1)) Index: test/CodeGen/ARM/fnmul.ll =================================================================== --- test/CodeGen/ARM/fnmul.ll +++ test/CodeGen/ARM/fnmul.ll @@ -1,17 +1,15 @@ -; RUN: llc -mtriple=arm-eabi -mattr=+v6,+vfp2 %s -o - | FileCheck %s - -; RUN: llc -mtriple=arm-eabi -mattr=+v6,+vfp2 -enable-sign-dependent-rounding-fp-math %s -o - \ -; RUN: | FileCheck %s -check-prefix CHECK-ROUNDING - +; RUN: llc -mtriple=arm-eabi -mattr=+v6,+vfp2 %s -o - | FileCheck %s -check-prefix STRICT +; RUN: llc -mtriple=arm-eabi -mattr=+v6,+vfp2 -enable-unsafe-fp-math %s -o - | FileCheck %s -check-prefix UNSAFE define double @t1(double %a, double %b) { +; STRICT: vnmul.f64 +; +; UNSAFE: vnmul.f64 entry: %tmp2 = fsub double -0.000000e+00, %a ; [#uses=1] %tmp4 = fmul double %tmp2, %b ; [#uses=1] ret double %tmp4 } -; CHECK: vnmul.f64 -; CHECK-ROUNDING: vmul.f64 Index: test/CodeGen/X86/fp-fold.ll =================================================================== --- test/CodeGen/X86/fp-fold.ll +++ test/CodeGen/X86/fp-fold.ll @@ -62,6 +62,17 @@ ret float %r } +define float @fsub_neg_x_y(float %x, float %y) { +; ANY-LABEL: fsub_neg_x_y: +; ANY: # %bb.0: +; ANY-NEXT: subss %xmm0, %xmm1 +; ANY-NEXT: movaps %xmm1, %xmm0 +; ANY-NEXT: retq + %neg = fsub nsz float 0.0, %x + %r = fadd nsz float %neg, %y + ret float %r +} + define float @fsub_negzero(float %x) { ; STRICT-LABEL: fsub_negzero: ; STRICT: # %bb.0: