diff options
author | Duncan Sands <baldrick@free.fr> | 2008-06-17 14:27:01 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2008-06-17 14:27:01 +0000 |
commit | 69b01e92a29ce6d7e435171aeea3fbc987b81586 (patch) | |
tree | 5d1ea52d6c49439229957559901114b55b955cb1 /lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp | |
parent | de9256ad2e33a203e97328e285c3909f67aad4b0 (diff) |
Split type expansion into ExpandInteger and ExpandFloat
rather than bundling them together. Rename FloatToInt
to PromoteFloat (better, if not perfect). Reorganize
files by types rather than by operations.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52408 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp | 582 |
1 files changed, 0 insertions, 582 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp deleted file mode 100644 index 74aae7f4c8..0000000000 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp +++ /dev/null @@ -1,582 +0,0 @@ -//===-- LegalizeTypesSplit.cpp - Vector Splitting for LegalizeTypes -------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements vector splitting support for LegalizeTypes. Vector -// splitting is the act of changing a computation in an invalid vector type to -// be a computation in multiple vectors of a smaller type. For example, -// implementing <128 x f32> operations in terms of two <64 x f32> operations. -// -//===----------------------------------------------------------------------===// - -#include "LegalizeTypes.h" -using namespace llvm; - -/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector -/// type that needs to be split. This handles non-power of two vectors. -static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) { - MVT NewEltVT = InVT.getVectorElementType(); - unsigned NumElements = InVT.getVectorNumElements(); - if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector. - NumElements >>= 1; - Lo = Hi = MVT::getVectorVT(NewEltVT, NumElements); - } else { // Non-power-of-two vectors. - unsigned NewNumElts_Lo = 1 << Log2_32(NumElements); - unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo; - Lo = MVT::getVectorVT(NewEltVT, NewNumElts_Lo); - Hi = MVT::getVectorVT(NewEltVT, NewNumElts_Hi); - } -} - - -//===----------------------------------------------------------------------===// -// Result Vector Splitting -//===----------------------------------------------------------------------===// - -/// SplitResult - This method is called when the specified result of the -/// specified node is found to need vector splitting. At this point, the node -/// may also have invalid operands or may have other results that need -/// legalization, we just know that (at least) one result needs vector -/// splitting. -void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n"); - SDOperand Lo, Hi; - -#if 0 - // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { - // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { - // Everything that once used N now uses P. We are guaranteed that the - // result value types of N and the result value types of P match. - ReplaceNodeWith(N, P); - return; - } - } -#endif - - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "SplitResult #" << ResNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to split the result of this operator!"); - abort(); - - case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; - case ISD::LOAD: SplitRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break; - case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break; - case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; - case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break; - case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break; - case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break; - case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break; - case ISD::CTTZ: - case ISD::CTLZ: - case ISD::CTPOP: - case ISD::FNEG: - case ISD::FABS: - case ISD::FSQRT: - case ISD::FSIN: - case ISD::FCOS: - case ISD::FP_TO_SINT: - case ISD::FP_TO_UINT: - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break; - case ISD::ADD: - case ISD::SUB: - case ISD::MUL: - case ISD::FADD: - case ISD::FSUB: - case ISD::FMUL: - case ISD::SDIV: - case ISD::UDIV: - case ISD::FDIV: - case ISD::FPOW: - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::UREM: - case ISD::SREM: - case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break; - case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break; - case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; - } - - // If Lo/Hi is null, the sub-method took care of registering results etc. - if (Lo.Val) - SetSplitOp(SDOperand(N, ResNo), Lo, Hi); -} - -void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - Lo = DAG.getNode(ISD::UNDEF, LoVT); - Hi = DAG.getNode(ISD::UNDEF, HiVT); -} - -void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD, - SDOperand &Lo, SDOperand &Hi) { - // FIXME: Add support for indexed loads. - MVT LoVT, HiVT; - GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT); - - SDOperand Ch = LD->getChain(); - SDOperand Ptr = LD->getBasePtr(); - const Value *SV = LD->getSrcValue(); - int SVOffset = LD->getSrcValueOffset(); - unsigned Alignment = LD->getAlignment(); - bool isVolatile = LD->isVolatile(); - - Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); - unsigned IncrementSize = LoVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - SVOffset += IncrementSize; - Alignment = MinAlign(Alignment, IncrementSize); - Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment); - - // Build a factor node to remember that this load is independent of the - // other one. - SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - - // Legalized the chain result - switch anything that used the old chain to - // use the new one. - ReplaceValueWith(SDOperand(LD, 1), TF); -} - -void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - Lo = N->getOperand(0); - Hi = N->getOperand(1); -} - -void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - SDOperand Vec = N->getOperand(0); - SDOperand Elt = N->getOperand(1); - SDOperand Idx = N->getOperand(2); - GetSplitOp(Vec, Lo, Hi); - - if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) { - unsigned IdxVal = CIdx->getValue(); - unsigned LoNumElts = Lo.getValueType().getVectorNumElements(); - if (IdxVal < LoNumElts) - Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, Lo.getValueType(), Lo, Elt, Idx); - else - Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, Elt, - DAG.getIntPtrConstant(IdxVal - LoNumElts)); - return; - } - - // Spill the vector to the stack. - MVT VecVT = Vec.getValueType(); - SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); - SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); - - // Store the new element. - SDOperand EltPtr = GetVectorElementPointer(StackPtr, - VecVT.getVectorElementType(), Idx); - Store = DAG.getStore(Store, Elt, EltPtr, NULL, 0); - - // Reload the vector from the stack. - SDOperand Load = DAG.getLoad(VecVT, Store, StackPtr, NULL, 0); - - // Split it. - SplitRes_LOAD(cast<LoadSDNode>(Load.Val), Lo, Hi); -} - -void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Build the low part. - SDOperand Mask = N->getOperand(2); - SmallVector<SDOperand, 16> Ops; - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - MVT EltVT = LoVT.getVectorElementType(); - unsigned LoNumElts = LoVT.getVectorNumElements(); - unsigned NumElements = Mask.getNumOperands(); - - // Insert all of the elements from the input that are needed. We use - // buildvector of extractelement here because the input vectors will have - // to be legalized, so this makes the code simpler. - for (unsigned i = 0; i != LoNumElts; ++i) { - unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue(); - SDOperand InVec = N->getOperand(0); - if (Idx >= NumElements) { - InVec = N->getOperand(1); - Idx -= NumElements; - } - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, - DAG.getIntPtrConstant(Idx))); - } - Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size()); - Ops.clear(); - - for (unsigned i = LoNumElts; i != NumElements; ++i) { - unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue(); - SDOperand InVec = N->getOperand(0); - if (Idx >= NumElements) { - InVec = N->getOperand(1); - Idx -= NumElements; - } - Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec, - DAG.getIntPtrConstant(Idx))); - } - Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size()); -} - -void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo, - SDOperand &Hi) { - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - unsigned LoNumElts = LoVT.getVectorNumElements(); - SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts); - Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size()); - - SmallVector<SDOperand, 8> HiOps(N->op_begin()+LoNumElts, N->op_end()); - Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size()); -} - -void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // FIXME: Handle non-power-of-two vectors? - unsigned NumSubvectors = N->getNumOperands() / 2; - if (NumSubvectors == 1) { - Lo = N->getOperand(0); - Hi = N->getOperand(1); - return; - } - - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors); - Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size()); - - SmallVector<SDOperand, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end()); - Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size()); -} - -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 LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - - // Handle some special cases efficiently. - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - case Legal: - case FloatToInt: - case Promote: - case Scalarize: - break; - case Expand: - // A scalar to vector conversion, where the scalar needs expansion. - // If the vector is being split in two then we can just convert the - // expanded pieces. - if (LoVT == HiVT) { - 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; - } - - // In the general case, convert the input to an integer and split it by hand. - MVT LoIntVT = MVT::getIntegerVT(LoVT.getSizeInBits()); - MVT HiIntVT = MVT::getIntegerVT(HiVT.getSizeInBits()); - if (TLI.isBigEndian()) - std::swap(LoIntVT, HiIntVT); - - SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, 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); -} - -void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - SDOperand LHSLo, LHSHi; - GetSplitOp(N->getOperand(0), LHSLo, LHSHi); - SDOperand RHSLo, RHSHi; - GetSplitOp(N->getOperand(1), RHSLo, RHSHi); - - Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo); - Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi); -} - -void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - // Get the dest types. This doesn't always match input types, e.g. int_to_fp. - MVT LoVT, HiVT; - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT); - - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = DAG.getNode(N->getOpcode(), LoVT, Lo); - Hi = DAG.getNode(N->getOpcode(), HiVT, Hi); -} - -void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - GetSplitOp(N->getOperand(0), Lo, Hi); - Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1)); - Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1)); -} - - -void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){ - SDOperand LL, LH, RL, RH; - GetSplitOp(N->getOperand(1), LL, LH); - GetSplitOp(N->getOperand(2), RL, RH); - - SDOperand Cond = N->getOperand(0); - Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL); - Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH); -} - - -//===----------------------------------------------------------------------===// -// Operand Vector Splitting -//===----------------------------------------------------------------------===// - -/// SplitOperand - This method is called when the specified operand of the -/// specified node is found to need vector splitting. At this point, all of the -/// result types of the node are known to be legal, but other operands of the -/// node may need legalization as well as the specified one. -bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { - DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res(0, 0); - -#if 0 - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); -#endif - - if (Res.Val == 0) { - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "SplitOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to split this operator's operand!"); - abort(); - case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N), OpNo); break; - case ISD::RET: Res = SplitOp_RET(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; - } - } - - // If the result is null, the sub-method took care of registering results etc. - if (!Res.Val) return false; - - // If the result is N, the sub-method updated N in place. Check to see if any - // operands are new, and if so, mark them. - if (Res.Val == N) { - // Mark N as new and remark N and its operands. This allows us to correctly - // revisit N if it needs another step of promotion and allows us to visit - // any new operands to N. - ReanalyzeNode(N); - return true; - } - - assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 && - "Invalid operand expansion"); - - ReplaceValueWith(SDOperand(N, 0), Res); - return false; -} - -SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. - assert(OpNo == 1 && "Can only split the stored value"); - - SDOperand Ch = N->getChain(); - SDOperand Ptr = N->getBasePtr(); - int SVOffset = N->getSrcValueOffset(); - unsigned Alignment = N->getAlignment(); - bool isVol = N->isVolatile(); - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(1), Lo, Hi); - - unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8; - - Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment); - - // Increment the pointer to the other half. - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - - Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVol, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); -} - -SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) { - assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far"); - // FIXME: Returns of gcc generic vectors larger than a legal vector - // type should be returned by reference! - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(1), Lo, Hi); - - SDOperand Chain = N->getOperand(0); // The chain. - SDOperand Sign = N->getOperand(2); // Signness - - 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); - Lo = BitConvertToInteger(Lo); - Hi = BitConvertToInteger(Hi); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), - JoinIntegers(Lo, Hi)); -} - -SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) { - SDOperand Vec = N->getOperand(0); - SDOperand Idx = N->getOperand(1); - MVT VecVT = Vec.getValueType(); - - if (isa<ConstantSDNode>(Idx)) { - uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue(); - assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!"); - - SDOperand Lo, Hi; - GetSplitOp(Vec, Lo, Hi); - - uint64_t LoElts = Lo.getValueType().getVectorNumElements(); - - 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. - MVT EltVT = VecVT.getVectorElementType(); - SDOperand StackPtr = DAG.CreateStackTemporary(VecVT); - SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0); - - // Load back the required element. - StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); - 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. - MVT SubVT = N->getValueType(0); - SDOperand Idx = N->getOperand(1); - SDOperand Lo, Hi; - GetSplitOp(N->getOperand(0), Lo, Hi); - - uint64_t LoElts = Lo.getValueType().getVectorNumElements(); - uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue(); - - if (IdxVal < LoElts) { - assert(IdxVal + SubVT.getVectorNumElements() <= LoElts && - "Extracted subvector crosses vector split!"); - return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Lo, Idx); - } else { - return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Hi, - DAG.getConstant(IdxVal - LoElts, Idx.getValueType())); - } -} - -SDOperand DAGTypeLegalizer::SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo) { - assert(OpNo == 2 && "Shuffle source type differs from result type?"); - SDOperand Mask = N->getOperand(2); - unsigned MaskLength = Mask.getValueType().getVectorNumElements(); - unsigned LargestMaskEntryPlusOne = 2 * MaskLength; - unsigned MinimumBitWidth = Log2_32_Ceil(LargestMaskEntryPlusOne); - - // Look for a legal vector type to place the mask values in. - // Note that there may not be *any* legal vector-of-integer - // type for which the element type is legal! - for (MVT::SimpleValueType EltVT = MVT::FIRST_INTEGER_VALUETYPE; - EltVT <= MVT::LAST_INTEGER_VALUETYPE; - // Integer values types are consecutively numbered. Exploit this. - EltVT = MVT::SimpleValueType(EltVT + 1)) { - - // Is the element type big enough to hold the values? - if (MVT(EltVT).getSizeInBits() < MinimumBitWidth) - // Nope. - continue; - - // Is the vector type legal? - MVT VecVT = MVT::getVectorVT(EltVT, MaskLength); - if (!isTypeLegal(VecVT)) - // Nope. - continue; - - // If the element type is not legal, find a larger legal type to use for - // the BUILD_VECTOR operands. This is an ugly hack, but seems to work! - // FIXME: The real solution is to change VECTOR_SHUFFLE into a variadic - // node where the shuffle mask is a list of integer operands, #2 .. #2+n. - for (MVT::SimpleValueType OpVT = EltVT; OpVT <= MVT::LAST_INTEGER_VALUETYPE; - // Integer values types are consecutively numbered. Exploit this. - OpVT = MVT::SimpleValueType(OpVT + 1)) { - if (!isTypeLegal(OpVT)) - continue; - - // Success! Rebuild the vector using the legal types. - SmallVector<SDOperand, 16> Ops(MaskLength); - for (unsigned i = 0; i < MaskLength; ++i) { - uint64_t Idx = - cast<ConstantSDNode>(Mask.getOperand(i))->getValue(); - Ops[i] = DAG.getConstant(Idx, OpVT); - } - return DAG.UpdateNodeOperands(SDOperand(N,0), - N->getOperand(0), N->getOperand(1), - DAG.getNode(ISD::BUILD_VECTOR, - VecVT, &Ops[0], Ops.size())); - } - - // Continuing is pointless - failure is certain. - break; - } - assert(false && "Failed to find an appropriate mask type!"); - return SDOperand(N, 0); -} |