From 70c2a61e0a0fb0a7e8b9bddd26bdcc92762772f0 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 31 Mar 2006 02:06:56 +0000 Subject: [PATCH] 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 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 5 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 141 ++++++++++++------ 3 files changed, 99 insertions(+), 50 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 29d7a5ebf6a..93b0d9b1cce 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 a2c423fbcb4..dda5cfe772f 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 0a694cce1fb..0b32352c689 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(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(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(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; - } + if (VT != MVT::Vector) { + MVT::ValueType DestVT = TLI.getTypeToTransformTo(VT); - 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 + 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(VTy),PTyElementVT, + PTyLegalElementVT); + + // Build a VBUILD_VECTOR with the input registers. + std::vector 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(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(V->getType()), + PTyElementVT, PTyLegalElementVT); - unsigned 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)); - // 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; + // 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 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))