diff options
author | Dan Gohman <gohman@apple.com> | 2007-06-13 15:12:02 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2007-06-13 15:12:02 +0000 |
commit | 26455c4ae0c40849a256aef404d932074479a085 (patch) | |
tree | 9ab64dc54d01a4d8a716554336e294c0c211598b /llvm/lib/CodeGen | |
parent | cbd51c8b60bf73aa17cde37950e0385bc42a28fe (diff) | |
download | bcm5719-llvm-26455c4ae0c40849a256aef404d932074479a085.tar.gz bcm5719-llvm-26455c4ae0c40849a256aef404d932074479a085.zip |
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
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 63 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 39 |
3 files changed, 83 insertions, 21 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 2823b46f880..aeb6f276c5f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/llvm/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<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) { @@ -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<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: @@ -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/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a5ecd57dc40..e3ee9fb0d8c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/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/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 390429e74f7..c870edfd686 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/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<SDOperand, 8> 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<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)); |