From: Dan Gohman Date: Wed, 13 Jun 2007 15:12:02 +0000 (+0000) Subject: Introduce new SelectionDAG node opcodes VEXTRACT_SUBVECTOR and X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6595635175764f402e7a5e53216c8d46bdce8c28;p=oota-llvm.git 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37569 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 23682c765c5..5a7d47fdc6e 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -267,6 +267,19 @@ namespace ISD { /// 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 diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 2823b46f880..aeb6f276c5f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -225,6 +225,7 @@ private: 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) { @@ -1178,6 +1179,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { 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); @@ -3561,6 +3566,9 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { 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; @@ -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(*(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(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) { @@ -5501,6 +5540,21 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo, Hi = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, &HiOps[0], HiOps.size()); break; } + case ISD::VCONCAT_VECTORS: { + unsigned NewNumSubvectors = (Node->getNumOperands() - 2) / 2; + SmallVector 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 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: @@ -5655,6 +5709,11 @@ SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op, } } 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. @@ -5665,6 +5724,10 @@ SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op, 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. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a5ecd57dc40..e3ee9fb0d8c 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2865,6 +2865,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { 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"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 390429e74f7..c870edfd686 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -761,7 +761,7 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) { 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 Ops; if (PTyElementVT == PTyLegalElementVT) { // 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)); - 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; @@ -4426,21 +4425,19 @@ SDOperand SelectionDAGLowering::CopyValueToVirtualRegister(Value *V, MVT::ValueType PTyElementVT, PTyLegalElementVT; unsigned NE = TLI.getVectorTypeBreakdown(cast(V->getType()), PTyElementVT, PTyLegalElementVT); + uint64_t SrcVL = cast(*(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 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));