aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff options
context:
space:
mode:
authorBob Wilson <bob.wilson@apple.com>2009-04-13 22:05:19 +0000
committerBob Wilson <bob.wilson@apple.com>2009-04-13 22:05:19 +0000
commitb1303d05a89972195de023fda432cc621375a27c (patch)
tree83ded3f76bc8714c5a7be5b15d6abbd0fa45abcd /lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
parent88c7af096b09ad26cbcebfdf40151e04094b7460 (diff)
Change SelectionDAG type legalization to allow BUILD_VECTOR operands to be
promoted to legal types without changing the type of the vector. This is following a suggestion from Duncan (http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-February/019923.html). The transformation that used to be done during type legalization is now postponed to DAG legalization. This allows the BUILD_VECTORs to be optimized and potentially handled specially by target-specific code. It turns out that this is also consistent with an optimization done by the DAG combiner: a BUILD_VECTOR and INSERT_VECTOR_ELT may be combined by replacing one of the BUILD_VECTOR operands with the newly inserted element; but INSERT_VECTOR_ELT allows its scalar operand to be larger than the element type, with any extra high bits being implicitly truncated. The result is a BUILD_VECTOR where one of the operands has a type larger the the vector element type. Any code that operates on BUILD_VECTORs may now need to be aware of the potential type discrepancy between the vector element type and the BUILD_VECTOR operands. This patch updates all of the places that I could find to handle that case. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@68996 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeDAG.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 40785da8cf..55a52b600a 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -5483,6 +5483,41 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
MVT OpVT = SplatValue.getValueType();
MVT EltVT = VT.getVectorElementType();
+ // Check if the BUILD_VECTOR operands were promoted to legalize their types.
+ if (OpVT != EltVT) {
+ // Now that the DAG combiner and target-specific lowering have had a
+ // chance to optimize/recognize the BUILD_VECTOR with promoted operands,
+ // transform it so the operand types match the vector. Build a vector of
+ // half the length out of elements of twice the bitwidth.
+ // For example <4 x i16> -> <2 x i32>.
+ MVT NewVT = MVT::getIntegerVT(2 * EltVT.getSizeInBits());
+ assert(OpVT.isSimple() && NewVT.isSimple());
+ SmallVector<SDValue, 16> NewElts;
+
+ for (unsigned i = 0; i < NumElems; i += 2) {
+ // Combine two successive elements into one promoted element.
+ SDValue Lo = Node->getOperand(i);
+ SDValue Hi = Node->getOperand(i+1);
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Lo = DAG.getZeroExtendInReg(Lo, dl, EltVT);
+ Hi = DAG.getNode(ISD::SHL, dl, OpVT, Hi,
+ DAG.getConstant(EltVT.getSizeInBits(),
+ TLI.getPointerTy()));
+ NewElts.push_back(DAG.getNode(ISD::OR, dl, OpVT, Lo, Hi));
+ }
+
+ SDValue NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl,
+ MVT::getVectorVT(NewVT, NewElts.size()),
+ &NewElts[0], NewElts.size());
+
+ // Recurse
+ NewVec = ExpandBUILD_VECTOR(NewVec.getNode());
+
+ // Convert the new vector to the old vector type.
+ return DAG.getNode(ISD::BIT_CONVERT, dl, VT, NewVec);
+ }
+
// If the only non-undef value is the low element, turn this into a
// SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X.
bool isOnlyLowElement = true;