summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2008-02-27 13:03:44 +0000
committerDuncan Sands <baldrick@free.fr>2008-02-27 13:03:44 +0000
commit8745b52853c9b1d1370005d7cb42587ebe2a7193 (patch)
tree34fed63d9a14c636f574d79d9a0e1318345de39d
parent4f069e6db1772a7e6cd8bfc360d819b56557badc (diff)
downloadllvm-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.h1
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp55
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);
+}