diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:08 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-24 01:00:08 +0000 | 
| commit | c7dac04c3480f3c20487f912f77343139fce2d99 (patch) | |
| tree | 21a09bce0171e27bd1e92649db9df797fa097cea /lib/Target/Hexagon/HexagonISelLowering.cpp | |
| parent | 044eb2f6afba375a914ac9d8024f8f5142bb912e (diff) | |
Diffstat (limited to 'lib/Target/Hexagon/HexagonISelLowering.cpp')
| -rw-r--r-- | lib/Target/Hexagon/HexagonISelLowering.cpp | 345 | 
1 files changed, 216 insertions, 129 deletions
| diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 586363335df1..0e0da2ddc400 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -761,11 +761,13 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,      // Promote the value if needed.      switch (VA.getLocInfo()) {        default: -        // Loc info must be one of Full, SExt, ZExt, or AExt. +        // Loc info must be one of Full, BCvt, SExt, ZExt, or AExt.          llvm_unreachable("Unknown loc info!"); -      case CCValAssign::BCvt:        case CCValAssign::Full:          break; +      case CCValAssign::BCvt: +        Arg = DAG.getBitcast(VA.getLocVT(), Arg); +        break;        case CCValAssign::SExt:          Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);          break; @@ -1135,6 +1137,8 @@ SDValue HexagonTargetLowering::LowerFormalArguments(          unsigned VReg =            RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);          RegInfo.addLiveIn(VA.getLocReg(), VReg); +        if (VA.getLocInfo() == CCValAssign::BCvt) +          RegVT = VA.getValVT();          SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);          // Treat values of type MVT::i1 specially: they are passed in          // registers of type i32, but they need to remain as values of @@ -1155,6 +1159,8 @@ SDValue HexagonTargetLowering::LowerFormalArguments(          unsigned VReg =            RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);          RegInfo.addLiveIn(VA.getLocReg(), VReg); +        if (VA.getLocInfo() == CCValAssign::BCvt) +          RegVT = VA.getValVT();          InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));        // Single Vector @@ -1715,8 +1721,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,    addRegisterClass(MVT::v4i1,  &Hexagon::PredRegsRegClass);  // ddccbbaa    addRegisterClass(MVT::v8i1,  &Hexagon::PredRegsRegClass);  // hgfedcba    addRegisterClass(MVT::i32,   &Hexagon::IntRegsRegClass); -  addRegisterClass(MVT::v4i8,  &Hexagon::IntRegsRegClass);    addRegisterClass(MVT::v2i16, &Hexagon::IntRegsRegClass); +  addRegisterClass(MVT::v4i8,  &Hexagon::IntRegsRegClass);    addRegisterClass(MVT::i64,   &Hexagon::DoubleRegsRegClass);    addRegisterClass(MVT::v8i8,  &Hexagon::DoubleRegsRegClass);    addRegisterClass(MVT::v4i16, &Hexagon::DoubleRegsRegClass); @@ -1735,6 +1741,14 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,        addRegisterClass(MVT::v128i8, &Hexagon::HvxWRRegClass);        addRegisterClass(MVT::v64i16, &Hexagon::HvxWRRegClass);        addRegisterClass(MVT::v32i32, &Hexagon::HvxWRRegClass); +      // These "short" boolean vector types should be legal because +      // they will appear as results of vector compares. If they were +      // not legal, type legalization would try to make them legal +      // and that would require using operations that do not use or +      // produce such types. That, in turn, would imply using custom +      // nodes, which would be unoptimizable by the DAG combiner. +      // The idea is to rely on target-independent operations as much +      // as possible.        addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass);        addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass);        addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass); @@ -1964,9 +1978,8 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,    setLoadExtAction(ISD::SEXTLOAD, MVT::v4i16, MVT::v4i8, Legal);    // Types natively supported: -  for (MVT NativeVT : {MVT::v2i1, MVT::v4i1, MVT::v8i1, MVT::v32i1, MVT::v64i1, -                       MVT::v4i8, MVT::v8i8, MVT::v2i16, MVT::v4i16, MVT::v1i32, -                       MVT::v2i32, MVT::v1i64}) { +  for (MVT NativeVT : {MVT::v32i1, MVT::v64i1, MVT::v4i8, MVT::v8i8, MVT::v2i16, +                       MVT::v4i16, MVT::v1i32, MVT::v2i32, MVT::v1i64}) {      setOperationAction(ISD::BUILD_VECTOR,       NativeVT, Custom);      setOperationAction(ISD::EXTRACT_VECTOR_ELT, NativeVT, Custom);      setOperationAction(ISD::INSERT_VECTOR_ELT,  NativeVT, Custom); @@ -1992,63 +2005,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,      AddPromotedToType(Opc, FromTy, ToTy);    }; -  if (Subtarget.useHVXOps()) { -    bool Use64b = Subtarget.useHVX64BOps(); -    ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128; -    ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128; -    MVT ByteV = Use64b ?  MVT::v64i8 : MVT::v128i8; -    MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8; - -    setOperationAction(ISD::VECTOR_SHUFFLE, ByteV, Legal); -    setOperationAction(ISD::VECTOR_SHUFFLE, ByteW, Legal); -    setOperationAction(ISD::CONCAT_VECTORS, ByteW, Legal); -    setOperationAction(ISD::AND,            ByteV, Legal); -    setOperationAction(ISD::OR,             ByteV, Legal); -    setOperationAction(ISD::XOR,            ByteV, Legal); - -    for (MVT T : LegalV) { -      setIndexedLoadAction(ISD::POST_INC,  T, Legal); -      setIndexedStoreAction(ISD::POST_INC, T, Legal); - -      setOperationAction(ISD::ADD,     T, Legal); -      setOperationAction(ISD::SUB,     T, Legal); -      setOperationAction(ISD::VSELECT, T, Legal); -      if (T != ByteV) { -        setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal); -        setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); -      } - -      setOperationAction(ISD::MUL,                T, Custom); -      setOperationAction(ISD::SETCC,              T, Custom); -      setOperationAction(ISD::BUILD_VECTOR,       T, Custom); -      setOperationAction(ISD::INSERT_SUBVECTOR,   T, Custom); -      setOperationAction(ISD::INSERT_VECTOR_ELT,  T, Custom); -      setOperationAction(ISD::EXTRACT_SUBVECTOR,  T, Custom); -      setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom); -      if (T != ByteV) -        setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom); -    } - -    for (MVT T : LegalV) { -      if (T == ByteV) -        continue; -      // Promote all shuffles and concats to operate on vectors of bytes. -      setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV); -      setPromoteTo(ISD::CONCAT_VECTORS, T, ByteV); -      setPromoteTo(ISD::AND,            T, ByteV); -      setPromoteTo(ISD::OR,             T, ByteV); -      setPromoteTo(ISD::XOR,            T, ByteV); -    } - -    for (MVT T : LegalW) { -      if (T == ByteW) -        continue; -      // Promote all shuffles and concats to operate on vectors of bytes. -      setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW); -      setPromoteTo(ISD::CONCAT_VECTORS, T, ByteW); -    } -  } -    // Subtarget-specific operation actions.    //    if (Subtarget.hasV5TOps()) { @@ -2110,6 +2066,67 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,      setIndexedStoreAction(ISD::POST_INC, VT, Legal);    } +  if (Subtarget.useHVXOps()) { +    bool Use64b = Subtarget.useHVX64BOps(); +    ArrayRef<MVT> LegalV = Use64b ? LegalV64 : LegalV128; +    ArrayRef<MVT> LegalW = Use64b ? LegalW64 : LegalW128; +    MVT ByteV = Use64b ?  MVT::v64i8 : MVT::v128i8; +    MVT ByteW = Use64b ? MVT::v128i8 : MVT::v256i8; + +    setOperationAction(ISD::VECTOR_SHUFFLE, ByteV, Legal); +    setOperationAction(ISD::VECTOR_SHUFFLE, ByteW, Legal); +    setOperationAction(ISD::CONCAT_VECTORS, ByteW, Legal); +    setOperationAction(ISD::AND,            ByteV, Legal); +    setOperationAction(ISD::OR,             ByteV, Legal); +    setOperationAction(ISD::XOR,            ByteV, Legal); + +    for (MVT T : LegalV) { +      setIndexedLoadAction(ISD::POST_INC,  T, Legal); +      setIndexedStoreAction(ISD::POST_INC, T, Legal); + +      setOperationAction(ISD::ADD,     T, Legal); +      setOperationAction(ISD::SUB,     T, Legal); +      if (T != ByteV) { +        setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal); +        setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); +      } + +      setOperationAction(ISD::MUL,                T, Custom); +      setOperationAction(ISD::SETCC,              T, Custom); +      setOperationAction(ISD::BUILD_VECTOR,       T, Custom); +      setOperationAction(ISD::INSERT_SUBVECTOR,   T, Custom); +      setOperationAction(ISD::INSERT_VECTOR_ELT,  T, Custom); +      setOperationAction(ISD::EXTRACT_SUBVECTOR,  T, Custom); +      setOperationAction(ISD::EXTRACT_VECTOR_ELT, T, Custom); +      if (T != ByteV) +        setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom); +    } + +    for (MVT T : LegalV) { +      if (T == ByteV) +        continue; +      // Promote all shuffles and concats to operate on vectors of bytes. +      setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteV); +      setPromoteTo(ISD::CONCAT_VECTORS, T, ByteV); +      setPromoteTo(ISD::AND,            T, ByteV); +      setPromoteTo(ISD::OR,             T, ByteV); +      setPromoteTo(ISD::XOR,            T, ByteV); +    } + +    for (MVT T : LegalW) { +      // Custom-lower BUILD_VECTOR for vector pairs. The standard (target- +      // independent) handling of it would convert it to a load, which is +      // not always the optimal choice. +      setOperationAction(ISD::BUILD_VECTOR, T, Custom); + +      if (T == ByteW) +        continue; +      // Promote all shuffles and concats to operate on vectors of bytes. +      setPromoteTo(ISD::VECTOR_SHUFFLE, T, ByteW); +      setPromoteTo(ISD::CONCAT_VECTORS, T, ByteW); +    } +  } +    computeRegisterProperties(&HRI);    // @@ -2256,6 +2273,7 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {    case HexagonISD::VINSERTW0:     return "HexagonISD::VINSERTW0";    case HexagonISD::VROR:          return "HexagonISD::VROR";    case HexagonISD::READCYCLE:     return "HexagonISD::READCYCLE"; +  case HexagonISD::VZERO:         return "HexagonISD::VZERO";    case HexagonISD::OP_END:        break;    }    return nullptr; @@ -2331,14 +2349,27 @@ bool HexagonTargetLowering::isShuffleMaskLegal(ArrayRef<int> Mask,  TargetLoweringBase::LegalizeTypeAction  HexagonTargetLowering::getPreferredVectorAction(EVT VT) const { +  if (VT.getVectorNumElements() == 1) +    return TargetLoweringBase::TypeScalarizeVector; + +  // Always widen vectors of i1. +  MVT ElemTy = VT.getSimpleVT().getVectorElementType(); +  if (ElemTy == MVT::i1) +    return TargetLoweringBase::TypeWidenVector; +    if (Subtarget.useHVXOps()) {      // If the size of VT is at least half of the vector length,      // widen the vector. Note: the threshold was not selected in      // any scientific way. -    if (VT.getSizeInBits() >= Subtarget.getVectorLength()*8/2) -      return TargetLoweringBase::TypeWidenVector; +    ArrayRef<MVT> Tys = Subtarget.getHVXElementTypes(); +    if (llvm::find(Tys, ElemTy) != Tys.end()) { +      unsigned HwWidth = 8*Subtarget.getVectorLength(); +      unsigned VecWidth = VT.getSizeInBits(); +      if (VecWidth >= HwWidth/2 && VecWidth < HwWidth) +        return TargetLoweringBase::TypeWidenVector; +    }    } -  return TargetLowering::getPreferredVectorAction(VT); +  return TargetLoweringBase::TypeSplitVector;  }  // Lower a vector shuffle (V1, V2, V3).  V1 and V2 are the two vectors @@ -2463,21 +2494,43 @@ HexagonTargetLowering::LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const {    return DAG.getNode(ISD::BITCAST, dl, VT, Result);  } +bool +HexagonTargetLowering::getBuildVectorConstInts(ArrayRef<SDValue> Values, +      MVT VecTy, SelectionDAG &DAG, +      MutableArrayRef<ConstantInt*> Consts) const { +  MVT ElemTy = VecTy.getVectorElementType(); +  unsigned ElemWidth = ElemTy.getSizeInBits(); +  IntegerType *IntTy = IntegerType::get(*DAG.getContext(), ElemWidth); +  bool AllConst = true; + +  for (unsigned i = 0, e = Values.size(); i != e; ++i) { +    SDValue V = Values[i]; +    if (V.isUndef()) { +      Consts[i] = ConstantInt::get(IntTy, 0); +      continue; +    } +    if (auto *CN = dyn_cast<ConstantSDNode>(V.getNode())) { +      const ConstantInt *CI = CN->getConstantIntValue(); +      Consts[i] = const_cast<ConstantInt*>(CI); +    } else if (auto *CN = dyn_cast<ConstantFPSDNode>(V.getNode())) { +      const ConstantFP *CF = CN->getConstantFPValue(); +      APInt A = CF->getValueAPF().bitcastToAPInt(); +      Consts[i] = ConstantInt::get(IntTy, A.getZExtValue()); +    } else { +      AllConst = false; +    } +  } +  return AllConst; +} +  SDValue  HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl,                                       MVT VecTy, SelectionDAG &DAG) const {    MVT ElemTy = VecTy.getVectorElementType();    assert(VecTy.getVectorNumElements() == Elem.size()); -  SmallVector<ConstantSDNode*,4> Consts; -  bool AllConst = true; -  for (SDValue V : Elem) { -    if (isUndef(V)) -      V = DAG.getConstant(0, dl, ElemTy); -    auto *C = dyn_cast<ConstantSDNode>(V.getNode()); -    Consts.push_back(C); -    AllConst = AllConst && C != nullptr; -  } +  SmallVector<ConstantInt*,4> Consts(Elem.size()); +  bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);    unsigned First, Num = Elem.size();    for (First = 0; First != Num; ++First) @@ -2486,6 +2539,10 @@ HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl,    if (First == Num)      return DAG.getUNDEF(VecTy); +  if (AllConst && +      llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); })) +    return getZero(dl, VecTy, DAG); +    if (ElemTy == MVT::i16) {      assert(Elem.size() == 2);      if (AllConst) { @@ -2498,45 +2555,55 @@ HexagonTargetLowering::buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl,      return DAG.getBitcast(MVT::v2i16, N);    } -  // First try generating a constant. -  assert(ElemTy == MVT::i8 && Num == 4); -  if (AllConst) { -    int32_t V = (Consts[0]->getZExtValue() & 0xFF) | -                (Consts[1]->getZExtValue() & 0xFF) << 8 | -                (Consts[1]->getZExtValue() & 0xFF) << 16 | -                Consts[2]->getZExtValue() << 24; -    return DAG.getBitcast(MVT::v4i8, DAG.getConstant(V, dl, MVT::i32)); -  } +  if (ElemTy == MVT::i8) { +    // First try generating a constant. +    if (AllConst) { +      int32_t V = (Consts[0]->getZExtValue() & 0xFF) | +                  (Consts[1]->getZExtValue() & 0xFF) << 8 | +                  (Consts[1]->getZExtValue() & 0xFF) << 16 | +                  Consts[2]->getZExtValue() << 24; +      return DAG.getBitcast(MVT::v4i8, DAG.getConstant(V, dl, MVT::i32)); +    } -  // Then try splat. -  bool IsSplat = true; -  for (unsigned i = 0; i != Num; ++i) { -    if (i == First) -      continue; -    if (Elem[i] == Elem[First] || isUndef(Elem[i])) -      continue; -    IsSplat = false; -    break; -  } -  if (IsSplat) -    return DAG.getNode(HexagonISD::VSPLAT, dl, VecTy, Elem[First]); +    // Then try splat. +    bool IsSplat = true; +    for (unsigned i = 0; i != Num; ++i) { +      if (i == First) +        continue; +      if (Elem[i] == Elem[First] || isUndef(Elem[i])) +        continue; +      IsSplat = false; +      break; +    } +    if (IsSplat) { +      // Legalize the operand to VSPLAT. +      SDValue Ext = DAG.getZExtOrTrunc(Elem[First], dl, MVT::i32); +      return DAG.getNode(HexagonISD::VSPLAT, dl, VecTy, Ext); +    } -  // Generate -  //   (zxtb(Elem[0]) | (zxtb(Elem[1]) << 8)) | -  //   (zxtb(Elem[2]) | (zxtb(Elem[3]) << 8)) << 16 -  SDValue S8 = DAG.getConstant(8, dl, MVT::i32); -  SDValue V0 = DAG.getZeroExtendInReg(Elem[0], dl, MVT::i8); -  SDValue V1 = DAG.getZeroExtendInReg(Elem[1], dl, MVT::i8); -  SDValue V2 = DAG.getZeroExtendInReg(Elem[2], dl, MVT::i8); -  SDValue V3 = DAG.getZeroExtendInReg(Elem[3], dl, MVT::i8); +    // Generate +    //   (zxtb(Elem[0]) | (zxtb(Elem[1]) << 8)) | +    //   (zxtb(Elem[2]) | (zxtb(Elem[3]) << 8)) << 16 +    assert(Elem.size() == 4); +    SDValue Vs[4]; +    for (unsigned i = 0; i != 4; ++i) { +      Vs[i] = DAG.getZExtOrTrunc(Elem[i], dl, MVT::i32); +      Vs[i] = DAG.getZeroExtendInReg(Vs[i], dl, MVT::i8); +    } +    SDValue S8 = DAG.getConstant(8, dl, MVT::i32); +    SDValue T0 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[1], S8}); +    SDValue T1 = DAG.getNode(ISD::SHL, dl, MVT::i32, {Vs[3], S8}); +    SDValue B0 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[0], T0}); +    SDValue B1 = DAG.getNode(ISD::OR, dl, MVT::i32, {Vs[2], T1}); -  SDValue V4 = DAG.getNode(ISD::SHL, dl, MVT::i32, {V1, S8}); -  SDValue V5 = DAG.getNode(ISD::SHL, dl, MVT::i32, {V3, S8}); -  SDValue V6 = DAG.getNode(ISD::OR, dl, MVT::i32, {V0, V4}); -  SDValue V7 = DAG.getNode(ISD::OR, dl, MVT::i32, {V2, V5}); +    SDValue R = getNode(Hexagon::A2_combine_ll, dl, MVT::i32, {B1, B0}, DAG); +    return DAG.getBitcast(MVT::v4i8, R); +  } -  SDValue T0 = getNode(Hexagon::A2_combine_ll, dl, MVT::i32, {V7, V6}, DAG); -  return DAG.getBitcast(MVT::v4i8, T0); +#ifndef NDEBUG +  dbgs() << "VecTy: " << EVT(VecTy).getEVTString() << '\n'; +#endif +  llvm_unreachable("Unexpected vector element type");  }  SDValue @@ -2545,15 +2612,8 @@ HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,    MVT ElemTy = VecTy.getVectorElementType();    assert(VecTy.getVectorNumElements() == Elem.size()); -  SmallVector<ConstantSDNode*,8> Consts; -  bool AllConst = true; -  for (SDValue V : Elem) { -    if (isUndef(V)) -      V = DAG.getConstant(0, dl, ElemTy); -    auto *C = dyn_cast<ConstantSDNode>(V.getNode()); -    Consts.push_back(C); -    AllConst = AllConst && C != nullptr; -  } +  SmallVector<ConstantInt*,8> Consts(Elem.size()); +  bool AllConst = getBuildVectorConstInts(Elem, VecTy, DAG, Consts);    unsigned First, Num = Elem.size();    for (First = 0; First != Num; ++First) @@ -2562,6 +2622,10 @@ HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,    if (First == Num)      return DAG.getUNDEF(VecTy); +  if (AllConst && +      llvm::all_of(Consts, [](ConstantInt *CI) { return CI->isZero(); })) +    return getZero(dl, VecTy, DAG); +    // First try splat if possible.    if (ElemTy == MVT::i16) {      bool IsSplat = true; @@ -2573,8 +2637,11 @@ HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,        IsSplat = false;        break;      } -    if (IsSplat) -      return DAG.getNode(HexagonISD::VSPLAT, dl, VecTy, Elem[First]); +    if (IsSplat) { +      // Legalize the operand to VSPLAT. +      SDValue Ext = DAG.getZExtOrTrunc(Elem[First], dl, MVT::i32); +      return DAG.getNode(HexagonISD::VSPLAT, dl, VecTy, Ext); +    }    }    // Then try constant. @@ -2593,10 +2660,10 @@ HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,    MVT HalfTy = MVT::getVectorVT(ElemTy, Num/2);    SDValue L = (ElemTy == MVT::i32)                  ? Elem[0] -                : buildVector32({Elem.data(), Num/2}, dl, HalfTy, DAG); +                : buildVector32(Elem.take_front(Num/2), dl, HalfTy, DAG);    SDValue H = (ElemTy == MVT::i32)                  ? Elem[1] -                : buildVector32({Elem.data()+Num/2, Num/2}, dl, HalfTy, DAG); +                : buildVector32(Elem.drop_front(Num/2), dl, HalfTy, DAG);    return DAG.getNode(HexagonISD::COMBINE, dl, VecTy, {H, L});  } @@ -2696,21 +2763,41 @@ HexagonTargetLowering::insertVector(SDValue VecV, SDValue ValV, SDValue IdxV,  }  SDValue +HexagonTargetLowering::getZero(const SDLoc &dl, MVT Ty, SelectionDAG &DAG) +      const { +  if (Ty.isVector()) { +    assert(Ty.isInteger() && "Only integer vectors are supported here"); +    unsigned W = Ty.getSizeInBits(); +    if (W <= 64) +      return DAG.getBitcast(Ty, DAG.getConstant(0, dl, MVT::getIntegerVT(W))); +    return DAG.getNode(HexagonISD::VZERO, dl, Ty); +  } + +  if (Ty.isInteger()) +    return DAG.getConstant(0, dl, Ty); +  if (Ty.isFloatingPoint()) +    return DAG.getConstantFP(0.0, dl, Ty); +  llvm_unreachable("Invalid type for zero"); +} + +SDValue  HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {    MVT VecTy = ty(Op);    unsigned BW = VecTy.getSizeInBits(); + +  if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy, true)) +    return LowerHvxBuildVector(Op, DAG); +    if (BW == 32 || BW == 64) { +    const SDLoc &dl(Op);      SmallVector<SDValue,8> Ops;      for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i)        Ops.push_back(Op.getOperand(i));      if (BW == 32) -      return buildVector32(Ops, SDLoc(Op), VecTy, DAG); -    return buildVector64(Ops, SDLoc(Op), VecTy, DAG); +      return buildVector32(Ops, dl, VecTy, DAG); +    return buildVector64(Ops, dl, VecTy, DAG);    } -  if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy)) -    return LowerHvxBuildVector(Op, DAG); -    return SDValue();  } @@ -2822,7 +2909,7 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {  #ifndef NDEBUG        Op.getNode()->dumpr(&DAG);        if (Opc > HexagonISD::OP_BEGIN && Opc < HexagonISD::OP_END) -        errs() << "Check for a non-legal type in this operation\n"; +        errs() << "Error: check for a non-legal type in this operation\n";  #endif        llvm_unreachable("Should not custom lower this!");      case ISD::CONCAT_VECTORS:       return LowerCONCAT_VECTORS(Op, DAG); | 
