diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 308 | 
1 files changed, 32 insertions, 276 deletions
| diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 2b47407393d..9b678b22b46 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -785,252 +785,6 @@ void DAGCombiner::deleteAndRecombine(SDNode *N) {    DAG.DeleteNode(N);  } -/// Return 1 if we can compute the negated form of the specified expression for -/// the same cost as the expression itself, or 2 if we can compute the negated -/// form more cheaply than the expression itself. -static char isNegatibleForFree(SDValue Op, bool LegalOperations, -                               const TargetLowering &TLI, -                               const TargetOptions *Options, -                               bool ForCodeSize, -                               unsigned Depth = 0) { -  // fneg is removable even if it has multiple uses. -  if (Op.getOpcode() == ISD::FNEG) -    return 2; - -  // 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() && -      !(Op.getOpcode() == ISD::FP_EXTEND && -        TLI.isFPExtFree(VT, Op.getOperand(0).getValueType()))) -    return 0; - -  // Don't recurse exponentially. -  if (Depth > SelectionDAG::MaxRecursionDepth) -    return 0; - -  switch (Op.getOpcode()) { -  default: return false; -  case ISD::ConstantFP: { -    if (!LegalOperations) -      return 1; - -    // Don't invert constant FP values after legalization unless the target says -    // the negated constant is legal. -    return TLI.isOperationLegal(ISD::ConstantFP, VT) || -           TLI.isFPImmLegal(neg(cast<ConstantFPSDNode>(Op)->getValueAPF()), VT, -                            ForCodeSize); -  } -  case ISD::BUILD_VECTOR: { -    // Only permit BUILD_VECTOR of constants. -    if (llvm::any_of(Op->op_values(), [&](SDValue N) { -          return !N.isUndef() && !isa<ConstantFPSDNode>(N); -        })) -      return 0; -    if (!LegalOperations) -      return 1; -    if (TLI.isOperationLegal(ISD::ConstantFP, VT) && -        TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) -      return 1; -    return llvm::all_of(Op->op_values(), [&](SDValue N) { -      return N.isUndef() || -             TLI.isFPImmLegal(neg(cast<ConstantFPSDNode>(N)->getValueAPF()), VT, -                              ForCodeSize); -    }); -  } -  case ISD::FADD: -    if (!Options->NoSignedZerosFPMath && !Flags.hasNoSignedZeros()) -      return 0; - -    // After operation legalization, it might not be legal to create new FSUBs. -    if (LegalOperations && !TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) -      return 0; - -    // fold (fneg (fadd A, B)) -> (fsub (fneg A), B) -    if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI, -                                    Options, ForCodeSize, Depth + 1)) -      return V; -    // fold (fneg (fadd A, B)) -> (fsub (fneg B), A) -    return isNegatibleForFree(Op.getOperand(1), LegalOperations, TLI, Options, -                              ForCodeSize, Depth + 1); -  case ISD::FSUB: -    // We can't turn -(A-B) into B-A when we honor signed zeros. -    if (!Options->NoSignedZerosFPMath && !Flags.hasNoSignedZeros()) -      return 0; - -    // fold (fneg (fsub A, B)) -> (fsub B, A) -    return 1; - -  case ISD::FMUL: -  case ISD::FDIV: -    // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) or (fmul X, (fneg Y)) -    if (char V = isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI, -                                    Options, ForCodeSize, Depth + 1)) -      return V; - -    // Ignore X * 2.0 because that is expected to be canonicalized to X + X. -    if (auto *C = isConstOrConstSplatFP(Op.getOperand(1))) -      if (C->isExactlyValue(2.0) && Op.getOpcode() == ISD::FMUL) -        return 0; - -    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: -    return isNegatibleForFree(Op.getOperand(0), LegalOperations, TLI, Options, -                              ForCodeSize, Depth + 1); -  } -} - -/// If isNegatibleForFree returns true, return the newly negated expression. -static SDValue GetNegatedExpression(SDValue Op, SelectionDAG &DAG, -                                    bool LegalOperations, bool ForCodeSize, -                                    unsigned Depth = 0) { -  // fneg is removable even if it has multiple uses. -  if (Op.getOpcode() == ISD::FNEG) -    return Op.getOperand(0); - -  assert(Depth <= SelectionDAG::MaxRecursionDepth && -         "GetNegatedExpression doesn't match isNegatibleForFree"); -  const TargetOptions &Options = DAG.getTarget().Options; -  const SDNodeFlags Flags = Op->getFlags(); - -  switch (Op.getOpcode()) { -  default: llvm_unreachable("Unknown code"); -  case ISD::ConstantFP: { -    APFloat V = cast<ConstantFPSDNode>(Op)->getValueAPF(); -    V.changeSign(); -    return DAG.getConstantFP(V, SDLoc(Op), Op.getValueType()); -  } -  case ISD::BUILD_VECTOR: { -    SmallVector<SDValue, 4> Ops; -    for (SDValue C : Op->op_values()) { -      if (C.isUndef()) { -        Ops.push_back(C); -        continue; -      } -      APFloat V = cast<ConstantFPSDNode>(C)->getValueAPF(); -      V.changeSign(); -      Ops.push_back(DAG.getConstantFP(V, SDLoc(Op), C.getValueType())); -    } -    return DAG.getBuildVector(Op.getValueType(), SDLoc(Op), Ops); -  } -  case ISD::FADD: -    assert((Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros()) && -           "Expected NSZ fp-flag"); - -    // fold (fneg (fadd A, B)) -> (fsub (fneg A), B) -    if (isNegatibleForFree(Op.getOperand(0), LegalOperations, -                           DAG.getTargetLoweringInfo(), &Options, ForCodeSize, -                           Depth + 1)) -      return DAG.getNode(ISD::FSUB, SDLoc(Op), Op.getValueType(), -                         GetNegatedExpression(Op.getOperand(0), DAG, -                                              LegalOperations, ForCodeSize, -                                              Depth + 1), -                         Op.getOperand(1), Flags); -    // fold (fneg (fadd A, B)) -> (fsub (fneg B), A) -    return DAG.getNode(ISD::FSUB, SDLoc(Op), Op.getValueType(), -                       GetNegatedExpression(Op.getOperand(1), DAG, -                                            LegalOperations, ForCodeSize, -                                            Depth + 1), -                       Op.getOperand(0), Flags); -  case ISD::FSUB: -    // fold (fneg (fsub 0, B)) -> B -    if (ConstantFPSDNode *N0CFP = -            isConstOrConstSplatFP(Op.getOperand(0), /*AllowUndefs*/ true)) -      if (N0CFP->isZero()) -        return Op.getOperand(1); - -    // fold (fneg (fsub A, B)) -> (fsub B, A) -    return DAG.getNode(ISD::FSUB, SDLoc(Op), Op.getValueType(), -                       Op.getOperand(1), Op.getOperand(0), Flags); - -  case ISD::FMUL: -  case ISD::FDIV: -    // fold (fneg (fmul X, Y)) -> (fmul (fneg X), Y) -    if (isNegatibleForFree(Op.getOperand(0), LegalOperations, -                           DAG.getTargetLoweringInfo(), &Options, ForCodeSize, -                           Depth + 1)) -      return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), -                         GetNegatedExpression(Op.getOperand(0), DAG, -                                              LegalOperations, ForCodeSize, -                                              Depth + 1), -                         Op.getOperand(1), Flags); - -    // fold (fneg (fmul X, Y)) -> (fmul X, (fneg Y)) -    return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), -                       Op.getOperand(0), -                       GetNegatedExpression(Op.getOperand(1), 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(), -                       GetNegatedExpression(Op.getOperand(0), DAG, -                                            LegalOperations, ForCodeSize, -                                            Depth + 1)); -  case ISD::FP_ROUND: -    return DAG.getNode(ISD::FP_ROUND, SDLoc(Op), Op.getValueType(), -                       GetNegatedExpression(Op.getOperand(0), DAG, -                                            LegalOperations, ForCodeSize, -                                            Depth + 1), -                       Op.getOperand(1)); -  } -} -  // APInts must be the same size for most operations, this helper  // function zero extends the shorter of the pair so that they match.  // We provide an Offset so that we can create bitwidths that won't overflow. @@ -12052,17 +11806,17 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {    // fold (fadd A, (fneg B)) -> (fsub A, B)    if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) && -      isNegatibleForFree(N1, LegalOperations, TLI, &Options, ForCodeSize) == 2) -    return DAG.getNode(ISD::FSUB, DL, VT, N0, -                       GetNegatedExpression(N1, DAG, LegalOperations, -                                            ForCodeSize), Flags); +      TLI.isNegatibleForFree(N1, DAG, LegalOperations, ForCodeSize) == 2) +    return DAG.getNode( +        ISD::FSUB, DL, VT, N0, +        TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize), Flags);    // fold (fadd (fneg A), B) -> (fsub B, A)    if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT)) && -      isNegatibleForFree(N0, LegalOperations, TLI, &Options, ForCodeSize) == 2) -    return DAG.getNode(ISD::FSUB, DL, VT, N1, -                       GetNegatedExpression(N0, DAG, LegalOperations, -                                            ForCodeSize), Flags); +      TLI.isNegatibleForFree(N0, DAG, LegalOperations, ForCodeSize) == 2) +    return DAG.getNode( +        ISD::FSUB, DL, VT, N1, +        TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize), Flags);    auto isFMulNegTwo = [](SDValue FMul) {      if (!FMul.hasOneUse() || FMul.getOpcode() != ISD::FMUL) @@ -12241,16 +11995,16 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {    if (N0CFP && N0CFP->isZero()) {      if (N0CFP->isNegative() ||          (Options.NoSignedZerosFPMath || Flags.hasNoSignedZeros())) { -      if (isNegatibleForFree(N1, LegalOperations, TLI, &Options, ForCodeSize)) -        return GetNegatedExpression(N1, DAG, LegalOperations, ForCodeSize); +      if (TLI.isNegatibleForFree(N1, DAG, LegalOperations, ForCodeSize)) +        return TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize);        if (!LegalOperations || TLI.isOperationLegal(ISD::FNEG, VT))          return DAG.getNode(ISD::FNEG, DL, VT, N1, Flags);      }    }    if (((Options.UnsafeFPMath && Options.NoSignedZerosFPMath) || -      (Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) -      && N1.getOpcode() == ISD::FADD) { +       (Flags.hasAllowReassociation() && Flags.hasNoSignedZeros())) && +      N1.getOpcode() == ISD::FADD) {      // X - (X + Y) -> -Y      if (N0 == N1->getOperand(0))        return DAG.getNode(ISD::FNEG, DL, VT, N1->getOperand(1), Flags); @@ -12260,10 +12014,10 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {    }    // fold (fsub A, (fneg B)) -> (fadd A, B) -  if (isNegatibleForFree(N1, LegalOperations, TLI, &Options, ForCodeSize)) -    return DAG.getNode(ISD::FADD, DL, VT, N0, -                       GetNegatedExpression(N1, DAG, LegalOperations, -                                            ForCodeSize), Flags); +  if (TLI.isNegatibleForFree(N1, DAG, LegalOperations, ForCodeSize)) +    return DAG.getNode( +        ISD::FADD, DL, VT, N0, +        TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize), Flags);    // FSUB -> FMA combines:    if (SDValue Fused = visitFSUBForFMACombine(N)) { @@ -12277,11 +12031,10 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {  /// Return true if both inputs are at least as cheap in negated form and at  /// least one input is strictly cheaper in negated form.  bool DAGCombiner::isCheaperToUseNegatedFPOps(SDValue X, SDValue Y) { -  const TargetOptions &Options = DAG.getTarget().Options; -  if (char LHSNeg = isNegatibleForFree(X, LegalOperations, TLI, &Options, -                                   ForCodeSize)) -    if (char RHSNeg = isNegatibleForFree(Y, LegalOperations, TLI, &Options, -                                         ForCodeSize)) +  if (char LHSNeg = +          TLI.isNegatibleForFree(X, DAG, LegalOperations, ForCodeSize)) +    if (char RHSNeg = +            TLI.isNegatibleForFree(Y, DAG, LegalOperations, ForCodeSize))        // Both negated operands are at least as cheap as their counterparts.        // Check to see if at least one is cheaper negated.        if (LHSNeg == 2 || RHSNeg == 2) @@ -12362,8 +12115,10 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {    // -N0 * -N1 --> N0 * N1    if (isCheaperToUseNegatedFPOps(N0, N1)) { -    SDValue NegN0 = GetNegatedExpression(N0, DAG, LegalOperations, ForCodeSize); -    SDValue NegN1 = GetNegatedExpression(N1, DAG, LegalOperations, ForCodeSize); +    SDValue NegN0 = +        TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize); +    SDValue NegN1 = +        TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize);      return DAG.getNode(ISD::FMUL, DL, VT, NegN0, NegN1, Flags);    } @@ -12445,8 +12200,10 @@ SDValue DAGCombiner::visitFMA(SDNode *N) {    // (-N0 * -N1) + N2 --> (N0 * N1) + N2    if (isCheaperToUseNegatedFPOps(N0, N1)) { -    SDValue NegN0 = GetNegatedExpression(N0, DAG, LegalOperations, ForCodeSize); -    SDValue NegN1 = GetNegatedExpression(N1, DAG, LegalOperations, ForCodeSize); +    SDValue NegN0 = +        TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize); +    SDValue NegN1 = +        TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize);      return DAG.getNode(ISD::FMA, DL, VT, NegN0, NegN1, N2, Flags);    } @@ -12707,8 +12464,8 @@ SDValue DAGCombiner::visitFDIV(SDNode *N) {    if (isCheaperToUseNegatedFPOps(N0, N1))      return DAG.getNode(          ISD::FDIV, SDLoc(N), VT, -        GetNegatedExpression(N0, DAG, LegalOperations, ForCodeSize), -        GetNegatedExpression(N1, DAG, LegalOperations, ForCodeSize), Flags); +        TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize), +        TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize), Flags);    return SDValue();  } @@ -13262,9 +13019,8 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {    if (isConstantFPBuildVectorOrConstantFP(N0))      return DAG.getNode(ISD::FNEG, SDLoc(N), VT, N0); -  if (isNegatibleForFree(N0, LegalOperations, DAG.getTargetLoweringInfo(), -                         &DAG.getTarget().Options, ForCodeSize)) -    return GetNegatedExpression(N0, DAG, LegalOperations, ForCodeSize); +  if (TLI.isNegatibleForFree(N0, DAG, LegalOperations, ForCodeSize)) +    return TLI.getNegatedExpression(N0, DAG, LegalOperations, ForCodeSize);    // Transform fneg(bitconvert(x)) -> bitconvert(x ^ sign) to avoid loading    // constant pool values. | 

