[Hexagon] Create helpers extractVector and insertVector in lowering

llvm-svn: 319351
This commit is contained in:
Krzysztof Parzyszek 2017-11-29 19:58:10 +00:00
parent cf5b4af820
commit 6a8e5f4b0f
2 changed files with 144 additions and 139 deletions

View File

@ -2579,6 +2579,101 @@ HexagonTargetLowering::buildVector64(ArrayRef<SDValue> Elem, const SDLoc &dl,
return SDValue(N, 0);
}
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();
@ -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);
MVT VecTy = ty(Vec);
if (Subtarget.useHVXOps() && Subtarget.isHVXVectorType(VecTy))
return LowerEXTRACT_SUBVECTOR_HVX(Op, DAG);
if (ConstantSDNode *C = cast<ConstantSDNode>(Idx)) {
SDValue Offset = DAG.getConstant(C->getSExtValue() * EltSize, dl, MVT::i32);
const SDValue Ops[] = {Vec, Val, Width, Offset};
return extractVector(Vec, Op.getOperand(1), SDLoc(Op), ty(Op), ty(Op), DAG);
}
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();
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);
}
// 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);
}
const SDValue Ops[] = {Vec, Val, Combined};
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();
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:

View File

@ -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)