<div dir="ltr">Hi Simon,<br><br>This caused PR22678 and I've gone ahead and reverted and cc'd you on the bug. Sorry for the inconvenience!<div><br></div><div>-eric</div></div><br><div class="gmail_quote">On Sun Feb 22 2015 at 10:22:53 AM Simon Pilgrim <<a href="mailto:llvm-dev@redking.me.uk">llvm-dev@redking.me.uk</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rksimon<br>
Date: Sun Feb 22 12:17:28 2015<br>
New Revision: 230177<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=230177&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=230177&view=rev</a><br>
Log:<br>
[DagCombiner] Generalized BuildVector Vector Concatenation<br>
<br>
The CONCAT_VECTORS combiner pass can transform the concat of two BUILD_VECTOR nodes into a single BUILD_VECTOR node.<br>
<br>
This patch generalises this to support any number of BUILD_VECTOR nodes, and also permits UNDEF nodes to be included as well.<br>
<br>
This was noticed as AVX vec128 -> vec256 canonicalization sometimes creates a CONCAT_VECTOR with a real vec128 lower and an vec128 UNDEF upper.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D7816" target="_blank">http://reviews.llvm.org/D7816</a><br>
<br>
Modified:<br>
    llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp<br>
    llvm/trunk/test/CodeGen/X86/<u></u>vector-zext.ll<br>
<br>
Modified: llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=230177&r1=230176&r2=230177&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/lib/<u></u>CodeGen/SelectionDAG/<u></u>DAGCombiner.cpp?rev=230177&r1=<u></u>230176&r2=230177&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp Sun Feb 22 12:17:28 2015<br>
@@ -11430,36 +11430,51 @@ SDValue DAGCombiner::visitCONCAT_<u></u>VECTORS<br>
     }<br>
   }<br>
<br>
+  // Fold any combination of BUILD_VECTOR or UNDEF nodes into one BUILD_VECTOR.<br>
+  // We have already tested above for an UNDEF only concatenation.<br>
   // fold (concat_vectors (BUILD_VECTOR A, B, ...), (BUILD_VECTOR C, D, ...))<br>
   // -> (BUILD_VECTOR A, B, ..., C, D, ...)<br>
