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
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 40785da..55a52b6 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -5483,6 +5483,41 @@
   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;