diff options
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp | 120 |
1 files changed, 108 insertions, 12 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp index 80718d3834..c0168f0460 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp @@ -172,7 +172,6 @@ void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, else Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, ScalarOp, DAG.getConstant(Index - LoNumElts, TLI.getPointerTy())); - } void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, @@ -253,22 +252,50 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // We know the result is a vector. The input may be either a vector or a // scalar value. + MVT::ValueType LoVT, HiVT; + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + SDOperand InOp = N->getOperand(0); - if (MVT::isVector(InOp.getValueType()) && - MVT::getVectorNumElements(InOp.getValueType()) != 1) { - // If this is a vector, split the vector and convert each of the pieces now. - GetSplitOp(InOp, Lo, Hi); - - MVT::ValueType LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); + MVT::ValueType InVT = InOp.getValueType(); + MVT::ValueType NewInVT = TLI.getTypeToTransformTo(InVT); + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + break; + case Promote: + break; + case Scalarize: + // While it is tempting to extract the scalarized operand, check whether it + // needs expansion, and if so process it in the Expand case below, there is + // no guarantee that the scalarized operand has been processed yet. If it + // hasn't then the call to GetExpandedOp will abort. So just give up. + break; + case Expand: + // A scalar to vector conversion, where the scalar needs expansion. + // Check that the vector is being split in two. + if (MVT::getSizeInBits(NewInVT) == MVT::getSizeInBits(LoVT)) { + // Convert each expanded piece of the scalar now. + GetExpandedOp(InOp, Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); + return; + } + break; + case Split: + // If the input is a vector that needs to be split, convert each split + // piece of the input now. + GetSplitOp(InOp, Lo, Hi); Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); return; } - + // Lower the bit-convert to a store/load from the stack, then split the load. - SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); SplitRes_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi); } @@ -340,8 +367,11 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N), OpNo); break; case ISD::RET: Res = SplitOp_RET(N, OpNo); break; - case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break; - case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break; + case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break; + + case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break; + case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break; + case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break; } } @@ -402,6 +432,72 @@ SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign); } +SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { + // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will + // end up being split all the way down to individual components. Convert the + // split pieces into integers and reassemble. + SDOperand Lo, Hi; + GetSplitOp(N->getOperand(0), Lo, Hi); + + unsigned LoBits = MVT::getSizeInBits(Lo.getValueType()); + Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits), Lo); + + unsigned HiBits = MVT::getSizeInBits(Hi.getValueType()); + Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits), Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + + assert(LoBits == HiBits && "Do not know how to assemble odd sized vectors!"); + + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), + DAG.getNode(ISD::BUILD_PAIR, + MVT::getIntegerType(LoBits+HiBits), Lo, Hi)); +} + +SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) { + SDOperand Vec = N->getOperand(0); + SDOperand Idx = N->getOperand(1); + MVT::ValueType VecVT = Vec.getValueType(); + + if (isa<ConstantSDNode>(Idx)) { + uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue(); + assert(IdxVal < MVT::getVectorNumElements(VecVT) && + "Invalid vector index!"); + + SDOperand Lo, Hi; + GetSplitOp(Vec, Lo, Hi); + + uint64_t LoElts = MVT::getVectorNumElements(Lo.getValueType()); + + if (IdxVal < LoElts) + return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx); + else + return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi, + DAG.getConstant(IdxVal - LoElts, + Idx.getValueType())); + } + + // Store the vector to the stack and load back the required element. + SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); + SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); + + // Add the offset to the index. + MVT::ValueType EltVT = MVT::getVectorElementType(VecVT); + unsigned EltSize = MVT::getSizeInBits(EltVT)/8; // FIXME: should be ABI size. + Idx = DAG.getNode(ISD::MUL, Idx.getValueType(), Idx, + DAG.getConstant(EltSize, Idx.getValueType())); + + if (MVT::getSizeInBits(Idx.getValueType()) > + MVT::getSizeInBits(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), Idx); + else + Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx); + + StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, StackPtr); + return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0); +} + SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) { // We know that the extracted result type is legal. For now, assume the index // is a constant. |