-  if (N->getNumOperands() == 2 &&<br>
-      N->getOperand(0).getOpcode() == ISD::BUILD_VECTOR &&<br>
-      N->getOperand(1).getOpcode() == ISD::BUILD_VECTOR) {<br>
-    EVT VT = N->getValueType(0);<br>
-    SDValue N0 = N->getOperand(0);<br>
-    SDValue N1 = N->getOperand(1);<br>
+  auto IsBuildVectorOrUndef = [](const SDValue &Op) {<br>
+    return ISD::UNDEF == Op.getOpcode() || ISD::BUILD_VECTOR == Op.getOpcode();<br>
+  };<br>
+  bool AllBuildVectorsOrUndefs =<br>
+      std::all_of(N->op_begin(), N->op_end(), IsBuildVectorOrUndef);<br>
+  if (AllBuildVectorsOrUndefs) {<br>
     SmallVector<SDValue, 8> Opnds;<br>
-    unsigned BuildVecNumElts =  N0.getNumOperands();<br>
+    EVT SVT = VT.getScalarType();<br>
<br>
-    EVT SclTy0 = N0.getOperand(0)-><u></u>getValueType(0);<br>
-    EVT SclTy1 = N1.getOperand(0)-><u></u>getValueType(0);<br>
-    if (SclTy0.isFloatingPoint()) {<br>
-      for (unsigned i = 0; i != BuildVecNumElts; ++i)<br>
-        Opnds.push_back(N0.getOperand(<u></u>i));<br>
-      for (unsigned i = 0; i != BuildVecNumElts; ++i)<br>
-        Opnds.push_back(N1.getOperand(<u></u>i));<br>
-    } else {<br>
+    EVT MinVT = SVT;<br>
+    if (!SVT.isFloatingPoint())<br>
       // If BUILD_VECTOR are from built from integer, they may have different<br>
       // operand types. Get the smaller type and truncate all operands to it.<br>
-      EVT MinTy = SclTy0.bitsLE(SclTy1) ? SclTy0 : SclTy1;<br>
-      for (unsigned i = 0; i != BuildVecNumElts; ++i)<br>
-        Opnds.push_back(DAG.getNode(<u></u>ISD::TRUNCATE, SDLoc(N), MinTy,<br>
-                        N0.getOperand(i)));<br>
-      for (unsigned i = 0; i != BuildVecNumElts; ++i)<br>
-        Opnds.push_back(DAG.getNode(<u></u>ISD::TRUNCATE, SDLoc(N), MinTy,<br>
-                        N1.getOperand(i)));<br>
+      for (const SDValue &Op : N->ops()) {<br>
+        EVT OpSVT = Op.getValueType().<u></u>getScalarType();<br>
+        MinVT = MinVT.bitsLE(OpSVT) ? MinVT : OpSVT;<br>
+      }<br>
+<br>
+    for (const SDValue &Op : N->ops()) {<br>
+      EVT OpVT = Op.getValueType();<br>
+      unsigned NumElts = OpVT.getVectorNumElements();<br>
+<br>
+      if (ISD::UNDEF == Op.getOpcode())<br>
+        for (unsigned i = 0; i != NumElts; ++i)<br>
+          Opnds.push_back(DAG.getUNDEF(<u></u>MinVT));<br>
+<br>
+      if (ISD::BUILD_VECTOR == Op.getOpcode()) {<br>
+        if (SVT.isFloatingPoint()) {<br>
+          assert(SVT == OpVT.getScalarType() && "Concat vector type mismatch");<br>
+          for (unsigned i = 0; i != NumElts; ++i)<br>
+            Opnds.push_back(Op.getOperand(<u></u>i));<br>
+        } else {<br>
+          for (unsigned i = 0; i != NumElts; ++i)<br>
+            Opnds.push_back(<br>
+                DAG.getNode(ISD::TRUNCATE, SDLoc(N), MinVT, Op.getOperand(i)));<br>
+        }<br>
+      }<br>
     }<br>
<br>
+    assert(VT.<u></u>getVectorNumElements() == Opnds.size() &&<br>
+           "Concat vector type mismatch");<br>
     return DAG.getNode(ISD::BUILD_VECTOR, SDLoc(N), VT, Opnds);<br>
   }<br>
<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/<u></u>vector-zext.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vector-zext.ll?rev=230177&r1=230176&r2=230177&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>CodeGen/X86/vector-zext.ll?<u></u>rev=230177&r1=230176&r2=<u></u>230177&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/CodeGen/X86/<u></u>vector-zext.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/<u></u>vector-zext.ll Sun Feb 22 12:17:28 2015<br>
@@ -358,22 +358,16 @@ define <8 x i32> @shuf_zext_8i16_to_8i32<br>
 ;<br>
 ; AVX1-LABEL: shuf_zext_8i16_to_8i32:<br>
 ; AVX1:       # BB#0: # %entry<br>
-; AVX1-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
-; AVX1-NEXT:    vpshuflw {{.*#+}} xmm1 = xmm1[0,0,0,0,4,5,6,7]<br>
-; AVX1-NEXT:    vpshufd {{.*#+}} xmm2 = xmm0[2,3,0,1]<br>
-; AVX1-NEXT:    vpunpcklwd {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[<u></u>1],xmm2[2],xmm1[2],xmm2[3],<u></u>xmm1[3]<br>
-; AVX1-NEXT:    vpunpcklwd {{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[<u></u>1],xmm0[2],xmm1[2],xmm0[3],<u></u>xmm1[3]<br>
-; AVX1-NEXT:    vinsertf128 $1, %xmm2, %ymm0, %ymm0<br>
+; AVX1-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
+; AVX1-NEXT:    vpunpckhwd {{.*#+}} xmm1 = xmm0[4],xmm1[4],xmm0[5],xmm1[<u></u>5],xmm0[6],xmm1[6],xmm0[7],<u></u>xmm1[7]<br>
+; AVX1-NEXT:    vpmovzxwd {{.*#+}} xmm0 = xmm0[0],zero,xmm0[1],zero,<u></u>xmm0[2],zero,xmm0[3],zero<br>
+; AVX1-NEXT:    vinsertf128 $1, %xmm1, %ymm0, %ymm0<br>
 ; AVX1-NEXT:    retq<br>
 ;<br>
 ; AVX2-LABEL: shuf_zext_8i16_to_8i32:<br>
 ; AVX2:       # BB#0: # %entry<br>
-; AVX2-NEXT:    vpxor %xmm1, %xmm1, %xmm1<br>
-; AVX2-NEXT:    vpbroadcastw %xmm1, %xmm1<br>
-; AVX2-NEXT:    vpshufd {{.*#+}} xmm2 = xmm0[2,3,0,1]<br>
-; AVX2-NEXT:    vpunpcklwd {{.*#+}} xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[<u></u>1],xmm2[2],xmm1[2],xmm2[3],<u></u>xmm1[3]<br>
-; AVX2-NEXT:    vpunpcklwd{{.*#+}} xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[<u></u>1],xmm0[2],xmm1[2],xmm0[3],<u></u>xmm1[3]<br>
-; AVX2-NEXT:    vinserti128 $1, %xmm2, %ymm0, %ymm0<br>
+; AVX2-NEXT:    # kill<br>
+; AVX2-NEXT:    vpmovzxwd {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,<u></u>xmm0[2],zero,xmm0[3],zero,<u></u>xmm0[4],zero,xmm0[5],zero,<u></u>xmm0[6],zero,xmm0[7],zero<br>
 ; AVX2-NEXT:    retq<br>
 entry:<br>
   %B = shufflevector <8 x i16> %A, <8 x i16> zeroinitializer, <16 x i32> <i32 0, i32 8, i32 1, i32 8, i32 2, i32 8, i32 3, i32 8, i32 4, i32 8, i32 5, i32 8, i32 6, i32 8, i32 7, i32 8><br>
@@ -410,22 +404,17 @@ define <4 x i64> @shuf_zext_4i32_to_4i64<br>
 ;<br>
 ; AVX1-LABEL: shuf_zext_4i32_to_4i64:<br>
 ; AVX1:       # BB#0: # %entry<br>
-; AVX1-NEXT:    vxorps %xmm1, %xmm1, %xmm1<br>
-; AVX1-NEXT:    vshufps {{.*#+}} xmm2 = xmm0[0,1],xmm1[0,0]<br>
-; AVX1-NEXT:    vshufps {{.*#+}} xmm2 = xmm2[0,2,1,3]<br>
-; AVX1-NEXT:    vblendpd {{.*#+}} xmm0 = xmm1[0],xmm0[1]<br>
-; AVX1-NEXT:    vpermilps {{.*#+}} xmm0 = xmm0[2,0,3,0]<br>
-; AVX1-NEXT:    vinsertf128 $1, %xmm0, %ymm2, %ymm0<br>
+; AVX1-NEXT:    vinsertps {{.*#+}} xmm1 = xmm0[0],zero,xmm0[1],zero<br>
+; AVX1-NEXT:    vxorpd %xmm2, %xmm2, %xmm2<br>
+; AVX1-NEXT:    vblendpd {{.*#+}} xmm0 = xmm2[0],xmm0[1]<br>
+; AVX1-NEXT:    vpermilps {{.*#+}} xmm0 = xmm0[2,0,3,0]<br>
+; AVX1-NEXT:    vinsertf128 $1, %xmm0, %ymm1, %ymm0<br>
 ; AVX1-NEXT:    retq<br>
 ;<br>
 ; AVX2-LABEL: shuf_zext_4i32_to_4i64:<br>
 ; AVX2:       # BB#0: # %entry<br>
 ; AVX2-NEXT:    # kill<br>
 ; AVX2-NEXT:    vpmovzxdq {{.*#+}} ymm0 = xmm0[0],zero,xmm0[1],zero,<u></u>xmm0[2],zero,xmm0[3],zero<br>
-; AVX2-NEXT:    xorl %eax, %eax<br>
-; AVX2-NEXT:    vmovd %eax, %xmm1<br>
-; AVX2-NEXT:    vpbroadcastd %xmm1, %ymm1<br>
-; AVX2-NEXT:    vpblendd {{.*#+}} ymm0 = ymm0[0],ymm1[1],ymm0[2],ymm1[<u></u>3],ymm0[4],ymm1[5],ymm0[6],<u></u>ymm1[7]<br>
 ; AVX2-NEXT:    retq<br>
 entry:<br>
   %B = shufflevector <4 x i32> %A, <4 x i32> zeroinitializer, <8 x i32> <i32 0, i32 4, i32 1, i32 4, i32 2, i32 4, i32 3, i32 4><br>
<br>
<br>
______________________________<u></u>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvm-commits</a><br>
</blockquote></div>