From 8745b52853c9b1d1370005d7cb42587ebe2a7193 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 27 Feb 2008 13:03:44 +0000 Subject: [PATCH] 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 --- lib/CodeGen/SelectionDAG/LegalizeTypes.h | 1 + .../SelectionDAG/LegalizeTypesSplit.cpp | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index d480fe707a2..863242d536b 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 bfc497b55aa..80718d38343 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 Ops(MaskLength); + for (unsigned i = 0; i < MaskLength; ++i) { + uint64_t Idx = + cast(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); +} -- 2.34.1