diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 53 | 
1 files changed, 52 insertions, 1 deletions
| diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 081544818f6..ec47f2ba2c4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -876,6 +876,27 @@ static char isNegatibleForFree(SDValue Op, bool LegalOperations,      return isNegatibleForFree(Op.getOperand(1), LegalOperations, TLI, Options,                                ForCodeSize, Depth + 1); +  case ISD::FMA: +  case ISD::FMAD: { +    if (!Options->NoSignedZerosFPMath && !Flags.hasNoSignedZeros()) +      return 0; + +    // fold (fneg (fma X, Y, Z)) -> (fma (fneg X), Y, (fneg Z)) +    // fold (fneg (fma X, Y, Z)) -> (fma X, (fneg Y), (fneg Z)) +    char V2 = isNegatibleForFree(Op.getOperand(2), LegalOperations, TLI, +                                 Options, ForCodeSize, Depth + 1); +    if (!V2) +      return 0; + +    // One of Op0/Op1 must be cheaply negatible, then select the cheapest. +    char V0 = isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI, +                                 Options, ForCodeSize, Depth + 1); +    char V1 = isNegatibleForFree(Op.getOperand(1), LegalOperations, TLI, +                                 Options, ForCodeSize, Depth + 1); +    char V01 = std::max(V0, V1); +    return V01 ? std::max(V01, V2) : 0; +  } +    case ISD::FP_EXTEND:    case ISD::FP_ROUND:    case ISD::FSIN: @@ -917,7 +938,8 @@ static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG,      return DAG.getBuildVector(Op.getValueType(), SDLoc(Op), Ops);    }    case ISD::FADD: -    assert(Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros()); +    assert((Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros()) && +           "Expected NSZ fp-flag");      // fold (fneg (fadd A, B)) -> (fsub (fneg A), B)      if (isNegatibleForFree(Op.getOperand(0), LegalOperations, @@ -964,6 +986,35 @@ static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG,                                              LegalOperations, ForCodeSize,                                              Depth + 1), Flags); +  case ISD::FMA: +  case ISD::FMAD: { +    assert((Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros()) && +           "Expected NSZ fp-flag"); + +    SDValue Neg2 = GetNegatedExpression(Op.getOperand(2), DAG, LegalOperations, +                                        ForCodeSize, Depth + 1); + +    char V0 = isNegatibleForFree(Op.getOperand(0), LegalOperations, +                                 DAG.getTargetLoweringInfo(), &Options, +                                 ForCodeSize, Depth + 1); +    char V1 = isNegatibleForFree(Op.getOperand(1), LegalOperations, +                                 DAG.getTargetLoweringInfo(), &Options, +                                 ForCodeSize, Depth + 1); +    if (V0 >= V1) { +      // fold (fneg (fma X, Y, Z)) -> (fma (fneg X), Y, (fneg Z)) +      SDValue Neg0 = GetNegatedExpression( +          Op.getOperand(0), DAG, LegalOperations, ForCodeSize, Depth + 1); +      return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), Neg0, +                         Op.getOperand(1), Neg2, Flags); +    } + +    // fold (fneg (fma X, Y, Z)) -> (fma X, (fneg Y), (fneg Z)) +    SDValue Neg1 = GetNegatedExpression(Op.getOperand(1), DAG, LegalOperations, +                                        ForCodeSize, Depth + 1); +    return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), +                       Op.getOperand(0), Neg1, Neg2, Flags); +  } +    case ISD::FP_EXTEND:    case ISD::FSIN:      return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), | 

