diff options
author | Chris Lattner <sabre@nondot.org> | 2006-03-31 02:06:56 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2006-03-31 02:06:56 +0000 |
commit | 70c2a61e0a0fb0a7e8b9bddd26bdcc92762772f0 (patch) | |
tree | 19cf8952e4cce2d50d3b54e93bd945dbd8f41347 | |
parent | a6c9de42938a26aa7edf50f4250cfd5cdca7737d (diff) |
Significantly improve handling of vectors that are live across basic blocks,
handling cases where the vector elements need promotion, expansion, and when
the vector type itself needs to be decimated.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27278 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 145 |
3 files changed, 101 insertions, 52 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 29d7a5ebf6..93b0d9b1cc 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -4497,9 +4497,6 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo, /// type for the result. SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op, MVT::ValueType NewVT) { - // FIXME: THIS IS A TEMPORARY HACK - if (Op.getValueType() == NewVT) return Op; - assert(Op.getValueType() == MVT::Vector && "Bad PackVectorOp invocation!"); SDNode *Node = Op.Val; @@ -4536,7 +4533,7 @@ SDOperand SelectionDAGLegalize::PackVectorOp(SDOperand Op, break; } case ISD::VBUILD_VECTOR: - if (!MVT::isVector(NewVT)) { + if (Node->getOperand(0).getValueType() == NewVT) { // Returning a scalar? Result = Node->getOperand(0); } else { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a2c423fbcb..dda5cfe772 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1162,8 +1162,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, break; case ISD::BIT_CONVERT: // Basic sanity checking. - assert((Operand.getValueType() == MVT::Vector || // FIXME: This is a hack. - MVT::getSizeInBits(VT) == MVT::getSizeInBits(Operand.getValueType())) + assert(MVT::getSizeInBits(VT) == MVT::getSizeInBits(Operand.getValueType()) && "Cannot BIT_CONVERT between two different types!"); if (VT == Operand.getValueType()) return Operand; // noop conversion. if (OpOpcode == ISD::BIT_CONVERT) // bitconv(bitconv(x)) -> bitconv(x) diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 0a694cce1f..0b32352c68 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -264,8 +264,16 @@ FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli, for (BasicBlock::iterator I = BB->begin(); (PN = dyn_cast<PHINode>(I)); ++I) if (!PN->use_empty()) { - unsigned NumElements = - TLI.getNumElements(TLI.getValueType(PN->getType())); + MVT::ValueType VT = TLI.getValueType(PN->getType()); + unsigned NumElements; + if (VT != MVT::Vector) + NumElements = TLI.getNumElements(VT); + else { + MVT::ValueType VT1,VT2; + NumElements = + TLI.getPackedTypeBreakdown(cast<PackedType>(PN->getType()), + VT1, VT2); + } unsigned PHIReg = ValueMap[PN]; assert(PHIReg &&"PHI node does not have an assigned virtual register!"); for (unsigned i = 0; i != NumElements; ++i) @@ -622,32 +630,61 @@ SDOperand SelectionDAGLowering::getValue(const Value *V) { unsigned InReg = VMI->second; // If this type is not legal, make it so now. - if (VT == MVT::Vector) { - // FIXME: We only handle legal vectors right now. We need a VBUILD_VECTOR - const PackedType *PTy = cast<PackedType>(VTy); - unsigned NumElements = PTy->getNumElements(); - MVT::ValueType PVT = TLI.getValueType(PTy->getElementType()); - MVT::ValueType TVT = MVT::getVectorType(PVT, NumElements); - assert(TLI.isTypeLegal(TVT) && - "FIXME: Cannot handle illegal vector types here yet!"); - VT = TVT; - } - - MVT::ValueType DestVT = TLI.getTypeToTransformTo(VT); - - N = DAG.getCopyFromReg(DAG.getEntryNode(), InReg, DestVT); - if (DestVT < VT) { - // Source must be expanded. This input value is actually coming from the - // register pair VMI->second and VMI->second+1. - N = DAG.getNode(ISD::BUILD_PAIR, VT, N, - DAG.getCopyFromReg(DAG.getEntryNode(), InReg+1, DestVT)); - } else { - if (DestVT > VT) { // Promotion case + if (VT != MVT::Vector) { + MVT::ValueType DestVT = TLI.getTypeToTransformTo(VT); + + N = DAG.getCopyFromReg(DAG.getEntryNode(), InReg, DestVT); + if (DestVT < VT) { + // Source must be expanded. This input value is actually coming from the + // register pair VMI->second and VMI->second+1. + N = DAG.getNode(ISD::BUILD_PAIR, VT, N, + DAG.getCopyFromReg(DAG.getEntryNode(), InReg+1, DestVT)); + } else if (DestVT > VT) { // Promotion case if (MVT::isFloatingPoint(VT)) N = DAG.getNode(ISD::FP_ROUND, VT, N); else N = DAG.getNode(ISD::TRUNCATE, VT, N); } + } else { + // Otherwise, if this is a vector, make it available as a generic vector + // here. + MVT::ValueType PTyElementVT, PTyLegalElementVT; + unsigned NE = TLI.getPackedTypeBreakdown(cast<PackedType>(VTy),PTyElementVT, + PTyLegalElementVT); + + // Build a VBUILD_VECTOR with the input registers. + std::vector<SDOperand> Ops; + if (PTyElementVT == PTyLegalElementVT) { + // If the value types are legal, just VBUILD the CopyFromReg nodes. + for (unsigned i = 0; i != NE; ++i) + Ops.push_back(DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, + PTyElementVT)); + } else if (PTyElementVT < PTyLegalElementVT) { + // If the register was promoted, use TRUNCATE of FP_ROUND as appropriate. + for (unsigned i = 0; i != NE; ++i) { + SDOperand Op = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, + PTyElementVT); + if (MVT::isFloatingPoint(PTyElementVT)) + Op = DAG.getNode(ISD::FP_ROUND, PTyElementVT, Op); + else + Op = DAG.getNode(ISD::TRUNCATE, PTyElementVT, Op); + Ops.push_back(Op); + } + } else { + // If the register was expanded, use BUILD_PAIR. + assert((NE & 1) == 0 && "Must expand into a multiple of 2 elements!"); + for (unsigned i = 0; i != NE/2; ++i) { + SDOperand Op0 = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, + PTyElementVT); + SDOperand Op1 = DAG.getCopyFromReg(DAG.getEntryNode(), InReg++, + PTyElementVT); + Ops.push_back(DAG.getNode(ISD::BUILD_PAIR, VT, Op0, Op1)); + } + } + + Ops.push_back(DAG.getConstant(NE, MVT::i32)); + Ops.push_back(DAG.getValueType(PTyLegalElementVT)); + N = DAG.getNode(ISD::VBUILD_VECTOR, MVT::Vector, Ops); } return N; @@ -2589,31 +2626,47 @@ CopyValueToVirtualRegister(SelectionDAGLowering &SDL, Value *V, unsigned Reg) { if (SrcVT == DestVT) { return DAG.getCopyToReg(SDL.getRoot(), Reg, Op); } else if (SrcVT == MVT::Vector) { - // FIXME: THIS DOES NOT SUPPORT PROMOTED/EXPANDED ELEMENTS! - - // Figure out the right, legal destination reg to copy into. - const PackedType *PTy = cast<PackedType>(V->getType()); - unsigned NumElts = PTy->getNumElements(); - MVT::ValueType EltTy = TLI.getValueType(PTy->getElementType()); + // Handle copies from generic vectors to registers. + MVT::ValueType PTyElementVT, PTyLegalElementVT; + unsigned NE = TLI.getPackedTypeBreakdown(cast<PackedType>(V->getType()), + PTyElementVT, PTyLegalElementVT); - unsigned NumVectorRegs = 1; - - // Divide the input until we get to a supported size. This will always - // end with a scalar if the target doesn't support vectors. - while (NumElts > 1 && !TLI.isTypeLegal(getVectorType(EltTy, NumElts))) { - NumElts >>= 1; - NumVectorRegs <<= 1; + // 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. + std::vector<SDOperand> OutChains; + SDOperand Root = SDL.getRoot(); + for (unsigned i = 0; i != NE; ++i) { + SDOperand Elt = DAG.getNode(ISD::VEXTRACT_VECTOR_ELT, PTyElementVT, + Op, DAG.getConstant(i, MVT::i32)); + if (PTyElementVT == PTyLegalElementVT) { + // Elements are legal. + OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt)); + } else if (PTyLegalElementVT > PTyElementVT) { + // Elements are promoted. + if (MVT::isFloatingPoint(PTyLegalElementVT)) + Elt = DAG.getNode(ISD::FP_EXTEND, PTyLegalElementVT, Elt); + else + Elt = DAG.getNode(ISD::ANY_EXTEND, PTyLegalElementVT, Elt); + OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Elt)); + } else { + // Elements are expanded. + // The src value is expanded into multiple registers. + SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, PTyLegalElementVT, + Elt, DAG.getConstant(0, MVT::i32)); + SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, PTyLegalElementVT, + Elt, DAG.getConstant(1, MVT::i32)); + OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Lo)); + OutChains.push_back(DAG.getCopyToReg(Root, Reg++, Hi)); + } } - - MVT::ValueType VT; - if (NumElts == 1) - VT = EltTy; - else - VT = getVectorType(EltTy, NumElts); - - // FIXME: THIS ASSUMES THAT THE INPUT VECTOR WILL BE LEGAL! - Op = DAG.getNode(ISD::BIT_CONVERT, VT, Op); - return DAG.getCopyToReg(SDL.getRoot(), Reg, Op); + return DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains); } else if (SrcVT < DestVT) { // The src value is promoted to the register. if (MVT::isFloatingPoint(SrcVT)) |