diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 131 | 
1 files changed, 98 insertions, 33 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index c8d0f5faf647..441437351852 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -24,6 +24,7 @@  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/Triple.h"  #include "llvm/ADT/Twine.h" +#include "llvm/Analysis/AliasAnalysis.h"  #include "llvm/Analysis/MemoryLocation.h"  #include "llvm/Analysis/ValueTracking.h"  #include "llvm/CodeGen/Analysis.h" @@ -602,7 +603,7 @@ static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) {  /// AddNodeIDOperands - Various routines for adding operands to the NodeID data.  static void AddNodeIDOperands(FoldingSetNodeID &ID,                                ArrayRef<SDValue> Ops) { -  for (auto& Op : Ops) { +  for (const auto &Op : Ops) {      ID.AddPointer(Op.getNode());      ID.AddInteger(Op.getResNo());    } @@ -611,7 +612,7 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID,  /// AddNodeIDOperands - Various routines for adding operands to the NodeID data.  static void AddNodeIDOperands(FoldingSetNodeID &ID,                                ArrayRef<SDUse> Ops) { -  for (auto& Op : Ops) { +  for (const auto &Op : Ops) {      ID.AddPointer(Op.getNode());      ID.AddInteger(Op.getResNo());    } @@ -2711,16 +2712,9 @@ bool SelectionDAG::isSplatValue(SDValue V, const APInt &DemandedElts,          SubDemandedElts &= ScaledDemandedElts;          if (!isSplatValue(Src, SubDemandedElts, SubUndefElts, Depth + 1))            return false; - -        // Here we can't do "MatchAnyBits" operation merge for undef bits. -        // Because some operation only use part value of the source. -        // Take llvm.fshl.* for example: -        // t1: v4i32 = Constant:i32<12>, undef:i32, Constant:i32<12>, undef:i32 -        // t2: v2i64 = bitcast t1 -        // t5: v2i64 = fshl t3, t4, t2 -        // We can not convert t2 to {i64 undef, i64 undef} -        UndefElts |= APIntOps::ScaleBitMask(SubUndefElts, NumElts, -                                            /*MatchAllBits=*/true); +        // TODO: Add support for merging sub undef elements. +        if (!SubUndefElts.isZero()) +          return false;        }        return true;      } @@ -2947,6 +2941,9 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,    unsigned Opcode = Op.getOpcode();    switch (Opcode) { +  case ISD::MERGE_VALUES: +    return computeKnownBits(Op.getOperand(Op.getResNo()), DemandedElts, +                            Depth + 1);    case ISD::BUILD_VECTOR:      // Collect the known bits that are shared by every demanded vector element.      Known.Zero.setAllBits(); Known.One.setAllBits(); @@ -3219,12 +3216,6 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,        Known = KnownBits::mulhs(Known, Known2);      break;    } -  case ISD::UDIV: { -    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); -    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); -    Known = KnownBits::udiv(Known, Known2); -    break; -  }    case ISD::AVGCEILU: {      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);      Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); @@ -3339,6 +3330,38 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,        Known.Zero |= Known2.Zero;      }      break; +  case ISD::SHL_PARTS: +  case ISD::SRA_PARTS: +  case ISD::SRL_PARTS: { +    assert((Op.getResNo() == 0 || Op.getResNo() == 1) && "Unknown result"); + +    // Collect lo/hi source values and concatenate. +    // TODO: Would a KnownBits::concatBits helper be useful? +    unsigned LoBits = Op.getOperand(0).getScalarValueSizeInBits(); +    unsigned HiBits = Op.getOperand(1).getScalarValueSizeInBits(); +    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); +    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); +    Known = Known.anyext(LoBits + HiBits); +    Known.insertBits(Known2, LoBits); + +    // Collect shift amount. +    Known2 = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1); + +    if (Opcode == ISD::SHL_PARTS) +      Known = KnownBits::shl(Known, Known2); +    else if (Opcode == ISD::SRA_PARTS) +      Known = KnownBits::ashr(Known, Known2); +    else // if (Opcode == ISD::SRL_PARTS) +      Known = KnownBits::lshr(Known, Known2); + +    // TODO: Minimum shift low/high bits are known zero. + +    if (Op.getResNo() == 0) +      Known = Known.extractBits(LoBits, 0); +    else +      Known = Known.extractBits(HiBits, LoBits); +    break; +  }    case ISD::SIGN_EXTEND_INREG: {      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);      EVT EVT = cast<VTSDNode>(Op.getOperand(1))->getVT(); @@ -3570,6 +3593,12 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,      Known = KnownBits::computeForAddCarry(Known, Known2, Carry);      break;    } +  case ISD::UDIV: { +    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1); +    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); +    Known = KnownBits::udiv(Known, Known2); +    break; +  }    case ISD::SREM: {      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);      Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1); @@ -3925,7 +3954,9 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,    case ISD::AssertZext:      Tmp = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();      return VTBits-Tmp; - +  case ISD::MERGE_VALUES: +    return ComputeNumSignBits(Op.getOperand(Op.getResNo()), DemandedElts, +                              Depth + 1);    case ISD::BUILD_VECTOR:      Tmp = VTBits;      for (unsigned i = 0, e = Op.getNumOperands(); (i < e) && (Tmp > 1); ++i) { @@ -6105,8 +6136,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,      assert(N1.getValueType().isVector() == VT.isVector() &&             "FP_TO_*INT_SAT type should be vector iff the operand type is "             "vector!"); -    assert((!VT.isVector() || VT.getVectorNumElements() == -                                  N1.getValueType().getVectorNumElements()) && +    assert((!VT.isVector() || VT.getVectorElementCount() == +                                  N1.getValueType().getVectorElementCount()) &&             "Vector element counts must match in FP_TO_*INT_SAT");      assert(!cast<VTSDNode>(N2)->getVT().isVector() &&             "Type to saturate to must be a scalar."); @@ -6719,7 +6750,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,                                         bool isVol, bool AlwaysInline,                                         MachinePointerInfo DstPtrInfo,                                         MachinePointerInfo SrcPtrInfo, -                                       const AAMDNodes &AAInfo) { +                                       const AAMDNodes &AAInfo, AAResults *AA) {    // Turn a memcpy of undef to nop.    // FIXME: We need to honor volatile even is Src is undef.    if (Src.isUndef()) @@ -6782,6 +6813,11 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,    AAMDNodes NewAAInfo = AAInfo;    NewAAInfo.TBAA = NewAAInfo.TBAAStruct = nullptr; +  const Value *SrcVal = SrcPtrInfo.V.dyn_cast<const Value *>(); +  bool isConstant = +      AA && SrcVal && +      AA->pointsToConstantMemory(MemoryLocation(SrcVal, Size, AAInfo)); +    MachineMemOperand::Flags MMOFlags =        isVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;    SmallVector<SDValue, 16> OutLoadChains; @@ -6843,6 +6879,8 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,        MachineMemOperand::Flags SrcMMOFlags = MMOFlags;        if (isDereferenceable)          SrcMMOFlags |= MachineMemOperand::MODereferenceable; +      if (isConstant) +        SrcMMOFlags |= MachineMemOperand::MOInvariant;        Value = DAG.getExtLoad(            ISD::EXTLOAD, dl, NVT, Chain, @@ -7131,7 +7169,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,                                  bool isVol, bool AlwaysInline, bool isTailCall,                                  MachinePointerInfo DstPtrInfo,                                  MachinePointerInfo SrcPtrInfo, -                                const AAMDNodes &AAInfo) { +                                const AAMDNodes &AAInfo, AAResults *AA) {    // Check to see if we should lower the memcpy to loads and stores first.    // For cases within the target-specified limits, this is the best choice.    ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); @@ -7142,7 +7180,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,      SDValue Result = getMemcpyLoadsAndStores(          *this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment, -        isVol, false, DstPtrInfo, SrcPtrInfo, AAInfo); +        isVol, false, DstPtrInfo, SrcPtrInfo, AAInfo, AA);      if (Result.getNode())        return Result;    } @@ -7161,9 +7199,9 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst,    // use a (potentially long) sequence of loads and stores.    if (AlwaysInline) {      assert(ConstantSize && "AlwaysInline requires a constant size!"); -    return getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src, -                                   ConstantSize->getZExtValue(), Alignment, -                                   isVol, true, DstPtrInfo, SrcPtrInfo, AAInfo); +    return getMemcpyLoadsAndStores( +        *this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment, +        isVol, true, DstPtrInfo, SrcPtrInfo, AAInfo, AA);    }    checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace()); @@ -7245,7 +7283,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst,                                   bool isVol, bool isTailCall,                                   MachinePointerInfo DstPtrInfo,                                   MachinePointerInfo SrcPtrInfo, -                                 const AAMDNodes &AAInfo) { +                                 const AAMDNodes &AAInfo, AAResults *AA) {    // Check to see if we should lower the memmove to loads and stores first.    // For cases within the target-specified limits, this is the best choice.    ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); @@ -8904,7 +8942,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,    }  #ifndef NDEBUG -  for (auto &Op : Ops) +  for (const auto &Op : Ops)      assert(Op.getOpcode() != ISD::DELETED_NODE &&             "Operand is DELETED_NODE!");  #endif @@ -8928,6 +8966,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,             "True and False arms of SelectCC must have same type!");      assert(Ops[2].getValueType() == VT &&             "select_cc node must be of same type as true and false value!"); +    assert((!Ops[0].getValueType().isVector() || +            Ops[0].getValueType().getVectorElementCount() == +                VT.getVectorElementCount()) && +           "Expected select_cc with vector result to have the same sized " +           "comparison type!");      break;    case ISD::BR_CC:      assert(NumOps == 5 && "BR_CC takes 5 operands!"); @@ -9018,12 +9061,34 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,      return getNode(Opcode, DL, VTList.VTs[0], Ops, Flags);  #ifndef NDEBUG -  for (auto &Op : Ops) +  for (const auto &Op : Ops)      assert(Op.getOpcode() != ISD::DELETED_NODE &&             "Operand is DELETED_NODE!");  #endif    switch (Opcode) { +  case ISD::SADDO: +  case ISD::UADDO: +  case ISD::SSUBO: +  case ISD::USUBO: { +    assert(VTList.NumVTs == 2 && Ops.size() == 2 && +           "Invalid add/sub overflow op!"); +    assert(VTList.VTs[0].isInteger() && VTList.VTs[1].isInteger() && +           Ops[0].getValueType() == Ops[1].getValueType() && +           Ops[0].getValueType() == VTList.VTs[0] && +           "Binary operator types must match!"); +    SDValue N1 = Ops[0], N2 = Ops[1]; +    canonicalizeCommutativeBinop(Opcode, N1, N2); + +    // (X +- 0) -> X with zero-overflow. +    ConstantSDNode *N2CV = isConstOrConstSplat(N2, /*AllowUndefs*/ false, +                                               /*AllowTruncation*/ true); +    if (N2CV && N2CV->isZero()) { +      SDValue ZeroOverFlow = getConstant(0, DL, VTList.VTs[1]); +      return getNode(ISD::MERGE_VALUES, DL, VTList, {N1, ZeroOverFlow}, Flags); +    } +    break; +  }    case ISD::STRICT_FP_EXTEND:      assert(VTList.NumVTs == 2 && Ops.size() == 2 &&             "Invalid STRICT_FP_EXTEND!"); @@ -9914,7 +9979,7 @@ void SelectionDAG::salvageDebugInfo(SDNode &N) {      return;    SmallVector<SDDbgValue *, 2> ClonedDVs; -  for (auto DV : GetDbgValues(&N)) { +  for (auto *DV : GetDbgValues(&N)) {      if (DV->isInvalidated())        continue;      switch (N.getOpcode()) { @@ -10268,7 +10333,7 @@ bool SelectionDAG::calculateDivergence(SDNode *N) {    }    if (TLI->isSDNodeSourceOfDivergence(N, FLI, DA))      return true; -  for (auto &Op : N->ops()) { +  for (const auto &Op : N->ops()) {      if (Op.Val.getValueType() != MVT::Other && Op.getNode()->isDivergent())        return true;    } @@ -10298,7 +10363,7 @@ void SelectionDAG::CreateTopologicalOrder(std::vector<SDNode *> &Order) {    }    for (size_t I = 0; I != Order.size(); ++I) {      SDNode *N = Order[I]; -    for (auto U : N->uses()) { +    for (auto *U : N->uses()) {        unsigned &UnsortedOps = Degree[U];        if (0 == --UnsortedOps)          Order.push_back(U);  | 
