forked from OSchip/llvm-project
Introduce new SelectionDAG node opcodes VEXTRACT_SUBVECTOR and
VCONCAT_VECTORS. Use these for CopyToReg and CopyFromReg legalizing in the case that the full register is to be split into subvectors instead of scalars. This replaces uses of VBIT_CONVERT to present values as vector-of-vector types in order to make whole subvectors accessible via BUILD_VECTOR and EXTRACT_VECTOR_ELT. This is in preparation for adding extended ValueType values, where having vector-of-vector types is undesirable. llvm-svn: 37569
This commit is contained in:
parent
cbd51c8b60
commit
26455c4ae0
|
@ -267,6 +267,19 @@ namespace ISD {
|
||||||
/// element number IDX.
|
/// element number IDX.
|
||||||
EXTRACT_VECTOR_ELT,
|
EXTRACT_VECTOR_ELT,
|
||||||
|
|
||||||
|
/// VCONCAT_VECTORS(VECTOR0, VECTOR1, ..., COUNT,TYPE) - Given a number of
|
||||||
|
/// values of MVT::Vector type with the same length and element type, this
|
||||||
|
/// produces a concatenated MVT::Vector result value, with length equal to
|
||||||
|
/// the sum of the input vectors. This can only be used before
|
||||||
|
/// legalization.
|
||||||
|
VCONCAT_VECTORS,
|
||||||
|
|
||||||
|
/// VEXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an
|
||||||
|
/// MVT::Vector value) starting with the (potentially variable)
|
||||||
|
/// element number IDX, which must be a multiple of the result vector
|
||||||
|
/// length. This can only be used before legalization.
|
||||||
|
VEXTRACT_SUBVECTOR,
|
||||||
|
|
||||||
/// VVECTOR_SHUFFLE(VEC1, VEC2, SHUFFLEVEC, COUNT,TYPE) - Returns a vector,
|
/// VVECTOR_SHUFFLE(VEC1, VEC2, SHUFFLEVEC, COUNT,TYPE) - Returns a vector,
|
||||||
/// of the same type as VEC1/VEC2. SHUFFLEVEC is a VBUILD_VECTOR of
|
/// of the same type as VEC1/VEC2. SHUFFLEVEC is a VBUILD_VECTOR of
|
||||||
/// constant int values that indicate which value each result element will
|
/// constant int values that indicate which value each result element will
|
||||||
|
|
|
@ -225,6 +225,7 @@ private:
|
||||||
SDOperand &Lo, SDOperand &Hi);
|
SDOperand &Lo, SDOperand &Hi);
|
||||||
|
|
||||||
SDOperand LowerVEXTRACT_VECTOR_ELT(SDOperand Op);
|
SDOperand LowerVEXTRACT_VECTOR_ELT(SDOperand Op);
|
||||||
|
SDOperand LowerVEXTRACT_SUBVECTOR(SDOperand Op);
|
||||||
SDOperand ExpandEXTRACT_VECTOR_ELT(SDOperand Op);
|
SDOperand ExpandEXTRACT_VECTOR_ELT(SDOperand Op);
|
||||||
|
|
||||||
SDOperand getIntPtrConstant(uint64_t Val) {
|
SDOperand getIntPtrConstant(uint64_t Val) {
|
||||||
|
@ -1178,6 +1179,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||||
Result = LegalizeOp(LowerVEXTRACT_VECTOR_ELT(Op));
|
Result = LegalizeOp(LowerVEXTRACT_VECTOR_ELT(Op));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ISD::VEXTRACT_SUBVECTOR:
|
||||||
|
Result = LegalizeOp(LowerVEXTRACT_SUBVECTOR(Op));
|
||||||
|
break;
|
||||||
|
|
||||||
case ISD::CALLSEQ_START: {
|
case ISD::CALLSEQ_START: {
|
||||||
SDNode *CallEnd = FindCallEndFromCallStart(Node);
|
SDNode *CallEnd = FindCallEndFromCallStart(Node);
|
||||||
|
|
||||||
|
@ -3561,6 +3566,9 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
|
||||||
case ISD::VEXTRACT_VECTOR_ELT:
|
case ISD::VEXTRACT_VECTOR_ELT:
|
||||||
Result = PromoteOp(LowerVEXTRACT_VECTOR_ELT(Op));
|
Result = PromoteOp(LowerVEXTRACT_VECTOR_ELT(Op));
|
||||||
break;
|
break;
|
||||||
|
case ISD::VEXTRACT_SUBVECTOR:
|
||||||
|
Result = PromoteOp(LowerVEXTRACT_SUBVECTOR(Op));
|
||||||
|
break;
|
||||||
case ISD::EXTRACT_VECTOR_ELT:
|
case ISD::EXTRACT_VECTOR_ELT:
|
||||||
Result = PromoteOp(ExpandEXTRACT_VECTOR_ELT(Op));
|
Result = PromoteOp(ExpandEXTRACT_VECTOR_ELT(Op));
|
||||||
break;
|
break;
|
||||||
|
@ -3622,6 +3630,37 @@ SDOperand SelectionDAGLegalize::LowerVEXTRACT_VECTOR_ELT(SDOperand Op) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// LowerVEXTRACT_SUBVECTOR - Lower a VEXTRACT_SUBVECTOR operation. For now
|
||||||
|
/// we assume the operation can be split if it is not already legal.
|
||||||
|
SDOperand SelectionDAGLegalize::LowerVEXTRACT_SUBVECTOR(SDOperand Op) {
|
||||||
|
// We know that operand #0 is the Vec vector. For now we assume the index
|
||||||
|
// is a constant and that the extracted result is a supported hardware type.
|
||||||
|
SDOperand Vec = Op.getOperand(0);
|
||||||
|
SDOperand Idx = LegalizeOp(Op.getOperand(1));
|
||||||
|
|
||||||
|
SDNode *InVal = Vec.Val;
|
||||||
|
unsigned NumElems = cast<ConstantSDNode>(*(InVal->op_end()-2))->getValue();
|
||||||
|
|
||||||
|
if (NumElems == MVT::getVectorNumElements(Op.getValueType())) {
|
||||||
|
// This must be an access of the desired vector length. Return it.
|
||||||
|
return PackVectorOp(Vec, Op.getValueType());
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstantSDNode *CIdx = cast<ConstantSDNode>(Idx);
|
||||||
|
SDOperand Lo, Hi;
|
||||||
|
SplitVectorOp(Vec, Lo, Hi);
|
||||||
|
if (CIdx->getValue() < NumElems/2) {
|
||||||
|
Vec = Lo;
|
||||||
|
} else {
|
||||||
|
Vec = Hi;
|
||||||
|
Idx = DAG.getConstant(CIdx->getValue() - NumElems/2, Idx.getValueType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's now an extract from the appropriate high or low part. Recurse.
|
||||||
|
Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
|
||||||
|
return LowerVEXTRACT_SUBVECTOR(Op);
|
||||||
|
}
|
||||||
|
|
||||||
/// ExpandEXTRACT_VECTOR_ELT - Expand an EXTRACT_VECTOR_ELT operation into
|
/// ExpandEXTRACT_VECTOR_ELT - Expand an EXTRACT_VECTOR_ELT operation into
|
||||||
/// memory traffic.
|
/// memory traffic.
|
||||||
SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
|
SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
|
||||||
|
@ -5501,6 +5540,21 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
|
||||||
Hi = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &HiOps[0], HiOps.size());
|
Hi = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &HiOps[0], HiOps.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ISD::VCONCAT_VECTORS: {
|
||||||
|
unsigned NewNumSubvectors = (Node->getNumOperands() - 2) / 2;
|
||||||
|
SmallVector<SDOperand, 8> LoOps(Node->op_begin(),
|
||||||
|
Node->op_begin()+NewNumSubvectors);
|
||||||
|
LoOps.push_back(NewNumEltsNode);
|
||||||
|
LoOps.push_back(TypeNode);
|
||||||
|
Lo = DAG.getNode(ISD::VCONCAT_VECTORS, MVT::Vector, &LoOps[0], LoOps.size());
|
||||||
|
|
||||||
|
SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumSubvectors,
|
||||||
|
Node->op_end()-2);
|
||||||
|
HiOps.push_back(NewNumEltsNode);
|
||||||
|
HiOps.push_back(TypeNode);
|
||||||
|
Hi = DAG.getNode(ISD::VCONCAT_VECTORS, MVT::Vector, &HiOps[0], HiOps.size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ISD::VADD:
|
case ISD::VADD:
|
||||||
case ISD::VSUB:
|
case ISD::VSUB:
|
||||||
case ISD::VMUL:
|
case ISD::VMUL:
|
||||||
|
@ -5655,6 +5709,11 @@ SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ISD::VCONCAT_VECTORS:
|
||||||
|
assert(Node->getOperand(0).getValueType() == NewVT &&
|
||||||
|
"Concat of non-legal vectors not yet supported!");
|
||||||
|
Result = Node->getOperand(0);
|
||||||
|
break;
|
||||||
case ISD::VINSERT_VECTOR_ELT:
|
case ISD::VINSERT_VECTOR_ELT:
|
||||||
if (!MVT::isVector(NewVT)) {
|
if (!MVT::isVector(NewVT)) {
|
||||||
// Returning a scalar? Must be the inserted element.
|
// Returning a scalar? Must be the inserted element.
|
||||||
|
@ -5665,6 +5724,10 @@ SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op,
|
||||||
Node->getOperand(1), Node->getOperand(2));
|
Node->getOperand(1), Node->getOperand(2));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ISD::VEXTRACT_SUBVECTOR:
|
||||||
|
Result = PackVectorOp(Node->getOperand(0), NewVT);
|
||||||
|
assert(Result.getValueType() == NewVT);
|
||||||
|
break;
|
||||||
case ISD::VVECTOR_SHUFFLE:
|
case ISD::VVECTOR_SHUFFLE:
|
||||||
if (!MVT::isVector(NewVT)) {
|
if (!MVT::isVector(NewVT)) {
|
||||||
// Returning a scalar? Figure out if it is the LHS or RHS and return it.
|
// Returning a scalar? Figure out if it is the LHS or RHS and return it.
|
||||||
|
|
|
@ -2865,6 +2865,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||||
case ISD::VINSERT_VECTOR_ELT: return "vinsert_vector_elt";
|
case ISD::VINSERT_VECTOR_ELT: return "vinsert_vector_elt";
|
||||||
case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt";
|
case ISD::EXTRACT_VECTOR_ELT: return "extract_vector_elt";
|
||||||
case ISD::VEXTRACT_VECTOR_ELT: return "vextract_vector_elt";
|
case ISD::VEXTRACT_VECTOR_ELT: return "vextract_vector_elt";
|
||||||
|
case ISD::VCONCAT_VECTORS: return "vconcat_vectors";
|
||||||
|
case ISD::VEXTRACT_SUBVECTOR: return "vextract_subvector";
|
||||||
case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector";
|
case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector";
|
||||||
case ISD::VBUILD_VECTOR: return "vbuild_vector";
|
case ISD::VBUILD_VECTOR: return "vbuild_vector";
|
||||||
case ISD::VECTOR_SHUFFLE: return "vector_shuffle";
|
case ISD::VECTOR_SHUFFLE: return "vector_shuffle";
|
||||||
|
|
|
@ -761,7 +761,7 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) {
|
||||||
unsigned NE = TLI.getVectorTypeBreakdown(PTy, PTyElementVT,
|
unsigned NE = TLI.getVectorTypeBreakdown(PTy, PTyElementVT,
|
||||||
PTyLegalElementVT);
|
PTyLegalElementVT);
|
||||||
|
|
||||||
// Build a VBUILD_VECTOR with the input registers.
|
// Build a VBUILD_VECTOR or VCONCAT_VECTORS with the input registers.
|
||||||
SmallVector<SDOperand, 8> Ops;
|
SmallVector<SDOperand, 8> Ops;
|
||||||
if (PTyElementVT == PTyLegalElementVT) {
|
if (PTyElementVT == PTyLegalElementVT) {
|
||||||
// If the value types are legal, just VBUILD the CopyFromReg nodes.
|
// If the value types are legal, just VBUILD the CopyFromReg nodes.
|
||||||
|
@ -791,16 +791,15 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ops.push_back(DAG.getConstant(NE, MVT::i32));
|
if (MVT::isVector(PTyElementVT)) {
|
||||||
Ops.push_back(DAG.getValueType(PTyElementVT));
|
Ops.push_back(DAG.getConstant(NE * MVT::getVectorNumElements(PTyElementVT), MVT::i32));
|
||||||
N = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &Ops[0], Ops.size());
|
Ops.push_back(DAG.getValueType(MVT::getVectorBaseType(PTyElementVT)));
|
||||||
|
N = DAG.getNode(ISD::VCONCAT_VECTORS, MVT::Vector, &Ops[0], Ops.size());
|
||||||
// Finally, use a VBIT_CONVERT to make this available as the appropriate
|
} else {
|
||||||
// vector type.
|
Ops.push_back(DAG.getConstant(NE, MVT::i32));
|
||||||
N = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, N,
|
Ops.push_back(DAG.getValueType(PTyElementVT));
|
||||||
DAG.getConstant(PTy->getNumElements(),
|
N = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &Ops[0], Ops.size());
|
||||||
MVT::i32),
|
}
|
||||||
DAG.getValueType(TLI.getValueType(PTy->getElementType())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return N;
|
return N;
|
||||||
|
@ -4426,21 +4425,19 @@ SDOperand SelectionDAGLowering::CopyValueToVirtualRegister(Value *V,
|
||||||
MVT::ValueType PTyElementVT, PTyLegalElementVT;
|
MVT::ValueType PTyElementVT, PTyLegalElementVT;
|
||||||
unsigned NE = TLI.getVectorTypeBreakdown(cast<VectorType>(V->getType()),
|
unsigned NE = TLI.getVectorTypeBreakdown(cast<VectorType>(V->getType()),
|
||||||
PTyElementVT, PTyLegalElementVT);
|
PTyElementVT, PTyLegalElementVT);
|
||||||
|
uint64_t SrcVL = cast<ConstantSDNode>(*(Op.Val->op_end()-2))->getValue();
|
||||||
|
|
||||||
// Insert a VBIT_CONVERT of the input vector to a "N x PTyElementVT"
|
|
||||||
// MVT::Vector type.
|
|
||||||
Op = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, Op,
|
|
||||||
DAG.getConstant(NE, MVT::i32),
|
|
||||||
DAG.getValueType(PTyElementVT));
|
|
||||||
|
|
||||||
// Loop over all of the elements of the resultant vector,
|
// Loop over all of the elements of the resultant vector,
|
||||||
// VEXTRACT_VECTOR_ELT'ing them, converting them to PTyLegalElementVT, then
|
// VEXTRACT_VECTOR_ELT'ing or VEXTRACT_SUBVECTOR'ing them, converting them
|
||||||
// copying them into output registers.
|
// to PTyLegalElementVT, then copying them into output registers.
|
||||||
SmallVector<SDOperand, 8> OutChains;
|
SmallVector<SDOperand, 8> OutChains;
|
||||||
SDOperand Root = getRoot();
|
SDOperand Root = getRoot();
|
||||||
for (unsigned i = 0; i != NE; ++i) {
|
for (unsigned i = 0; i != NE; ++i) {
|
||||||
SDOperand Elt = DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, PTyElementVT,
|
SDOperand Elt = MVT::isVector(PTyElementVT) ?
|
||||||
Op, DAG.getConstant(i, TLI.getPointerTy()));
|
DAG.getNode(ISD::VEXTRACT_SUBVECTOR, PTyElementVT,
|
||||||
|
Op, DAG.getConstant(i * (SrcVL / NE), TLI.getPointerTy())) :
|
||||||
|
DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, PTyElementVT,
|
||||||
|
Op, DAG.getConstant(i, TLI.getPointerTy()));
|
||||||
if (PTyElementVT == PTyLegalElementVT) {
|
if (PTyElementVT == PTyLegalElementVT) {
|
||||||
// Elements are legal.
|
// Elements are legal.
|
||||||
OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt));
|
OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt));
|
||||||
|
|
Loading…
Reference in New Issue