9bfea88462d31a31fe19f7b3e037ab2760ee3398
[oota-llvm.git] / test / CodeGen / X86 / sse3.ll
1 ; These are tests for SSE3 codegen.
2
3 ; RUN: llc < %s -march=x86-64 -mcpu=nocona -mtriple=i686-apple-darwin9 -O3 | FileCheck %s --check-prefix=X64
4
5 ; Test for v8xi16 lowering where we extract the first element of the vector and
6 ; placed it in the second element of the result.
7
8 define void @t0(<8 x i16>* %dest, <8 x i16>* %old) nounwind {
9 ; X64-LABEL: t0:
10 ; X64:       ## BB#0: ## %entry
11 ; X64-NEXT:    movdqa (%rsi), %xmm0
12 ; X64-NEXT:    pslldq $2, %xmm0
13 ; X64-NEXT:    movdqa %xmm0, (%rdi)
14 ; X64-NEXT:    retq
15 entry:
16         %tmp3 = load <8 x i16>* %old
17         %tmp6 = shufflevector <8 x i16> %tmp3,
18                 <8 x i16> < i16 0, i16 undef, i16 undef, i16 undef, i16 undef, i16 undef, i16 undef, i16 undef >,
19                 <8 x i32> < i32 8, i32 0, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef  >
20         store <8 x i16> %tmp6, <8 x i16>* %dest
21         ret void
22
23 }
24
25 define <8 x i16> @t1(<8 x i16>* %A, <8 x i16>* %B) nounwind {
26 ; X64-LABEL: t1:
27 ; X64:       ## BB#0:
28 ; X64-NEXT:    movdqa (%rdi), %xmm0
29 ; X64-NEXT:    pinsrw $0, (%rsi), %xmm0
30 ; X64-NEXT:    retq
31         %tmp1 = load <8 x i16>* %A
32         %tmp2 = load <8 x i16>* %B
33         %tmp3 = shufflevector <8 x i16> %tmp1, <8 x i16> %tmp2, <8 x i32> < i32 8, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 >
34         ret <8 x i16> %tmp3
35
36 }
37
38 define <8 x i16> @t2(<8 x i16> %A, <8 x i16> %B) nounwind {
39 ; X64-LABEL: t2:
40 ; X64:       ## BB#0:
41 ; X64-NEXT:    pextrw $1, %xmm1, %eax
42 ; X64-NEXT:    pinsrw $0, %eax, %xmm0
43 ; X64-NEXT:    pinsrw $3, %eax, %xmm0
44 ; X64-NEXT:    retq
45         %tmp = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 9, i32 1, i32 2, i32 9, i32 4, i32 5, i32 6, i32 7 >
46         ret <8 x i16> %tmp
47 }
48
49 define <8 x i16> @t3(<8 x i16> %A, <8 x i16> %B) nounwind {
50 ; X64-LABEL: t3:
51 ; X64:       ## BB#0:
52 ; X64-NEXT:    pextrw $5, %xmm0, %eax
53 ; X64-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[0,3,2,0,4,5,6,7]
54 ; X64-NEXT:    pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,6,5,4]
55 ; X64-NEXT:    pinsrw $3, %eax, %xmm0
56 ; X64-NEXT:    retq
57         %tmp = shufflevector <8 x i16> %A, <8 x i16> %A, <8 x i32> < i32 8, i32 3, i32 2, i32 13, i32 7, i32 6, i32 5, i32 4 >
58         ret <8 x i16> %tmp
59 }
60
61 define <8 x i16> @t4(<8 x i16> %A, <8 x i16> %B) nounwind {
62 ; X64-LABEL: t4:
63 ; X64:       ## BB#0:
64 ; X64-NEXT:    pextrw $7, %xmm0, %eax
65 ; X64-NEXT:    pshufhw {{.*#+}} xmm1 = xmm0[0,1,2,3,4,5,6,5]
66 ; X64-NEXT:    pinsrw $1, %eax, %xmm1
67 ; X64-NEXT:    pextrw $1, %xmm0, %eax
68 ; X64-NEXT:    pinsrw $4, %eax, %xmm1
69 ; X64-NEXT:    movdqa %xmm1, %xmm0
70 ; X64-NEXT:    retq
71         %tmp = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 0, i32 7, i32 2, i32 3, i32 1, i32 5, i32 6, i32 5 >
72         ret <8 x i16> %tmp
73 }
74
75 define <8 x i16> @t5(<8 x i16> %A, <8 x i16> %B) nounwind {
76 ; X64-LABEL: t5:
77 ; X64:       ## BB#0:
78 ; X64-NEXT:    movlhps {{.*#+}} xmm0 = xmm0[0],xmm1[0]
79 ; X64-NEXT:    pshufd {{.*#+}} xmm0 = xmm0[2,0,3,1]
80 ; X64-NEXT:    retq
81         %tmp = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 8, i32 9, i32 0, i32 1, i32 10, i32 11, i32 2, i32 3 >
82         ret <8 x i16> %tmp
83 }
84
85 define <8 x i16> @t6(<8 x i16> %A, <8 x i16> %B) nounwind {
86 ; X64-LABEL: t6:
87 ; X64:       ## BB#0:
88 ; X64-NEXT:    movss %xmm1, %xmm0
89 ; X64-NEXT:    retq
90         %tmp = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 8, i32 9, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 >
91         ret <8 x i16> %tmp
92 }
93
94 define <8 x i16> @t7(<8 x i16> %A, <8 x i16> %B) nounwind {
95 ; X64-LABEL: t7:
96 ; X64:       ## BB#0:
97 ; X64-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[0,0,3,2,4,5,6,7]
98 ; X64-NEXT:    pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,4,6,4,7]
99 ; X64-NEXT:    retq
100         %tmp = shufflevector <8 x i16> %A, <8 x i16> %B, <8 x i32> < i32 0, i32 0, i32 3, i32 2, i32 4, i32 6, i32 4, i32 7 >
101         ret <8 x i16> %tmp
102 }
103
104 define void @t8(<2 x i64>* %res, <2 x i64>* %A) nounwind {
105 ; X64-LABEL: t8:
106 ; X64:       ## BB#0:
107 ; X64-NEXT:    pshuflw {{.*#+}} xmm0 = mem[2,1,0,3,4,5,6,7]
108 ; X64-NEXT:    pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,6,5,4,7]
109 ; X64-NEXT:    movdqa %xmm0, (%rdi)
110 ; X64-NEXT:    retq
111         %tmp = load <2 x i64>* %A
112         %tmp.upgrd.1 = bitcast <2 x i64> %tmp to <8 x i16>
113         %tmp0 = extractelement <8 x i16> %tmp.upgrd.1, i32 0
114         %tmp1 = extractelement <8 x i16> %tmp.upgrd.1, i32 1
115         %tmp2 = extractelement <8 x i16> %tmp.upgrd.1, i32 2
116         %tmp3 = extractelement <8 x i16> %tmp.upgrd.1, i32 3
117         %tmp4 = extractelement <8 x i16> %tmp.upgrd.1, i32 4
118         %tmp5 = extractelement <8 x i16> %tmp.upgrd.1, i32 5
119         %tmp6 = extractelement <8 x i16> %tmp.upgrd.1, i32 6
120         %tmp7 = extractelement <8 x i16> %tmp.upgrd.1, i32 7
121         %tmp8 = insertelement <8 x i16> undef, i16 %tmp2, i32 0
122         %tmp9 = insertelement <8 x i16> %tmp8, i16 %tmp1, i32 1
123         %tmp10 = insertelement <8 x i16> %tmp9, i16 %tmp0, i32 2
124         %tmp11 = insertelement <8 x i16> %tmp10, i16 %tmp3, i32 3
125         %tmp12 = insertelement <8 x i16> %tmp11, i16 %tmp6, i32 4
126         %tmp13 = insertelement <8 x i16> %tmp12, i16 %tmp5, i32 5
127         %tmp14 = insertelement <8 x i16> %tmp13, i16 %tmp4, i32 6
128         %tmp15 = insertelement <8 x i16> %tmp14, i16 %tmp7, i32 7
129         %tmp15.upgrd.2 = bitcast <8 x i16> %tmp15 to <2 x i64>
130         store <2 x i64> %tmp15.upgrd.2, <2 x i64>* %res
131         ret void
132 }
133
134 define void @t9(<4 x float>* %r, <2 x i32>* %A) nounwind {
135 ; X64-LABEL: t9:
136 ; X64:       ## BB#0:
137 ; X64-NEXT:    movaps (%rdi), %xmm0
138 ; X64-NEXT:    movhps (%rsi), %xmm0
139 ; X64-NEXT:    movaps %xmm0, (%rdi)
140 ; X64-NEXT:    retq
141         %tmp = load <4 x float>* %r
142         %tmp.upgrd.3 = bitcast <2 x i32>* %A to double*
143         %tmp.upgrd.4 = load double* %tmp.upgrd.3
144         %tmp.upgrd.5 = insertelement <2 x double> undef, double %tmp.upgrd.4, i32 0
145         %tmp5 = insertelement <2 x double> %tmp.upgrd.5, double undef, i32 1
146         %tmp6 = bitcast <2 x double> %tmp5 to <4 x float>
147         %tmp.upgrd.6 = extractelement <4 x float> %tmp, i32 0
148         %tmp7 = extractelement <4 x float> %tmp, i32 1
149         %tmp8 = extractelement <4 x float> %tmp6, i32 0
150         %tmp9 = extractelement <4 x float> %tmp6, i32 1
151         %tmp10 = insertelement <4 x float> undef, float %tmp.upgrd.6, i32 0
152         %tmp11 = insertelement <4 x float> %tmp10, float %tmp7, i32 1
153         %tmp12 = insertelement <4 x float> %tmp11, float %tmp8, i32 2
154         %tmp13 = insertelement <4 x float> %tmp12, float %tmp9, i32 3
155         store <4 x float> %tmp13, <4 x float>* %r
156         ret void
157 }
158
159
160
161 ; FIXME: This testcase produces icky code. It can be made much better!
162 ; PR2585
163
164 @g1 = external constant <4 x i32>
165 @g2 = external constant <4 x i16>
166
167 define void @t10() nounwind {
168 ; X64-LABEL: t10:
169 ; X64:       ## BB#0:
170 ; X64-NEXT:    movq _g1@{{.*}}(%rip), %rax
171 ; X64-NEXT:    movdqa (%rax), %xmm0
172 ; X64-NEXT:    pextrw $4, %xmm0, %eax
173 ; X64-NEXT:    pextrw $6, %xmm0, %ecx
174 ; X64-NEXT:    movlhps {{.*#+}} xmm0 = xmm0[0,0]
175 ; X64-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[0,2,0,0,4,5,6,7]
176 ; X64-NEXT:    pinsrw $2, %eax, %xmm0
177 ; X64-NEXT:    pinsrw $3, %ecx, %xmm0
178 ; X64-NEXT:    movq _g2@{{.*}}(%rip), %rax
179 ; X64-NEXT:    movq %xmm0, (%rax)
180 ; X64-NEXT:    retq
181   load <4 x i32>* @g1, align 16
182   bitcast <4 x i32> %1 to <8 x i16>
183   shufflevector <8 x i16> %2, <8 x i16> undef, <8 x i32> < i32 0, i32 2, i32 4, i32 6, i32 undef, i32 undef, i32 undef, i32 undef >
184   bitcast <8 x i16> %3 to <2 x i64>
185   extractelement <2 x i64> %4, i32 0
186   bitcast i64 %5 to <4 x i16>
187   store <4 x i16> %6, <4 x i16>* @g2, align 8
188   ret void
189 }
190
191 ; Pack various elements via shuffles.
192 define <8 x i16> @t11(<8 x i16> %T0, <8 x i16> %T1) nounwind readnone {
193 ; X64-LABEL: t11:
194 ; X64:       ## BB#0: ## %entry
195 ; X64-NEXT:    movd %xmm1, %eax
196 ; X64-NEXT:    movlhps {{.*#+}} xmm0 = xmm0[0,0]
197 ; X64-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[1,0,0,0,4,5,6,7]
198 ; X64-NEXT:    pinsrw $1, %eax, %xmm0
199 ; X64-NEXT:    retq
200 entry:
201         %tmp7 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 1, i32 8, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef , i32 undef >
202         ret <8 x i16> %tmp7
203
204 }
205
206 define <8 x i16> @t12(<8 x i16> %T0, <8 x i16> %T1) nounwind readnone {
207 ; X64-LABEL: t12:
208 ; X64:       ## BB#0: ## %entry
209 ; X64-NEXT:    pextrw $3, %xmm1, %eax
210 ; X64-NEXT:    movlhps {{.*#+}} xmm0 = xmm0[0,0]
211 ; X64-NEXT:    pshufhw {{.*#+}} xmm0 = xmm0[0,1,2,3,7,4,4,4]
212 ; X64-NEXT:    pinsrw $5, %eax, %xmm0
213 ; X64-NEXT:    retq
214 entry:
215         %tmp9 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 0, i32 1, i32 undef, i32 undef, i32 3, i32 11, i32 undef , i32 undef >
216         ret <8 x i16> %tmp9
217
218 }
219
220 define <8 x i16> @t13(<8 x i16> %T0, <8 x i16> %T1) nounwind readnone {
221 ; X64-LABEL: t13:
222 ; X64:       ## BB#0: ## %entry
223 ; X64-NEXT:    punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
224 ; X64-NEXT:    pextrw $3, %xmm1, %eax
225 ; X64-NEXT:    pshufhw {{.*#+}} xmm0 = xmm1[0,1,2,3,4,7,4,4]
226 ; X64-NEXT:    pinsrw $4, %eax, %xmm0
227 ; X64-NEXT:    retq
228 entry:
229         %tmp9 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 8, i32 9, i32 undef, i32 undef, i32 11, i32 3, i32 undef , i32 undef >
230         ret <8 x i16> %tmp9
231 }
232
233 define <8 x i16> @t14(<8 x i16> %T0, <8 x i16> %T1) nounwind readnone {
234 ; X64-LABEL: t14:
235 ; X64:       ## BB#0: ## %entry
236 ; X64-NEXT:    punpcklqdq {{.*#+}} xmm1 = xmm1[0],xmm0[0]
237 ; X64-NEXT:    pshufhw {{.*#+}} xmm0 = xmm1[0,1,2,3,4,6,4,4]
238 ; X64-NEXT:    retq
239 entry:
240         %tmp9 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 8, i32 9, i32 undef, i32 undef, i32 undef, i32 2, i32 undef , i32 undef >
241         ret <8 x i16> %tmp9
242 }
243
244 ; FIXME: t15 is worse off from disabling of scheduler 2-address hack.
245 define <8 x i16> @t15(<8 x i16> %T0, <8 x i16> %T1) nounwind readnone {
246 ; X64-LABEL: t15:
247 ; X64:       ## BB#0: ## %entry
248 ; X64-NEXT:    pextrw $7, %xmm0, %eax
249 ; X64-NEXT:    punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0]
250 ; X64-NEXT:    pshuflw {{.*#+}} xmm0 = xmm0[0,0,0,2,4,5,6,7]
251 ; X64-NEXT:    pinsrw $2, %eax, %xmm0
252 ; X64-NEXT:    retq
253 entry:
254   %tmp8 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 undef, i32 undef, i32 7, i32 2, i32 8, i32 undef, i32 undef , i32 undef >
255   ret <8 x i16> %tmp8
256 }
257
258 ; Test yonah where we convert a shuffle to pextrw and pinrsw
259 define <16 x i8> @t16(<16 x i8> %T0) nounwind readnone {
260 ; X64-LABEL: t16:
261 ; X64:       ## BB#0: ## %entry
262 ; X64-NEXT:    pextrw $8, %xmm0, %eax
263 ; X64-NEXT:    pslldq $2, %xmm0
264 ; X64-NEXT:    andl $65280, %eax ## imm = 0xFF00
265 ; X64-NEXT:    pextrw $1, %xmm0, %ecx
266 ; X64-NEXT:    movzbl %cl, %ecx
267 ; X64-NEXT:    orl %eax, %ecx
268 ; X64-NEXT:    pinsrw $1, %ecx, %xmm0
269 ; X64-NEXT:    retq
270 entry:
271   %tmp8 = shufflevector <16 x i8> <i8 0, i8 0, i8 0, i8 0, i8 1, i8 1, i8 1, i8 1, i8 0, i8 0, i8 0, i8 0,  i8 0, i8 0, i8 0, i8 0>, <16 x i8> %T0, <16 x i32> < i32 0, i32 1, i32 16, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef , i32 undef >
272   %tmp9 = shufflevector <16 x i8> %tmp8, <16 x i8> %T0,  <16 x i32> < i32 0, i32 1, i32 2, i32 17,  i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef, i32 undef , i32 undef >
273   ret <16 x i8> %tmp9
274 }
275
276 ; rdar://8520311
277 define <4 x i32> @t17() nounwind {
278 ; X64-LABEL: t17:
279 ; X64:       ## BB#0: ## %entry
280 ; X64-NEXT:    movddup (%rax), %xmm0
281 ; X64-NEXT:    andpd {{.*}}(%rip), %xmm0
282 ; X64-NEXT:    retq
283 entry:
284   %tmp1 = load <4 x float>* undef, align 16
285   %tmp2 = shufflevector <4 x float> %tmp1, <4 x float> undef, <4 x i32> <i32 4, i32 1, i32 2, i32 3>
286   %tmp3 = load <4 x float>* undef, align 16
287   %tmp4 = shufflevector <4 x float> %tmp2, <4 x float> undef, <4 x i32> <i32 undef, i32 undef, i32 0, i32 1>
288   %tmp5 = bitcast <4 x float> %tmp3 to <4 x i32>
289   %tmp6 = shufflevector <4 x i32> %tmp5, <4 x i32> undef, <4 x i32> <i32 undef, i32 undef, i32 0, i32 1>
290   %tmp7 = and <4 x i32> %tmp6, <i32 undef, i32 undef, i32 -1, i32 0>
291   ret <4 x i32> %tmp7
292 }