diff options
author | Duncan Sands <baldrick@free.fr> | 2008-02-27 13:03:44 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2008-02-27 13:03:44 +0000 |
commit | 8745b52853c9b1d1370005d7cb42587ebe2a7193 (patch) | |
tree | 34fed63d9a14c636f574d79d9a0e1318345de39d | |
parent | 4f069e6db1772a7e6cd8bfc360d819b56557badc (diff) | |
download | llvm-8745b52853c9b1d1370005d7cb42587ebe2a7193.tar.gz llvm-8745b52853c9b1d1370005d7cb42587ebe2a7193.tar.bz2 llvm-8745b52853c9b1d1370005d7cb42587ebe2a7193.tar.xz |
LegalizeTypes support for legalizing the mask
operand of a VECTOR_SHUFFLE. The mask is a
vector of constant integers. The code in
LegalizeDAG doesn't bother to legalize the
mask, since it's basically just storage for
a bunch of constants, however LegalizeTypes
is more picky. The problem is that there may
not exist any legal vector-of-integers type
with a legal element type, so it is impossible
to create a legal mask! Unless of course you
cheat by creating a BUILD_VECTOR where the
operands have a different type to the element
type of the vector being built... This is
pretty ugly but works - all relevant tests in
the testsuite pass, and produce the same
assembler with and without LegalizeTypes.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47670 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp | 55 |
2 files changed, 56 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index d480fe707a..863242d536 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -316,6 +316,7 @@ private: SDOperand SplitOp_EXTRACT_SUBVECTOR(SDNode *N); SDOperand SplitOp_RET(SDNode *N, unsigned OpNo); SDOperand SplitOp_STORE(StoreSDNode *N, unsigned OpNo); + SDOperand SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo); }; } // end namespace llvm. diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp index bfc497b55a..80718d3834 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp @@ -341,6 +341,7 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) { 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; } } @@ -421,3 +422,57 @@ SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) { 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 = MVT::getVectorNumElements(Mask.getValueType()); + 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::getSizeInBits(EltVT) < MinimumBitWidth) + // Nope. + continue; + + // Is the vector type legal? + MVT::ValueType VecVT = MVT::getVectorType(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! + 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); +} |