fix the BuildVector -> unpcklps logic to not do pointless shuffles
authorChris Lattner <sabre@nondot.org>
Sat, 28 Aug 2010 17:28:30 +0000 (17:28 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 28 Aug 2010 17:28:30 +0000 (17:28 +0000)
when the top elements of a vector are undefined.  This happens all
the time for X86-64 ABI stuff because only the low 2 elements of
a 4 element vector are defined.  For example, on:

_Complex float f32(_Complex float A, _Complex float B) {
  return A+B;
}

We used to produce (with SSE2, SSE4.1+ uses insertps):

_f32:                                   ## @f32
movdqa %xmm0, %xmm2
addss %xmm1, %xmm2
pshufd $16, %xmm2, %xmm2
pshufd $1, %xmm1, %xmm1
pshufd $1, %xmm0, %xmm0
addss %xmm1, %xmm0
pshufd $16, %xmm0, %xmm1
movdqa %xmm2, %xmm0
unpcklps %xmm1, %xmm0
ret

We now produce:

_f32:                                   ## @f32
movdqa %xmm0, %xmm2
addss %xmm1, %xmm2
pshufd $1, %xmm1, %xmm1
pshufd $1, %xmm0, %xmm3
addss %xmm1, %xmm3
movaps %xmm2, %xmm0
unpcklps %xmm3, %xmm0
ret

This implements rdar://8368414

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@112378 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/sse1.ll

index 91fc26cd1e3555eeeade3ffbdd590545ff688e62..81416341658d9b386e414e04f577edd781ab43b1 100644 (file)
@@ -4304,8 +4304,18 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
     //   Step 2: unpcklps X, Y ==>    <3, 2, 1, 0>
     unsigned EltStride = NumElems >> 1;
     while (EltStride != 0) {
-      for (unsigned i = 0; i < EltStride; ++i)
+      for (unsigned i = 0; i < EltStride; ++i) {
+        // If V[i+EltStride] is undef and this is the first round of mixing,
+        // then it is safe to just drop this shuffle: V[i] is already in the
+        // right place, the one element (since it's the first round) being
+        // inserted as undef can be dropped.  This isn't safe for successive
+        // rounds because they will permute elements within both vectors.
+        if (V[i+EltStride].getOpcode() == ISD::UNDEF &&
+            EltStride == NumElems/2)
+          continue;
+        
         V[i] = getUnpackl(DAG, dl, VT, V[i], V[i + EltStride]);
+      }
       EltStride >>= 1;
     }
     return V[0];
index 6e7aad84de620684e5860ca6a0f9ea2835ab422f..73f88aec643f346185948158797ea660d72ee7c1 100644 (file)
@@ -18,3 +18,28 @@ define <8 x i16> @test2(<8 x i32> %a) nounwind {
 ;  %c = sext <4 x i16> %a to <4 x i32>             ; <<4 x i32>> [#uses=1]
 ;  ret <4 x i32> %c
 ;}
+
+; This should not emit shuffles to populate the top 2 elements of the 4-element
+; vector that this ends up returning.
+; rdar://8368414
+define <2 x float> @test4(<2 x float> %A, <2 x float> %B) nounwind {
+entry:
+  %tmp7 = extractelement <2 x float> %A, i32 0
+  %tmp5 = extractelement <2 x float> %A, i32 1
+  %tmp3 = extractelement <2 x float> %B, i32 0
+  %tmp1 = extractelement <2 x float> %B, i32 1
+  %add.r = fadd float %tmp7, %tmp3
+  %add.i = fsub float %tmp5, %tmp1
+  %tmp11 = insertelement <2 x float> undef, float %add.r, i32 0
+  %tmp9 = insertelement <2 x float> %tmp11, float %add.i, i32 1
+  ret <2 x float> %tmp9
+; CHECK: test4:
+; CHECK-NOT: shufps    $16
+; CHECK: shufps        $1, 
+; CHECK-NOT: shufps    $16
+; CHECK: shufps        $1, 
+; CHECK-NOT: shufps    $16
+; CHECK: unpcklps
+; CHECK-NOT: shufps    $16
+; CHECK: ret
+}