summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/Hexagon/HexagonISelLowering.cpp258
-rw-r--r--lib/Target/Hexagon/HexagonISelLowering.h25
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)