/// element number IDX.
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,
/// of the same type as VEC1/VEC2. SHUFFLEVEC is a VBUILD_VECTOR of
/// constant int values that indicate which value each result element will
SDOperand &Lo, SDOperand &Hi);
SDOperand LowerVEXTRACT_VECTOR_ELT(SDOperand Op);
+ SDOperand LowerVEXTRACT_SUBVECTOR(SDOperand Op);
SDOperand ExpandEXTRACT_VECTOR_ELT(SDOperand Op);
SDOperand getIntPtrConstant(uint64_t Val) {
Result = LegalizeOp(LowerVEXTRACT_VECTOR_ELT(Op));
break;
+ case ISD::VEXTRACT_SUBVECTOR:
+ Result = LegalizeOp(LowerVEXTRACT_SUBVECTOR(Op));
+ break;
+
case ISD::CALLSEQ_START: {
SDNode *CallEnd = FindCallEndFromCallStart(Node);
case ISD::VEXTRACT_VECTOR_ELT:
Result = PromoteOp(LowerVEXTRACT_VECTOR_ELT(Op));
break;
+ case ISD::VEXTRACT_SUBVECTOR:
+ Result = PromoteOp(LowerVEXTRACT_SUBVECTOR(Op));
+ break;
case ISD::EXTRACT_VECTOR_ELT:
Result = PromoteOp(ExpandEXTRACT_VECTOR_ELT(Op));
break;
}
}
+/// 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
/// memory traffic.
SDOperand SelectionDAGLegalize::ExpandEXTRACT_VECTOR_ELT(SDOperand Op) {
Hi = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &HiOps[0], HiOps.size());
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::VSUB:
case ISD::VMUL:
}
}
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:
if (!MVT::isVector(NewVT)) {
// Returning a scalar? Must be the inserted element.
Node->getOperand(1), Node->getOperand(2));
}
break;
+ case ISD::VEXTRACT_SUBVECTOR:
+ Result = PackVectorOp(Node->getOperand(0), NewVT);
+ assert(Result.getValueType() == NewVT);
+ break;
case ISD::VVECTOR_SHUFFLE:
if (!MVT::isVector(NewVT)) {
// Returning a scalar? Figure out if it is the LHS or RHS and return it.
case ISD::VINSERT_VECTOR_ELT: return "vinsert_vector_elt";
case ISD::EXTRACT_VECTOR_ELT: return "extract_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::VBUILD_VECTOR: return "vbuild_vector";
case ISD::VECTOR_SHUFFLE: return "vector_shuffle";
unsigned NE = TLI.getVectorTypeBreakdown(PTy, PTyElementVT,
PTyLegalElementVT);
- // Build a VBUILD_VECTOR with the input registers.
+ // Build a VBUILD_VECTOR or VCONCAT_VECTORS with the input registers.
SmallVector<SDOperand, 8> Ops;
if (PTyElementVT == PTyLegalElementVT) {
// If the value types are legal, just VBUILD the CopyFromReg nodes.
}
}
- Ops.push_back(DAG.getConstant(NE, MVT::i32));
- Ops.push_back(DAG.getValueType(PTyElementVT));
- N = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &Ops[0], Ops.size());
-
- // Finally, use a VBIT_CONVERT to make this available as the appropriate
- // vector type.
- N = DAG.getNode(ISD::VBIT_CONVERT, MVT::Vector, N,
- DAG.getConstant(PTy->getNumElements(),
- MVT::i32),
- DAG.getValueType(TLI.getValueType(PTy->getElementType())));
+ if (MVT::isVector(PTyElementVT)) {
+ Ops.push_back(DAG.getConstant(NE * MVT::getVectorNumElements(PTyElementVT), MVT::i32));
+ Ops.push_back(DAG.getValueType(MVT::getVectorBaseType(PTyElementVT)));
+ N = DAG.getNode(ISD::VCONCAT_VECTORS, MVT::Vector, &Ops[0], Ops.size());
+ } else {
+ Ops.push_back(DAG.getConstant(NE, MVT::i32));
+ Ops.push_back(DAG.getValueType(PTyElementVT));
+ N = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &Ops[0], Ops.size());
+ }
}
return N;
MVT::ValueType PTyElementVT, PTyLegalElementVT;
unsigned NE = TLI.getVectorTypeBreakdown(cast<VectorType>(V->getType()),
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,
- // VEXTRACT_VECTOR_ELT'ing them, converting them to PTyLegalElementVT, then
- // copying them into output registers.
+ // VEXTRACT_VECTOR_ELT'ing or VEXTRACT_SUBVECTOR'ing them, converting them
+ // to PTyLegalElementVT, then copying them into output registers.
SmallVector<SDOperand, 8> OutChains;
SDOperand Root = getRoot();
for (unsigned i = 0; i != NE; ++i) {
- SDOperand Elt = DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, PTyElementVT,
- Op, DAG.getConstant(i, TLI.getPointerTy()));
+ SDOperand Elt = MVT::isVector(PTyElementVT) ?
+ 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) {
// Elements are legal.
OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt));