diff options
-rw-r--r-- | lib/Target/Hexagon/HexagonISelLowering.cpp | 258 | ||||
-rw-r--r-- | lib/Target/Hexagon/HexagonISelLowering.h | 25 |
2 files changed, 144 insertions, 139 deletions
diff --git a/lib/Target/Hexagon/HexagonISelLowering.cpp b/lib/Target/Hexagon/HexagonISelLowering.cpp index 2005ca6360c..087a6d69439 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -2580,6 +2580,101 @@ HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl, } SDValue +HexagonTargetLowering::extractVector(SDValue VecV, SDValue IdxV, + const SDLoc &dl, MVT ValTy, MVT ResTy, + SelectionDAG &DAG) const { + MVT VecTy = ty(VecV); + assert(!ValTy.isVector() || + VecTy.getVectorElementType() == ValTy.getVectorElementType()); + unsigned VecWidth = VecTy.getSizeInBits(); + unsigned ValWidth = ValTy.getSizeInBits(); + unsigned ElemWidth = VecTy.getVectorElementType().getSizeInBits(); + assert(VecWidth == 32 || VecWidth == 64); + assert((VecWidth % ElemWidth) == 0); + + // Cast everything to scalar integer types. + MVT ScalarTy = tyScalar(VecTy); + VecV = DAG.getBitcast(ScalarTy, VecV); + + SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32); + SDValue ExtV; + + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) { + unsigned Off = C->getZExtValue() * ElemWidth; + if (VecWidth == 64 && ValWidth == 32) { + assert(Off == 0 || Off == 32); + unsigned SubIdx = Off == 0 ? Hexagon::isub_lo : Hexagon::isub_hi; + ExtV = DAG.getTargetExtractSubreg(SubIdx, dl, MVT::i32, VecV); + } else if (Off == 0 && (ValWidth % 8) == 0) { + ExtV = DAG.getZeroExtendInReg(VecV, dl, tyScalar(ValTy)); + } else { + SDValue OffV = DAG.getConstant(Off, dl, MVT::i32); + // The return type of EXTRACTU must be the same as the type of the + // input vector. + ExtV = DAG.getNode(HexagonISD::EXTRACTU, dl, ScalarTy, + {VecV, WidthV, OffV}); + } + } else { + if (ty(IdxV) != MVT::i32) + IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32); + SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, + DAG.getConstant(ElemWidth, dl, MVT::i32)); + // EXTRACTURP takes width/offset in a 64-bit pair. + SDValue CombV = DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, + {WidthV, OffV}); + ExtV = DAG.getNode(HexagonISD::EXTRACTURP, dl, ScalarTy, + {VecV, CombV}); + } + + // Cast ExtV to the requested result type. + ExtV = DAG.getZExtOrTrunc(ExtV, dl, tyScalar(ResTy)); + ExtV = DAG.getBitcast(ResTy, ExtV); + return ExtV; +} + +SDValue +HexagonTargetLowering::insertVector(SDValue VecV, SDValue ValV, SDValue IdxV, + const SDLoc &dl, MVT ValTy, + SelectionDAG &DAG) const { + MVT VecTy = ty(VecV); + unsigned VecWidth = VecTy.getSizeInBits(); + unsigned ValWidth = ValTy.getSizeInBits(); + assert(VecWidth == 32 || VecWidth == 64); + assert((VecWidth % ValWidth) == 0); + + // Cast everything to scalar integer types. + MVT ScalarTy = MVT::getIntegerVT(VecWidth); + // The actual type of ValV may be different than ValTy (which is related + // to the vector type). + unsigned VW = ty(ValV).getSizeInBits(); + ValV = DAG.getBitcast(MVT::getIntegerVT(VW), ValV); + VecV = DAG.getBitcast(ScalarTy, VecV); + if (VW != VecWidth) + ValV = DAG.getAnyExtOrTrunc(ValV, dl, ScalarTy); + + SDValue WidthV = DAG.getConstant(ValWidth, dl, MVT::i32); + SDValue InsV; + + if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(IdxV)) { + unsigned W = C->getZExtValue() * ValWidth; + SDValue OffV = DAG.getConstant(W, dl, MVT::i32); + InsV = DAG.getNode(HexagonISD::INSERT, dl, ScalarTy, + {VecV, ValV, WidthV, OffV}); + } else { + if (ty(IdxV) != MVT::i32) + IdxV = DAG.getZExtOrTrunc(IdxV, dl, MVT::i32); + SDValue OffV = DAG.getNode(ISD::MUL, dl, MVT::i32, IdxV, WidthV); + // INSERTRP takes width/offset in a 64-bit pair. + SDValue CombV = DAG.getNode(HexagonISD::COMBINE, dl, MVT::i64, + {WidthV, OffV}); + InsV = DAG.getNode(HexagonISD::INSERTRP, dl, ScalarTy, + {VecV, ValV, CombV}); + } + + return DAG.getNode(ISD::BITCAST, dl, VecTy, InsV); +} + +SDValue HexagonTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { MVT VT = Op.getValueType().getSimpleVT(); unsigned BW = VT.getSizeInBits(); @@ -2701,145 +2796,38 @@ HexagonTargetLowering::LowerEXTRACT_SUBVECTOR_HVX(SDValue Op, } SDValue -HexagonTargetLowering::LowerEXTRACT_VECTOR(SDValue Op, - SelectionDAG &DAG) const { - // If we are dealing with EXTRACT_SUBVECTOR on a HVX type, we may - // be able to simplify it to an EXTRACT_SUBREG. - if (Op.getOpcode() == ISD::EXTRACT_SUBVECTOR && Subtarget.useHVXOps() && - Subtarget.isHVXVectorType(Op.getValueType().getSimpleVT())) - return LowerEXTRACT_SUBVECTOR_HVX(Op, DAG); - - EVT VT = Op.getValueType(); - int VTN = VT.isVector() ? VT.getVectorNumElements() : 1; - SDLoc dl(Op); - SDValue Idx = Op.getOperand(1); +HexagonTargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op, + SelectionDAG &DAG) const { SDValue Vec = Op.getOperand(0); - EVT VecVT = Vec.getValueType(); - EVT EltVT = VecVT.getVectorElementType(); - int EltSize = EltVT.getSizeInBits(); - SDValue Width = DAG.getConstant(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT ? - EltSize : VTN * EltSize, dl, MVT::i64); - - // Constant element number. - if (ConstantSDNode *CI = dyn_cast<ConstantSDNode>(Idx)) { - uint64_t X = CI->getZExtValue(); - SDValue Offset = DAG.getConstant(X * EltSize, dl, MVT::i32); - const SDValue Ops[] = {Vec, Width, Offset}; - - ConstantSDNode *CW = dyn_cast<ConstantSDNode>(Width); - assert(CW && "Non constant width in LowerEXTRACT_VECTOR"); - - SDValue N; - MVT SVT = VecVT.getSimpleVT(); - uint64_t W = CW->getZExtValue(); - - if (W == 1) { - MVT LocVT = MVT::getIntegerVT(SVT.getSizeInBits()); - SDValue VecCast = DAG.getNode(ISD::BITCAST, dl, LocVT, Vec); - SDValue Shifted = DAG.getNode(ISD::SRA, dl, LocVT, VecCast, Offset); - return DAG.getNode(ISD::AND, dl, LocVT, Shifted, - DAG.getConstant(1, dl, LocVT)); - } else if (W == 32) { - // Translate this node into EXTRACT_SUBREG. - unsigned Subreg = (X == 0) ? Hexagon::isub_lo : 0; - - if (X == 0) - Subreg = Hexagon::isub_lo; - else if (SVT == MVT::v2i32 && X == 1) - Subreg = Hexagon::isub_hi; - else if (SVT == MVT::v4i16 && X == 2) - Subreg = Hexagon::isub_hi; - else if (SVT == MVT::v8i8 && X == 4) - Subreg = Hexagon::isub_hi; - else - llvm_unreachable("Bad offset"); - N = DAG.getTargetExtractSubreg(Subreg, dl, MVT::i32, Vec); - - } else if (SVT.getSizeInBits() == 32) { - N = DAG.getNode(HexagonISD::EXTRACTU, dl, MVT::i32, Ops); - } else if (SVT.getSizeInBits() == 64) { - N = DAG.getNode(HexagonISD::EXTRACTU, dl, MVT::i64, Ops); - if (VT.getSizeInBits() == 32) - N = DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, N); - } else - return SDValue(); - - return DAG.getNode(ISD::BITCAST, dl, VT, N); - } - - // Variable element number. - SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i32, Idx, - DAG.getConstant(EltSize, dl, MVT::i32)); - SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width, - DAG.getConstant(32, dl, MVT::i64)); - SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset); - - const SDValue Ops[] = {Vec, Combined}; - - SDValue N; - if (VecVT.getSizeInBits() == 32) { - N = DAG.getNode(HexagonISD::EXTRACTURP, dl, MVT::i32, Ops); - } else { - N = DAG.getNode(HexagonISD::EXTRACTURP, dl, MVT::i64, Ops); - if (VT.getSizeInBits() == 32) - N = DAG.getTargetExtractSubreg(Hexagon::isub_lo, dl, MVT::i32, N); - } - return DAG.getNode(ISD::BITCAST, dl, VT, N); + MVT ElemTy = ty(Vec).getVectorElementType(); + return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ElemTy, ty(Op), DAG); } SDValue -HexagonTargetLowering::LowerINSERT_VECTOR(SDValue Op, - SelectionDAG &DAG) const { - EVT VT = Op.getValueType(); - int VTN = VT.isVector() ? VT.getVectorNumElements() : 1; - SDLoc dl(Op); +HexagonTargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op, + SelectionDAG &DAG) const { SDValue Vec = Op.getOperand(0); - SDValue Val = Op.getOperand(1); - SDValue Idx = Op.getOperand(2); - EVT VecVT = Vec.getValueType(); - EVT EltVT = VecVT.getVectorElementType(); - int EltSize = EltVT.getSizeInBits(); - SDValue Width = DAG.getConstant(Op.getOpcode() == ISD::INSERT_VECTOR_ELT ? - EltSize : VTN * EltSize, dl, MVT::i64); - - if (ConstantSDNode *C = cast<ConstantSDNode>(Idx)) { - SDValue Offset = DAG.getConstant(C->getSExtValue() * EltSize, dl, MVT::i32); - const SDValue Ops[] = {Vec, Val, Width, Offset}; - - SDValue N; - if (VT.getSizeInBits() == 32) - N = DAG.getNode(HexagonISD::INSERT, dl, MVT::i32, Ops); - else if (VT.getSizeInBits() == 64) - N = DAG.getNode(HexagonISD::INSERT, dl, MVT::i64, Ops); - else - return SDValue(); - - return DAG.getNode(ISD::BITCAST, dl, VT, N); - } - - // Variable element number. - SDValue Offset = DAG.getNode(ISD::MUL, dl, MVT::i32, Idx, - DAG.getConstant(EltSize, dl, MVT::i32)); - SDValue Shifted = DAG.getNode(ISD::SHL, dl, MVT::i64, Width, - DAG.getConstant(32, dl, MVT::i64)); - SDValue Combined = DAG.getNode(ISD::OR, dl, MVT::i64, Shifted, Offset); - - if (VT.getSizeInBits() == 64 && Val.getValueSizeInBits() == 32) { - SDValue C = DAG.getConstant(0, dl, MVT::i32); - Val = DAG.getNode(HexagonISD::COMBINE, dl, VT, C, Val); - } + MVT VecTy = ty(Vec); + if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy)) + return LowerEXTRACT_SUBVECTOR_HVX(Op, DAG); - const SDValue Ops[] = {Vec, Val, Combined}; + return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ty(Op), ty(Op), DAG); +} - SDValue N; - if (VT.getSizeInBits() == 32) - N = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i32, Ops); - else if (VT.getSizeInBits() == 64) - N = DAG.getNode(HexagonISD::INSERTRP, dl, MVT::i64, Ops); - else - return SDValue(); +SDValue +HexagonTargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, + SelectionDAG &DAG) const { + MVT VecTy = ty(Op); + return insertVector(Op.getOperand(0), Op.getOperand(1), Op.getOperand(2), + SDLoc(Op), VecTy.getVectorElementType(), DAG); +} - return DAG.getNode(ISD::BITCAST, dl, VT, N); +SDValue +HexagonTargetLowering::LowerINSERT_SUBVECTOR(SDValue Op, + SelectionDAG &DAG) const { + SDValue ValV = Op.getOperand(1); + return insertVector(Op.getOperand(0), ValV, Op.getOperand(2), + SDLoc(Op), ty(ValV), DAG); } bool @@ -2894,10 +2882,10 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { #endif llvm_unreachable("Should not custom lower this!"); case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG); - case ISD::INSERT_SUBVECTOR: return LowerINSERT_VECTOR(Op, DAG); - case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR(Op, DAG); - case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_VECTOR(Op, DAG); - case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR(Op, DAG); + case ISD::INSERT_SUBVECTOR: return LowerINSERT_SUBVECTOR(Op, DAG); + case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG); + case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG); case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG); case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG); case ISD::SRA: diff --git a/lib/Target/Hexagon/HexagonISelLowering.h b/lib/Target/Hexagon/HexagonISelLowering.h index b76fd0c1592..781e49ab2d0 100644 --- a/lib/Target/Hexagon/HexagonISelLowering.h +++ b/lib/Target/Hexagon/HexagonISelLowering.h @@ -117,13 +117,17 @@ namespace HexagonISD { SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; const char *getTargetNodeName(unsigned Opcode) const override; + + SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerEXTRACT_VECTOR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerEXTRACT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerEXTRACT_SUBVECTOR_HVX(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerINSERT_VECTOR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerINSERT_SUBVECTOR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVECTOR_SHIFT(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const; SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG) const; @@ -269,11 +273,24 @@ namespace HexagonISD { return AtomicExpansionKind::LLSC; } - protected: + private: + MVT ty(SDValue Op) const { + return Op.getValueType().getSimpleVT(); + } + MVT tyScalar(MVT Ty) const { + if (!Ty.isVector()) + return Ty; + return MVT::getIntegerVT(Ty.getSizeInBits()); + } + SDValue buildVector32(ArrayRef<SDValue> Elem, const SDLoc &dl, MVT VecTy, SelectionDAG &DAG) const; SDValue buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl, MVT VecTy, SelectionDAG &DAG) const; + SDValue extractVector(SDValue VecV, SDValue IdxV, const SDLoc &dl, + MVT ValTy, MVT ResTy, SelectionDAG &DAG) const; + SDValue insertVector(SDValue VecV, SDValue ValV, SDValue IdxV, + const SDLoc &dl, MVT ValTy, SelectionDAG &DAG) const; std::pair<const TargetRegisterClass*, uint8_t> findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) |