Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -16959,17 +16959,42 @@ if (ConstantFPSDNode *CFP = dyn_cast(N1)) { // Allow either -0.0 or 0.0 if (CFP->isZero()) { - // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs - if ((CC == ISD::SETGE || CC == ISD::SETGT) && - N0 == N2 && N3.getOpcode() == ISD::FNEG && - N2 == N3.getOperand(0)) - return DAG.getNode(ISD::FABS, DL, VT, N0); - - // select (setl[te] X, +/-0.0), fneg(X), X -> fabs - if ((CC == ISD::SETLT || CC == ISD::SETLE) && - N0 == N3 && N2.getOpcode() == ISD::FNEG && - N2.getOperand(0) == N3) - return DAG.getNode(ISD::FABS, DL, VT, N3); + // These patterns should produce -0.0 on one of the zero inputs. Check + // for nsz before folding. + if (N0.getNode()->getFlags().hasNoSignedZeros()) { + // select (setg[te] X, +/-0.0), X, fneg(X) -> fabs + if ((CC == ISD::SETGE || CC == ISD::SETGT) && N0 == N2 && + N3.getOpcode() == ISD::FNEG && N2 == N3.getOperand(0)) + return DAG.getNode(ISD::FABS, DL, VT, N0); + + // select (setl[te] X, +/-0.0), fneg(X), X -> fabs + if ((CC == ISD::SETLT || CC == ISD::SETLE) && N0 == N3 && + N2.getOpcode() == ISD::FNEG && N2.getOperand(0) == N3) + return DAG.getNode(ISD::FABS, DL, VT, N3); + } + + // These patterns are sign-of-zero compliant, but the zero values must be + // routed to the (0.0 - X) option, so only 2 out of 4 conditions are + // supported. + // select (setgt X, +/-0.0), X, (fsub 0.0, X) -> fabs + if (CC == ISD::SETGT && N0 == N2 && N3.getOpcode() == ISD::FSUB && + N0 == N3.getOperand(1)) { + if (ConstantFPSDNode *CZ = + dyn_cast(N3.getOperand(0))) { + if (CZ->isZero() && !CZ->isNegative()) + return DAG.getNode(ISD::FABS, DL, VT, N0); + } + } + + // select (setle X, +/-0.0), (fsub 0.0, X), X -> fabs + if (CC == ISD::SETLE && N0 == N3 && N2.getOpcode() == ISD::FSUB && + N0 == N2.getOperand(1)) { + if (ConstantFPSDNode *CZ = + dyn_cast(N2.getOperand(0))) { + if (CZ->isZero() && !CZ->isNegative()) + return DAG.getNode(ISD::FABS, DL, VT, N3); + } + } } } Index: test/CodeGen/X86/fabs.ll =================================================================== --- test/CodeGen/X86/fabs.ll +++ test/CodeGen/X86/fabs.ll @@ -32,11 +32,8 @@ } ; fabs is not used here. ; CHECK-NOT: fabs -; NOOPT-NOT: fabs - -; UNSAFE: {{^[ \t]+fabs$}} - ; UNSAFE-NOT: fabs +; NOOPT-NOT: fabs ; CHECK-LABEL: test3: ; UNSAFE-LABEL: test3: @@ -52,3 +49,20 @@ ; CHECK-NOT: fabs ; UNSAFE-NOT: fabs ; NOOPT-NOT: fabs + +; CHECK-LABEL: test4: +; UNSAFE-LABEL: test4: +; NOOPT-LABEL: test4: +define double @test4(double %X) { + %Y = fcmp ogt double %X, zeroinitializer + %Z = fsub double zeroinitializer, %X + %Q = select i1 %Y, double %X, double %Z + ret double %Q +} +; fabs is not used here. +; CHECK-NOT: fabs +; NOOPT-NOT: fabs + +; UNSAFE: {{^[ \t]+fabs$}} + +; UNSAFE-NOT: fabs