[x86] Teach the unpack lowering to try wider element unpacks.
[oota-llvm.git] / test / CodeGen / X86 / vector-trunc.ll
1 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mattr=+sse2 | FileCheck %s --check-prefix=SSE --check-prefix=SSE2
2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mattr=+ssse3 | FileCheck %s --check-prefix=SSE --check-prefix=SSSE3
3 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mattr=+sse4.1 | FileCheck %s --check-prefix=SSE --check-prefix=SSE41
4 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -mattr=+avx | FileCheck %s --check-prefix=AVX --check-prefix=AVX1
5
6 define <4 x i32> @trunc2x2i64(<2 x i64> %a, <2 x i64> %b) {
7 ; SSE2-LABEL: trunc2x2i64:
8 ; SSE2:       # BB#0: # %entry
9 ; SSE2-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3]
10 ; SSE2-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
11 ; SSE2-NEXT:    punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
12 ; SSE2-NEXT:    retq
13 ;
14 ; SSSE3-LABEL: trunc2x2i64:
15 ; SSSE3:       # BB#0: # %entry
16 ; SSSE3-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3]
17 ; SSSE3-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
18 ; SSSE3-NEXT:    punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
19 ; SSSE3-NEXT:    retq
20 ;
21 ; SSE41-LABEL: trunc2x2i64:
22 ; SSE41:       # BB#0: # %entry
23 ; SSE41-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,1,0,2]
24 ; SSE41-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
25 ; SSE41-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7]
26 ; SSE41-NEXT:    retq
27 ;
28 ; AVX-LABEL: trunc2x2i64:
29 ; AVX:       # BB#0: # %entry
30 ; AVX-NEXT:    vpshufd {{.*#+}} xmm1 = xmm1[0,1,0,2]
31 ; AVX-NEXT:    vpshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
32 ; AVX-NEXT:    vpblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7]
33 ; AVX-NEXT:    retq
34
35
36 entry:
37   %0 = trunc <2 x i64> %a to <2 x i32>
38   %1 = trunc <2 x i64> %b to <2 x i32>
39   %2 = shufflevector <2 x i32> %0, <2 x i32> %1, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
40   ret <4 x i32> %2
41 }
42
43 define i64 @trunc2i64(<2 x i64> %inval) {
44 ; SSE-LABEL: trunc2i64:
45 ; SSE:       # BB#0: # %entry
46 ; SSE-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
47 ; SSE-NEXT:    movd %xmm0, %rax
48 ; SSE-NEXT:    retq
49 ;
50 ; AVX-LABEL: trunc2i64:
51 ; AVX:       # BB#0: # %entry
52 ; AVX-NEXT:    vpshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
53 ; AVX-NEXT:    vmovq %xmm0, %rax
54 ; AVX-NEXT:    retq
55
56
57 entry:
58   %0 = trunc <2 x i64> %inval to <2 x i32>
59   %1 = bitcast <2 x i32> %0 to i64
60   ret i64 %1
61 }
62
63 define <8 x i16> @trunc2x4i32(<4 x i32> %a, <4 x i32> %b) {
64 ; SSE2-LABEL: trunc2x4i32:
65 ; SSE2:       # BB#0: # %entry
66 ; SSE2-NEXT:    pshuflw {{.*#+}} xmm1 = xmm1[0,2,2,3,4,5,6,7]
67 ; SSE2-NEXT:    pshufhw {{.*#+}} xmm1 = xmm1[0,1,2,3,4,6,6,7]
68 ; SSE2-NEXT:    pshufd {{.*#+}} xmm1 = xmm1[0,2,2,3]
69 ; SSE2-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
70 ; SSE2-NEXT:    pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,6,6,7]
71 ; SSE2-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
72 ; SSE2-NEXT:    punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
73 ; SSE2-NEXT:    retq
74 ;
75 ; SSSE3-LABEL: trunc2x4i32:
76 ; SSSE3:       # BB#0: # %entry
77 ; SSSE3-NEXT:    movdqa {{.*#+}} xmm2 = [0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15]
78 ; SSSE3-NEXT:    pshufb %xmm2, %xmm1
79 ; SSSE3-NEXT:    pshufb %xmm2, %xmm0
80 ; SSSE3-NEXT:    punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
81 ; SSSE3-NEXT:    retq
82 ;
83 ; SSE41-LABEL: trunc2x4i32:
84 ; SSE41:       # BB#0: # %entry
85 ; SSE41-NEXT:    pshufb {{.*#+}} xmm1 = xmm1[0,1,4,5,4,5,6,7,0,1,4,5,8,9,12,13]
86 ; SSE41-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15]
87 ; SSE41-NEXT:    pblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7]
88 ; SSE41-NEXT:    retq
89 ;
90 ; AVX-LABEL: trunc2x4i32:
91 ; AVX:       # BB#0: # %entry
92 ; AVX-NEXT:    vpshufb {{.*#+}} xmm1 = xmm1[0,1,4,5,4,5,6,7,0,1,4,5,8,9,12,13]
93 ; AVX-NEXT:    vpshufb {{.*#+}} xmm0 = xmm0[0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15]
94 ; AVX-NEXT:    vpblendw {{.*#+}} xmm0 = xmm0[0,1,2,3],xmm1[4,5,6,7]
95 ; AVX-NEXT:    retq
96
97
98
99
100 entry:
101   %0 = trunc <4 x i32> %a to <4 x i16>
102   %1 = trunc <4 x i32> %b to <4 x i16>
103   %2 = shufflevector <4 x i16> %0, <4 x i16> %1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
104   ret <8 x i16> %2
105 }
106
107 ; PR15524 http://llvm.org/bugs/show_bug.cgi?id=15524
108 define i64 @trunc4i32(<4 x i32> %inval) {
109 ; SSE2-LABEL: trunc4i32:
110 ; SSE2:       # BB#0: # %entry
111 ; SSE2-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[0,2,2,3,4,5,6,7]
112 ; SSE2-NEXT:    pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,6,6,7]
113 ; SSE2-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[0,2,2,3]
114 ; SSE2-NEXT:    movd %xmm0, %rax
115 ; SSE2-NEXT:    retq
116 ;
117 ; SSSE3-LABEL: trunc4i32:
118 ; SSSE3:       # BB#0: # %entry
119 ; SSSE3-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15]
120 ; SSSE3-NEXT:    movd %xmm0, %rax
121 ; SSSE3-NEXT:    retq
122 ;
123 ; SSE41-LABEL: trunc4i32:
124 ; SSE41:       # BB#0: # %entry
125 ; SSE41-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15]
126 ; SSE41-NEXT:    movd %xmm0, %rax
127 ; SSE41-NEXT:    retq
128 ;
129 ; AVX-LABEL: trunc4i32:
130 ; AVX:       # BB#0: # %entry
131 ; AVX-NEXT:    vpshufb {{.*#+}} xmm0 = xmm0[0,1,4,5,8,9,12,13,8,9,12,13,12,13,14,15]
132 ; AVX-NEXT:    vmovq %xmm0, %rax
133 ; AVX-NEXT:    retq
134
135
136
137
138 entry:
139   %0 = trunc <4 x i32> %inval to <4 x i16>
140   %1 = bitcast <4 x i16> %0 to i64
141   ret i64 %1
142 }
143
144 define <16 x i8> @trunc2x8i16(<8 x i16> %a, <8 x i16> %b) {
145 ; SSE2-LABEL: trunc2x8i16:
146 ; SSE2:       # BB#0: # %entry
147 ; SSE2-NEXT:    movdqa {{.*#+}} xmm2 = [255,255,255,255,255,255,255,255]
148 ; SSE2-NEXT:    pand %xmm2, %xmm1
149 ; SSE2-NEXT:    pand %xmm2, %xmm0
150 ; SSE2-NEXT:    packuswb %xmm1, %xmm0
151 ; SSE2-NEXT:    retq
152 ;
153 ; SSSE3-LABEL: trunc2x8i16:
154 ; SSSE3:       # BB#0: # %entry
155 ; SSSE3-NEXT:    pshufb {{.*#+}} xmm1 = zero,zero,zero,zero,zero,zero,zero,zero,xmm1[0,2,4,6,8,10,12,14]
156 ; SSSE3-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14],zero,zero,zero,zero,zero,zero,zero,zero
157 ; SSSE3-NEXT:    por %xmm1, %xmm0
158 ; SSSE3-NEXT:    retq
159 ;
160 ; SSE41-LABEL: trunc2x8i16:
161 ; SSE41:       # BB#0: # %entry
162 ; SSE41-NEXT:    pshufb {{.*#+}} xmm1 = zero,zero,zero,zero,zero,zero,zero,zero,xmm1[0,2,4,6,8,10,12,14]
163 ; SSE41-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14],zero,zero,zero,zero,zero,zero,zero,zero
164 ; SSE41-NEXT:    por %xmm1, %xmm0
165 ; SSE41-NEXT:    retq
166 ;
167 ; AVX-LABEL: trunc2x8i16:
168 ; AVX:       # BB#0: # %entry
169 ; AVX-NEXT:    vpshufb {{.*#+}} xmm1 = zero,zero,zero,zero,zero,zero,zero,zero,xmm1[0,2,4,6,8,10,12,14]
170 ; AVX-NEXT:    vpshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14],zero,zero,zero,zero,zero,zero,zero,zero
171 ; AVX-NEXT:    vpor %xmm1, %xmm0, %xmm0
172 ; AVX-NEXT:    retq
173
174
175
176
177 entry:
178   %0 = trunc <8 x i16> %a to <8 x i8>
179   %1 = trunc <8 x i16> %b to <8 x i8>
180   %2 = shufflevector <8 x i8> %0, <8 x i8> %1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
181   ret <16 x i8> %2
182 }
183
184 ; PR15524 http://llvm.org/bugs/show_bug.cgi?id=15524
185 define i64 @trunc8i16(<8 x i16> %inval) {
186 ; SSE2-LABEL: trunc8i16:
187 ; SSE2:       # BB#0: # %entry
188 ; SSE2-NEXT:    pand {{.*}}(%rip), %xmm0
189 ; SSE2-NEXT:    packuswb %xmm0, %xmm0
190 ; SSE2-NEXT:    movd %xmm0, %rax
191 ; SSE2-NEXT:    retq
192 ;
193 ; SSSE3-LABEL: trunc8i16:
194 ; SSSE3:       # BB#0: # %entry
195 ; SSSE3-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u]
196 ; SSSE3-NEXT:    movd %xmm0, %rax
197 ; SSSE3-NEXT:    retq
198 ;
199 ; SSE41-LABEL: trunc8i16:
200 ; SSE41:       # BB#0: # %entry
201 ; SSE41-NEXT:    pshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u]
202 ; SSE41-NEXT:    movd %xmm0, %rax
203 ; SSE41-NEXT:    retq
204 ;
205 ; AVX-LABEL: trunc8i16:
206 ; AVX:       # BB#0: # %entry
207 ; AVX-NEXT:    vpshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u]
208 ; AVX-NEXT:    vmovq %xmm0, %rax
209 ; AVX-NEXT:    retq
210
211
212
213
214 entry:
215   %0 = trunc <8 x i16> %inval to <8 x i8>
216   %1 = bitcast <8 x i8> %0 to i64
217   ret i64 %1
218 }