diff options
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 40 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/fp-fold.ll | 43 | 
2 files changed, 51 insertions, 32 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 64b0ee571a2..8b7abdb0395 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -673,6 +673,7 @@ static char isNegatibleForFree(SDValue Op, bool LegalOperations,    // 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()))) @@ -710,7 +711,7 @@ static char isNegatibleForFree(SDValue Op, bool LegalOperations,    case ISD::FSUB:      // We can't turn -(A-B) into B-A when we honor signed zeros.      if (!Options->NoSignedZerosFPMath && -        !Op.getNode()->getFlags().hasNoSignedZeros()) +        !Flags.hasNoSignedZeros())        return 0;      // fold (fneg (fsub A, B)) -> (fsub B, A) @@ -10414,15 +10415,23 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {    if (SDValue NewSel = foldBinOpIntoSelect(N))      return NewSel; -  // 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 A, 0) -> A +  if (N1CFP && N1CFP->isZero()) { +    if (!N1CFP->isNegative() || Options.UnsafeFPMath || +        Flags.hasNoSignedZeros()) { +      return N0; +    } +  } -  // FIXME: Auto-upgrade the target/function-level option. -  if (Options.NoSignedZerosFPMath  || N->getFlags().hasNoSignedZeros()) { -    // (fsub 0, B) -> -B -    if (N0CFP && N0CFP->isZero()) { +  if (N0 == N1) { +    // (fsub x, x) -> 0.0 +    if (Options.UnsafeFPMath || Flags.hasNoNaNs()) +      return DAG.getConstantFP(0.0f, DL, VT); +  } + +  // (fsub 0, B) -> -B +  if (N0CFP && N0CFP->isZero()) { +    if (Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros()) {        if (isNegatibleForFree(N1, LegalOperations, TLI, &Options))          return GetNegatedExpression(N1, DAG, LegalOperations);        if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT)) @@ -10430,16 +10439,13 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {      }    } +  // 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) { -    // (fsub A, 0) -> A -    if (N1CFP && N1CFP->isZero()) -      return N0; - -    // (fsub x, x) -> 0.0 -    if (N0 == N1) -      return DAG.getConstantFP(0.0f, DL, VT); -      // (fsub x, (fadd x, y)) -> (fneg y)      // (fsub x, (fadd y, x)) -> (fneg y)      if (N1.getOpcode() == ISD::FADD) { diff --git a/llvm/test/CodeGen/X86/fp-fold.ll b/llvm/test/CodeGen/X86/fp-fold.ll index 02b5bb999cf..55bb21910af 100644 --- a/llvm/test/CodeGen/X86/fp-fold.ll +++ b/llvm/test/CodeGen/X86/fp-fold.ll @@ -29,6 +29,14 @@ define float @fadd_negzero(float %x) {    ret float %r  } +define float @fadd_negzero_nsz(float %x) { +; ANY-LABEL: fadd_negzero_nsz: +; ANY:       # %bb.0: +; ANY-NEXT:    retq +  %r = fadd nsz float %x, -0.0 +  ret float %r +} +  define float @fadd_zero_nsz(float %x) {  ; ANY-LABEL: fadd_zero_nsz:  ; ANY:       # %bb.0: @@ -37,24 +45,20 @@ define float @fadd_zero_nsz(float %x) {    ret float %r  } -define float @fadd_negzero_nsz(float %x) { -; ANY-LABEL: fadd_negzero_nsz: +define float @fsub_zero(float %x) { +; ANY-LABEL: fsub_zero:  ; ANY:       # %bb.0:  ; ANY-NEXT:    retq -  %r = fadd nsz float %x, -0.0 +  %r = fsub float %x, 0.0    ret float %r  } -define float @fsub_zero(float %x) { -; STRICT-LABEL: fsub_zero: -; STRICT:       # %bb.0: -; STRICT-NEXT:    addss {{.*}}(%rip), %xmm0 -; STRICT-NEXT:    retq -; -; UNSAFE-LABEL: fsub_zero: -; UNSAFE:       # %bb.0: -; UNSAFE-NEXT:    retq -  %r = fsub float %x, 0.0 +define float @fsub_self(float %x) { +; ANY-LABEL: fsub_self: +; ANY:       # %bb.0: +; ANY-NEXT:    xorps %xmm0, %xmm0 +; ANY-NEXT:    retq +  %r = fsub nnan float %x, %x     ret float %r  } @@ -72,14 +76,23 @@ define float @fsub_negzero(float %x) {    ret float %r  } -define float @fsub_zero_nsz(float %x) { -; ANY-LABEL: fsub_zero_nsz: +define float @fsub_zero_nsz_1(float %x) { +; ANY-LABEL: fsub_zero_nsz_1:  ; ANY:       # %bb.0:  ; ANY-NEXT:    retq    %r = fsub nsz float %x, 0.0    ret float %r  } +define float @fsub_zero_nsz_2(float %x) { +; ANY-LABEL: fsub_zero_nsz_2: +; ANY:       # %bb.0: +; ANY-NEXT:    xorps {{.*}}(%rip), %xmm0 +; ANY-NEXT:    retq +  %r = fsub nsz float 0.0, %x +  ret float %r +} +  define float @fsub_negzero_nsz(float %x) {  ; ANY-LABEL: fsub_negzero_nsz:  ; ANY:       # %bb.0:  | 

