Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -673,6 +673,7 @@ // Don't allow anything with multiple uses unless we know it is free. EVT VT = Op.getValueType(); + const SDNodeFlags Flags = Op->getFlags(); if (!Op.hasOneUse()) if (!(Op.getOpcode() == ISD::FP_EXTEND && TLI.isFPExtFree(VT, Op.getOperand(0).getValueType()))) @@ -717,6 +718,16 @@ return 1; case ISD::FMUL: + if (Options->HonorSignDependentRoundingFPMathOption && + !Options->UnsafeFPMath && !Flags.hasNoSignedZeros()) 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)) + return V; + + return isNegatibleForFree(Op.getOperand(1), LegalOperations, TLI, Options, + Depth + 1); case ISD::FDIV: if (Options->HonorSignDependentRoundingFPMath()) return 0; @@ -10473,11 +10484,14 @@ if (SDValue NewSel = foldBinOpIntoSelect(N)) return NewSel; - if (Options.UnsafeFPMath) { + if (Options.UnsafeFPMath || + (Flags.hasNoNaNs() && Flags.hasNoSignedZeros())) { // fold (fmul A, 0) -> 0 if (N1CFP && N1CFP->isZero()) return N1; + } + if (Options.UnsafeFPMath || Flags.hasAllowReassociation()) { // fold (fmul (fmul x, c1), c2) -> (fmul x, (fmul c1, c2)) if (N0.getOpcode() == ISD::FMUL) { // Fold scalars or any vector constants (not just splats). Index: test/CodeGen/X86/fp-fold.ll =================================================================== --- test/CodeGen/X86/fp-fold.ll +++ test/CodeGen/X86/fp-fold.ll @@ -90,16 +90,10 @@ ; TODO: handle x*0 for fast flags the same as unsafe define float @fmul_zero(float %x) { -; STRICT-LABEL: fmul_zero: -; STRICT: # %bb.0: -; STRICT-NEXT: xorps %xmm1, %xmm1 -; STRICT-NEXT: mulss %xmm1, %xmm0 -; STRICT-NEXT: retq -; -; UNSAFE-LABEL: fmul_zero: -; UNSAFE: # %bb.0: -; UNSAFE-NEXT: xorps %xmm0, %xmm0 -; UNSAFE-NEXT: retq +; ANY-LABEL: fmul_zero: +; ANY: # %bb.0: +; ANY-NEXT: xorps %xmm0, %xmm0 +; ANY-NEXT: retq %r = fmul nnan nsz float %x, 0.0 ret float %r }