[X86] Refactor the logic to select horizontal adds/subs to a helper function.
[oota-llvm.git] / test / CodeGen / X86 / haddsub-2.ll
1 ; RUN: llc < %s -march=x86-64 -mattr=+sse2,+sse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE3
2 ; RUN: llc < %s -march=x86-64 -mattr=+sse2,+sse3,+ssse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSSE3
3 ; RUN: llc < %s -march=x86-64 -mcpu=corei7-avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX
4 ; RUN: llc < %s -march=x86-64 -mcpu=core-avx2 | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2
5
6
7
8 define <4 x float> @hadd_ps_test1(<4 x float> %A, <4 x float> %B) {
9   %vecext = extractelement <4 x float> %A, i32 0
10   %vecext1 = extractelement <4 x float> %A, i32 1
11   %add = fadd float %vecext, %vecext1
12   %vecinit = insertelement <4 x float> undef, float %add, i32 0
13   %vecext2 = extractelement <4 x float> %A, i32 2
14   %vecext3 = extractelement <4 x float> %A, i32 3
15   %add4 = fadd float %vecext2, %vecext3
16   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
17   %vecext6 = extractelement <4 x float> %B, i32 0
18   %vecext7 = extractelement <4 x float> %B, i32 1
19   %add8 = fadd float %vecext6, %vecext7
20   %vecinit9 = insertelement <4 x float> %vecinit5, float %add8, i32 2
21   %vecext10 = extractelement <4 x float> %B, i32 2
22   %vecext11 = extractelement <4 x float> %B, i32 3
23   %add12 = fadd float %vecext10, %vecext11
24   %vecinit13 = insertelement <4 x float> %vecinit9, float %add12, i32 3
25   ret <4 x float> %vecinit13
26 }
27 ; CHECK-LABEL: hadd_ps_test1
28 ; CHECK: haddps
29 ; CHECK-NEXT: ret
30
31
32 define <4 x float> @hadd_ps_test2(<4 x float> %A, <4 x float> %B) {
33   %vecext = extractelement <4 x float> %A, i32 2
34   %vecext1 = extractelement <4 x float> %A, i32 3
35   %add = fadd float %vecext, %vecext1
36   %vecinit = insertelement <4 x float> undef, float %add, i32 1
37   %vecext2 = extractelement <4 x float> %A, i32 0
38   %vecext3 = extractelement <4 x float> %A, i32 1
39   %add4 = fadd float %vecext2, %vecext3
40   %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 0
41   %vecext6 = extractelement <4 x float> %B, i32 2
42   %vecext7 = extractelement <4 x float> %B, i32 3
43   %add8 = fadd float %vecext6, %vecext7
44   %vecinit9 = insertelement <4 x float> %vecinit5, float %add8, i32 3
45   %vecext10 = extractelement <4 x float> %B, i32 0
46   %vecext11 = extractelement <4 x float> %B, i32 1
47   %add12 = fadd float %vecext10, %vecext11
48   %vecinit13 = insertelement <4 x float> %vecinit9, float %add12, i32 2
49   ret <4 x float> %vecinit13
50 }
51 ; CHECK-LABEL: hadd_ps_test2
52 ; CHECK: haddps
53 ; CHECK-NEXT: ret
54
55
56 define <4 x float> @hsub_ps_test1(<4 x float> %A, <4 x float> %B) {
57   %vecext = extractelement <4 x float> %A, i32 0
58   %vecext1 = extractelement <4 x float> %A, i32 1
59   %sub = fsub float %vecext, %vecext1
60   %vecinit = insertelement <4 x float> undef, float %sub, i32 0
61   %vecext2 = extractelement <4 x float> %A, i32 2
62   %vecext3 = extractelement <4 x float> %A, i32 3
63   %sub4 = fsub float %vecext2, %vecext3
64   %vecinit5 = insertelement <4 x float> %vecinit, float %sub4, i32 1
65   %vecext6 = extractelement <4 x float> %B, i32 0
66   %vecext7 = extractelement <4 x float> %B, i32 1
67   %sub8 = fsub float %vecext6, %vecext7
68   %vecinit9 = insertelement <4 x float> %vecinit5, float %sub8, i32 2
69   %vecext10 = extractelement <4 x float> %B, i32 2
70   %vecext11 = extractelement <4 x float> %B, i32 3
71   %sub12 = fsub float %vecext10, %vecext11
72   %vecinit13 = insertelement <4 x float> %vecinit9, float %sub12, i32 3
73   ret <4 x float> %vecinit13
74 }
75 ; CHECK-LABEL: hsub_ps_test1
76 ; CHECK: hsubps
77 ; CHECK-NEXT: ret
78
79
80 define <4 x float> @hsub_ps_test2(<4 x float> %A, <4 x float> %B) {
81   %vecext = extractelement <4 x float> %A, i32 2
82   %vecext1 = extractelement <4 x float> %A, i32 3
83   %sub = fsub float %vecext, %vecext1
84   %vecinit = insertelement <4 x float> undef, float %sub, i32 1
85   %vecext2 = extractelement <4 x float> %A, i32 0
86   %vecext3 = extractelement <4 x float> %A, i32 1
87   %sub4 = fsub float %vecext2, %vecext3
88   %vecinit5 = insertelement <4 x float> %vecinit, float %sub4, i32 0
89   %vecext6 = extractelement <4 x float> %B, i32 2
90   %vecext7 = extractelement <4 x float> %B, i32 3
91   %sub8 = fsub float %vecext6, %vecext7
92   %vecinit9 = insertelement <4 x float> %vecinit5, float %sub8, i32 3
93   %vecext10 = extractelement <4 x float> %B, i32 0
94   %vecext11 = extractelement <4 x float> %B, i32 1
95   %sub12 = fsub float %vecext10, %vecext11
96   %vecinit13 = insertelement <4 x float> %vecinit9, float %sub12, i32 2
97   ret <4 x float> %vecinit13
98 }
99 ; CHECK-LABEL: hsub_ps_test2
100 ; CHECK: hsubps
101 ; CHECK-NEXT: ret
102
103
104 define <4 x i32> @phadd_d_test1(<4 x i32> %A, <4 x i32> %B) {
105   %vecext = extractelement <4 x i32> %A, i32 0
106   %vecext1 = extractelement <4 x i32> %A, i32 1
107   %add = add i32 %vecext, %vecext1
108   %vecinit = insertelement <4 x i32> undef, i32 %add, i32 0
109   %vecext2 = extractelement <4 x i32> %A, i32 2
110   %vecext3 = extractelement <4 x i32> %A, i32 3
111   %add4 = add i32 %vecext2, %vecext3
112   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %add4, i32 1
113   %vecext6 = extractelement <4 x i32> %B, i32 0
114   %vecext7 = extractelement <4 x i32> %B, i32 1
115   %add8 = add i32 %vecext6, %vecext7
116   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %add8, i32 2
117   %vecext10 = extractelement <4 x i32> %B, i32 2
118   %vecext11 = extractelement <4 x i32> %B, i32 3
119   %add12 = add i32 %vecext10, %vecext11
120   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %add12, i32 3
121   ret <4 x i32> %vecinit13
122 }
123 ; CHECK-LABEL: phadd_d_test1
124 ; SSE3-NOT: phaddd
125 ; SSSE3: phaddd
126 ; AVX: vphaddd
127 ; AVX2 vphaddd
128 ; CHECK: ret
129
130
131 define <4 x i32> @phadd_d_test2(<4 x i32> %A, <4 x i32> %B) {
132   %vecext = extractelement <4 x i32> %A, i32 2
133   %vecext1 = extractelement <4 x i32> %A, i32 3
134   %add = add i32 %vecext, %vecext1
135   %vecinit = insertelement <4 x i32> undef, i32 %add, i32 1
136   %vecext2 = extractelement <4 x i32> %A, i32 0
137   %vecext3 = extractelement <4 x i32> %A, i32 1
138   %add4 = add i32 %vecext2, %vecext3
139   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %add4, i32 0
140   %vecext6 = extractelement <4 x i32> %B, i32 3
141   %vecext7 = extractelement <4 x i32> %B, i32 2
142   %add8 = add i32 %vecext6, %vecext7
143   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %add8, i32 3
144   %vecext10 = extractelement <4 x i32> %B, i32 1
145   %vecext11 = extractelement <4 x i32> %B, i32 0
146   %add12 = add i32 %vecext10, %vecext11
147   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %add12, i32 2
148   ret <4 x i32> %vecinit13
149 }
150 ; CHECK-LABEL: phadd_d_test2
151 ; SSE3-NOT: phaddd
152 ; SSSE3: phaddd
153 ; AVX: vphaddd
154 ; AVX2 vphaddd
155 ; CHECK: ret
156
157
158 define <4 x i32> @phsub_d_test1(<4 x i32> %A, <4 x i32> %B) {
159   %vecext = extractelement <4 x i32> %A, i32 0
160   %vecext1 = extractelement <4 x i32> %A, i32 1
161   %sub = sub i32 %vecext, %vecext1
162   %vecinit = insertelement <4 x i32> undef, i32 %sub, i32 0
163   %vecext2 = extractelement <4 x i32> %A, i32 2
164   %vecext3 = extractelement <4 x i32> %A, i32 3
165   %sub4 = sub i32 %vecext2, %vecext3
166   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %sub4, i32 1
167   %vecext6 = extractelement <4 x i32> %B, i32 0
168   %vecext7 = extractelement <4 x i32> %B, i32 1
169   %sub8 = sub i32 %vecext6, %vecext7
170   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %sub8, i32 2
171   %vecext10 = extractelement <4 x i32> %B, i32 2
172   %vecext11 = extractelement <4 x i32> %B, i32 3
173   %sub12 = sub i32 %vecext10, %vecext11
174   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %sub12, i32 3
175   ret <4 x i32> %vecinit13
176 }
177 ; CHECK-LABEL: phsub_d_test1
178 ; SSE3-NOT: phsubd
179 ; SSSE3: phsubd
180 ; AVX: vphsubd
181 ; AVX2 vphsubd
182 ; CHECK: ret
183
184
185 define <4 x i32> @phsub_d_test2(<4 x i32> %A, <4 x i32> %B) {
186   %vecext = extractelement <4 x i32> %A, i32 2
187   %vecext1 = extractelement <4 x i32> %A, i32 3
188   %sub = sub i32 %vecext, %vecext1
189   %vecinit = insertelement <4 x i32> undef, i32 %sub, i32 1
190   %vecext2 = extractelement <4 x i32> %A, i32 0
191   %vecext3 = extractelement <4 x i32> %A, i32 1
192   %sub4 = sub i32 %vecext2, %vecext3
193   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %sub4, i32 0
194   %vecext6 = extractelement <4 x i32> %B, i32 2
195   %vecext7 = extractelement <4 x i32> %B, i32 3
196   %sub8 = sub i32 %vecext6, %vecext7
197   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %sub8, i32 3
198   %vecext10 = extractelement <4 x i32> %B, i32 0
199   %vecext11 = extractelement <4 x i32> %B, i32 1
200   %sub12 = sub i32 %vecext10, %vecext11
201   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %sub12, i32 2
202   ret <4 x i32> %vecinit13
203 }
204 ; CHECK-LABEL: phsub_d_test2
205 ; SSE3-NOT: phsubd
206 ; SSSE3: phsubd
207 ; AVX: vphsubd
208 ; AVX2 vphsubd
209 ; CHECK: ret
210
211
212 define <2 x double> @hadd_pd_test1(<2 x double> %A, <2 x double> %B) {
213   %vecext = extractelement <2 x double> %A, i32 0
214   %vecext1 = extractelement <2 x double> %A, i32 1
215   %add = fadd double %vecext, %vecext1
216   %vecinit = insertelement <2 x double> undef, double %add, i32 0
217   %vecext2 = extractelement <2 x double> %B, i32 0
218   %vecext3 = extractelement <2 x double> %B, i32 1
219   %add2 = fadd double %vecext2, %vecext3
220   %vecinit2 = insertelement <2 x double> %vecinit, double %add2, i32 1
221   ret <2 x double> %vecinit2
222 }
223 ; CHECK-LABEL: hadd_pd_test1
224 ; CHECK: haddpd
225 ; CHECK-NEXT: ret
226
227
228 define <2 x double> @hadd_pd_test2(<2 x double> %A, <2 x double> %B) {
229   %vecext = extractelement <2 x double> %A, i32 1
230   %vecext1 = extractelement <2 x double> %A, i32 0
231   %add = fadd double %vecext, %vecext1
232   %vecinit = insertelement <2 x double> undef, double %add, i32 0
233   %vecext2 = extractelement <2 x double> %B, i32 1
234   %vecext3 = extractelement <2 x double> %B, i32 0
235   %add2 = fadd double %vecext2, %vecext3
236   %vecinit2 = insertelement <2 x double> %vecinit, double %add2, i32 1
237   ret <2 x double> %vecinit2
238 }
239 ; CHECK-LABEL: hadd_pd_test2
240 ; CHECK: haddpd
241 ; CHECK-NEXT: ret
242
243
244 define <2 x double> @hsub_pd_test1(<2 x double> %A, <2 x double> %B) {
245   %vecext = extractelement <2 x double> %A, i32 0
246   %vecext1 = extractelement <2 x double> %A, i32 1
247   %sub = fsub double %vecext, %vecext1
248   %vecinit = insertelement <2 x double> undef, double %sub, i32 0
249   %vecext2 = extractelement <2 x double> %B, i32 0
250   %vecext3 = extractelement <2 x double> %B, i32 1
251   %sub2 = fsub double %vecext2, %vecext3
252   %vecinit2 = insertelement <2 x double> %vecinit, double %sub2, i32 1
253   ret <2 x double> %vecinit2
254 }
255 ; CHECK-LABEL: hsub_pd_test1
256 ; CHECK: hsubpd
257 ; CHECK-NEXT: ret
258
259
260 define <2 x double> @hsub_pd_test2(<2 x double> %A, <2 x double> %B) {
261   %vecext = extractelement <2 x double> %B, i32 0
262   %vecext1 = extractelement <2 x double> %B, i32 1
263   %sub = fsub double %vecext, %vecext1
264   %vecinit = insertelement <2 x double> undef, double %sub, i32 1
265   %vecext2 = extractelement <2 x double> %A, i32 0
266   %vecext3 = extractelement <2 x double> %A, i32 1
267   %sub2 = fsub double %vecext2, %vecext3
268   %vecinit2 = insertelement <2 x double> %vecinit, double %sub2, i32 0
269   ret <2 x double> %vecinit2
270 }
271 ; CHECK-LABEL: hsub_pd_test2
272 ; CHECK: hsubpd
273 ; CHECK-NEXT: ret
274
275
276 define <4 x double> @avx_vhadd_pd_test(<4 x double> %A, <4 x double> %B) {
277   %vecext = extractelement <4 x double> %A, i32 0
278   %vecext1 = extractelement <4 x double> %A, i32 1
279   %add = fadd double %vecext, %vecext1
280   %vecinit = insertelement <4 x double> undef, double %add, i32 0
281   %vecext2 = extractelement <4 x double> %A, i32 2
282   %vecext3 = extractelement <4 x double> %A, i32 3
283   %add4 = fadd double %vecext2, %vecext3
284   %vecinit5 = insertelement <4 x double> %vecinit, double %add4, i32 1
285   %vecext6 = extractelement <4 x double> %B, i32 0
286   %vecext7 = extractelement <4 x double> %B, i32 1
287   %add8 = fadd double %vecext6, %vecext7
288   %vecinit9 = insertelement <4 x double> %vecinit5, double %add8, i32 2
289   %vecext10 = extractelement <4 x double> %B, i32 2
290   %vecext11 = extractelement <4 x double> %B, i32 3
291   %add12 = fadd double %vecext10, %vecext11
292   %vecinit13 = insertelement <4 x double> %vecinit9, double %add12, i32 3
293   ret <4 x double> %vecinit13
294 }
295 ; CHECK-LABEL: avx_vhadd_pd_test
296 ; SSE3: haddpd
297 ; SSE3-NEXT: haddpd
298 ; SSSE3: haddpd
299 ; SSSE3: haddpd
300 ; AVX: vhaddpd
301 ; AVX: vhaddpd
302 ; AVX2: vhaddpd
303 ; AVX2: vhaddpd
304 ; CHECK: ret
305
306
307 define <4 x double> @avx_vhsub_pd_test(<4 x double> %A, <4 x double> %B) {
308   %vecext = extractelement <4 x double> %A, i32 0
309   %vecext1 = extractelement <4 x double> %A, i32 1
310   %sub = fsub double %vecext, %vecext1
311   %vecinit = insertelement <4 x double> undef, double %sub, i32 0
312   %vecext2 = extractelement <4 x double> %A, i32 2
313   %vecext3 = extractelement <4 x double> %A, i32 3
314   %sub4 = fsub double %vecext2, %vecext3
315   %vecinit5 = insertelement <4 x double> %vecinit, double %sub4, i32 1
316   %vecext6 = extractelement <4 x double> %B, i32 0
317   %vecext7 = extractelement <4 x double> %B, i32 1
318   %sub8 = fsub double %vecext6, %vecext7
319   %vecinit9 = insertelement <4 x double> %vecinit5, double %sub8, i32 2
320   %vecext10 = extractelement <4 x double> %B, i32 2
321   %vecext11 = extractelement <4 x double> %B, i32 3
322   %sub12 = fsub double %vecext10, %vecext11
323   %vecinit13 = insertelement <4 x double> %vecinit9, double %sub12, i32 3
324   ret <4 x double> %vecinit13
325 }
326 ; CHECK-LABEL: avx_vhsub_pd_test
327 ; SSE3: hsubpd
328 ; SSE3-NEXT: hsubpd
329 ; SSSE3: hsubpd
330 ; SSSE3-NEXT: hsubpd
331 ; AVX: vhsubpd
332 ; AVX: vhsubpd
333 ; AVX2: vhsubpd
334 ; AVX2: vhsubpd
335 ; CHECK: ret
336
337
338 define <8 x i32> @avx2_vphadd_d_test(<8 x i32> %A, <8 x i32> %B) {
339   %vecext = extractelement <8 x i32> %A, i32 0
340   %vecext1 = extractelement <8 x i32> %A, i32 1
341   %add = add i32 %vecext, %vecext1
342   %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
343   %vecext2 = extractelement <8 x i32> %A, i32 2
344   %vecext3 = extractelement <8 x i32> %A, i32 3
345   %add4 = add i32 %vecext2, %vecext3
346   %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 1
347   %vecext6 = extractelement <8 x i32> %A, i32 4
348   %vecext7 = extractelement <8 x i32> %A, i32 5
349   %add8 = add i32 %vecext6, %vecext7
350   %vecinit9 = insertelement <8 x i32> %vecinit5, i32 %add8, i32 2
351   %vecext10 = extractelement <8 x i32> %A, i32 6
352   %vecext11 = extractelement <8 x i32> %A, i32 7
353   %add12 = add i32 %vecext10, %vecext11
354   %vecinit13 = insertelement <8 x i32> %vecinit9, i32 %add12, i32 3
355   %vecext14 = extractelement <8 x i32> %B, i32 0
356   %vecext15 = extractelement <8 x i32> %B, i32 1
357   %add16 = add i32 %vecext14, %vecext15
358   %vecinit17 = insertelement <8 x i32> %vecinit13, i32 %add16, i32 4
359   %vecext18 = extractelement <8 x i32> %B, i32 2
360   %vecext19 = extractelement <8 x i32> %B, i32 3
361   %add20 = add i32 %vecext18, %vecext19
362   %vecinit21 = insertelement <8 x i32> %vecinit17, i32 %add20, i32 5
363   %vecext22 = extractelement <8 x i32> %B, i32 4
364   %vecext23 = extractelement <8 x i32> %B, i32 5
365   %add24 = add i32 %vecext22, %vecext23
366   %vecinit25 = insertelement <8 x i32> %vecinit21, i32 %add24, i32 6
367   %vecext26 = extractelement <8 x i32> %B, i32 6
368   %vecext27 = extractelement <8 x i32> %B, i32 7
369   %add28 = add i32 %vecext26, %vecext27
370   %vecinit29 = insertelement <8 x i32> %vecinit25, i32 %add28, i32 7
371   ret <8 x i32> %vecinit29
372 }
373 ; CHECK-LABEL: avx2_vphadd_d_test
374 ; SSE3-NOT: phaddd
375 ; SSSE3: phaddd
376 ; SSSE3-NEXT: phaddd
377 ; AVX: vphaddd
378 ; AVX: vphaddd
379 ; AVX2: vphaddd
380 ; AVX2: vphaddd
381 ; CHECK: ret
382
383 define <16 x i16> @avx2_vphadd_w_test(<16 x i16> %a, <16 x i16> %b) {
384   %vecext = extractelement <16 x i16> %a, i32 0
385   %vecext1 = extractelement <16 x i16> %a, i32 1
386   %add = add i16 %vecext, %vecext1
387   %vecinit = insertelement <16 x i16> undef, i16 %add, i32 0
388   %vecext4 = extractelement <16 x i16> %a, i32 2
389   %vecext6 = extractelement <16 x i16> %a, i32 3
390   %add8 = add i16 %vecext4, %vecext6
391   %vecinit10 = insertelement <16 x i16> %vecinit, i16 %add8, i32 1
392   %vecext11 = extractelement <16 x i16> %a, i32 4
393   %vecext13 = extractelement <16 x i16> %a, i32 5
394   %add15 = add i16 %vecext11, %vecext13
395   %vecinit17 = insertelement <16 x i16> %vecinit10, i16 %add15, i32 2
396   %vecext18 = extractelement <16 x i16> %a, i32 6
397   %vecext20 = extractelement <16 x i16> %a, i32 7
398   %add22 = add i16 %vecext18, %vecext20
399   %vecinit24 = insertelement <16 x i16> %vecinit17, i16 %add22, i32 3
400   %vecext25 = extractelement <16 x i16> %a, i32 8
401   %vecext27 = extractelement <16 x i16> %a, i32 9
402   %add29 = add i16 %vecext25, %vecext27
403   %vecinit31 = insertelement <16 x i16> %vecinit24, i16 %add29, i32 4
404   %vecext32 = extractelement <16 x i16> %a, i32 10
405   %vecext34 = extractelement <16 x i16> %a, i32 11
406   %add36 = add i16 %vecext32, %vecext34
407   %vecinit38 = insertelement <16 x i16> %vecinit31, i16 %add36, i32 5
408   %vecext39 = extractelement <16 x i16> %a, i32 12
409   %vecext41 = extractelement <16 x i16> %a, i32 13
410   %add43 = add i16 %vecext39, %vecext41
411   %vecinit45 = insertelement <16 x i16> %vecinit38, i16 %add43, i32 6
412   %vecext46 = extractelement <16 x i16> %a, i32 14
413   %vecext48 = extractelement <16 x i16> %a, i32 15
414   %add50 = add i16 %vecext46, %vecext48
415   %vecinit52 = insertelement <16 x i16> %vecinit45, i16 %add50, i32 7
416   %vecext53 = extractelement <16 x i16> %b, i32 0
417   %vecext55 = extractelement <16 x i16> %b, i32 1
418   %add57 = add i16 %vecext53, %vecext55
419   %vecinit59 = insertelement <16 x i16> %vecinit52, i16 %add57, i32 8
420   %vecext60 = extractelement <16 x i16> %b, i32 2
421   %vecext62 = extractelement <16 x i16> %b, i32 3
422   %add64 = add i16 %vecext60, %vecext62
423   %vecinit66 = insertelement <16 x i16> %vecinit59, i16 %add64, i32 9
424   %vecext67 = extractelement <16 x i16> %b, i32 4
425   %vecext69 = extractelement <16 x i16> %b, i32 5
426   %add71 = add i16 %vecext67, %vecext69
427   %vecinit73 = insertelement <16 x i16> %vecinit66, i16 %add71, i32 10
428   %vecext74 = extractelement <16 x i16> %b, i32 6
429   %vecext76 = extractelement <16 x i16> %b, i32 7
430   %add78 = add i16 %vecext74, %vecext76
431   %vecinit80 = insertelement <16 x i16> %vecinit73, i16 %add78, i32 11
432   %vecext81 = extractelement <16 x i16> %b, i32 8
433   %vecext83 = extractelement <16 x i16> %b, i32 9
434   %add85 = add i16 %vecext81, %vecext83
435   %vecinit87 = insertelement <16 x i16> %vecinit80, i16 %add85, i32 12
436   %vecext88 = extractelement <16 x i16> %b, i32 10
437   %vecext90 = extractelement <16 x i16> %b, i32 11
438   %add92 = add i16 %vecext88, %vecext90
439   %vecinit94 = insertelement <16 x i16> %vecinit87, i16 %add92, i32 13
440   %vecext95 = extractelement <16 x i16> %b, i32 12
441   %vecext97 = extractelement <16 x i16> %b, i32 13
442   %add99 = add i16 %vecext95, %vecext97
443   %vecinit101 = insertelement <16 x i16> %vecinit94, i16 %add99, i32 14
444   %vecext102 = extractelement <16 x i16> %b, i32 14
445   %vecext104 = extractelement <16 x i16> %b, i32 15
446   %add106 = add i16 %vecext102, %vecext104
447   %vecinit108 = insertelement <16 x i16> %vecinit101, i16 %add106, i32 15
448   ret <16 x i16> %vecinit108
449 }
450 ; CHECK-LABEL: avx2_vphadd_w_test
451 ; SSE3-NOT: phaddw
452 ; SSSE3: phaddw
453 ; SSSE3-NEXT: phaddw
454 ; AVX: vphaddw
455 ; AVX: vphaddw
456 ; AVX2: vphaddw
457 ; AVX2: vphaddw
458 ; CHECK: ret
459
460
461 ; Verify that we don't select horizontal subs in the following functions.
462
463 define <4 x i32> @not_a_hsub_1(<4 x i32> %A, <4 x i32> %B) {
464   %vecext = extractelement <4 x i32> %A, i32 0
465   %vecext1 = extractelement <4 x i32> %A, i32 1
466   %sub = sub i32 %vecext, %vecext1
467   %vecinit = insertelement <4 x i32> undef, i32 %sub, i32 0
468   %vecext2 = extractelement <4 x i32> %A, i32 2
469   %vecext3 = extractelement <4 x i32> %A, i32 3
470   %sub4 = sub i32 %vecext2, %vecext3
471   %vecinit5 = insertelement <4 x i32> %vecinit, i32 %sub4, i32 1
472   %vecext6 = extractelement <4 x i32> %B, i32 1
473   %vecext7 = extractelement <4 x i32> %B, i32 0
474   %sub8 = sub i32 %vecext6, %vecext7
475   %vecinit9 = insertelement <4 x i32> %vecinit5, i32 %sub8, i32 2
476   %vecext10 = extractelement <4 x i32> %B, i32 3
477   %vecext11 = extractelement <4 x i32> %B, i32 2
478   %sub12 = sub i32 %vecext10, %vecext11
479   %vecinit13 = insertelement <4 x i32> %vecinit9, i32 %sub12, i32 3
480   ret <4 x i32> %vecinit13
481 }
482 ; CHECK-LABEL: not_a_hsub_1
483 ; CHECK-NOT: phsubd
484 ; CHECK: ret
485
486
487 define <4 x float> @not_a_hsub_2(<4 x float> %A, <4 x float> %B) {
488   %vecext = extractelement <4 x float> %A, i32 2
489   %vecext1 = extractelement <4 x float> %A, i32 3
490   %sub = fsub float %vecext, %vecext1
491   %vecinit = insertelement <4 x float> undef, float %sub, i32 1
492   %vecext2 = extractelement <4 x float> %A, i32 0
493   %vecext3 = extractelement <4 x float> %A, i32 1
494   %sub4 = fsub float %vecext2, %vecext3
495   %vecinit5 = insertelement <4 x float> %vecinit, float %sub4, i32 0
496   %vecext6 = extractelement <4 x float> %B, i32 3
497   %vecext7 = extractelement <4 x float> %B, i32 2
498   %sub8 = fsub float %vecext6, %vecext7
499   %vecinit9 = insertelement <4 x float> %vecinit5, float %sub8, i32 3
500   %vecext10 = extractelement <4 x float> %B, i32 0
501   %vecext11 = extractelement <4 x float> %B, i32 1
502   %sub12 = fsub float %vecext10, %vecext11
503   %vecinit13 = insertelement <4 x float> %vecinit9, float %sub12, i32 2
504   ret <4 x float> %vecinit13
505 }
506 ; CHECK-LABEL: not_a_hsub_2
507 ; CHECK-NOT: hsubps
508 ; CHECK: ret
509
510
511 define <2 x double> @not_a_hsub_3(<2 x double> %A, <2 x double> %B) {
512   %vecext = extractelement <2 x double> %B, i32 0
513   %vecext1 = extractelement <2 x double> %B, i32 1
514   %sub = fsub double %vecext, %vecext1
515   %vecinit = insertelement <2 x double> undef, double %sub, i32 1
516   %vecext2 = extractelement <2 x double> %A, i32 1
517   %vecext3 = extractelement <2 x double> %A, i32 0
518   %sub2 = fsub double %vecext2, %vecext3
519   %vecinit2 = insertelement <2 x double> %vecinit, double %sub2, i32 0
520   ret <2 x double> %vecinit2
521 }
522 ; CHECK-LABEL: not_a_hsub_3
523 ; CHECK-NOT: hsubpd
524 ; CHECK: ret
525