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
8define <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
32define <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
56define <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
80define <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
104define <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
131define <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
158define <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
185define <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
212define <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
228define <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
244define <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
260define <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
276define <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
307define <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
338define <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
383define <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
463define <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
487define <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
511define <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
526
527; Test AVX horizontal add/sub of packed single/double precision
528; floating point values from 256-bit vectors.
529
530define <8 x float> @avx_vhadd_ps(<8 x float> %a, <8 x float> %b) {
531  %vecext = extractelement <8 x float> %a, i32 0
532  %vecext1 = extractelement <8 x float> %a, i32 1
533  %add = fadd float %vecext, %vecext1
534  %vecinit = insertelement <8 x float> undef, float %add, i32 0
535  %vecext2 = extractelement <8 x float> %a, i32 2
536  %vecext3 = extractelement <8 x float> %a, i32 3
537  %add4 = fadd float %vecext2, %vecext3
538  %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 1
539  %vecext6 = extractelement <8 x float> %b, i32 0
540  %vecext7 = extractelement <8 x float> %b, i32 1
541  %add8 = fadd float %vecext6, %vecext7
542  %vecinit9 = insertelement <8 x float> %vecinit5, float %add8, i32 2
543  %vecext10 = extractelement <8 x float> %b, i32 2
544  %vecext11 = extractelement <8 x float> %b, i32 3
545  %add12 = fadd float %vecext10, %vecext11
546  %vecinit13 = insertelement <8 x float> %vecinit9, float %add12, i32 3
547  %vecext14 = extractelement <8 x float> %a, i32 4
548  %vecext15 = extractelement <8 x float> %a, i32 5
549  %add16 = fadd float %vecext14, %vecext15
550  %vecinit17 = insertelement <8 x float> %vecinit13, float %add16, i32 4
551  %vecext18 = extractelement <8 x float> %a, i32 6
552  %vecext19 = extractelement <8 x float> %a, i32 7
553  %add20 = fadd float %vecext18, %vecext19
554  %vecinit21 = insertelement <8 x float> %vecinit17, float %add20, i32 5
555  %vecext22 = extractelement <8 x float> %b, i32 4
556  %vecext23 = extractelement <8 x float> %b, i32 5
557  %add24 = fadd float %vecext22, %vecext23
558  %vecinit25 = insertelement <8 x float> %vecinit21, float %add24, i32 6
559  %vecext26 = extractelement <8 x float> %b, i32 6
560  %vecext27 = extractelement <8 x float> %b, i32 7
561  %add28 = fadd float %vecext26, %vecext27
562  %vecinit29 = insertelement <8 x float> %vecinit25, float %add28, i32 7
563  ret <8 x float> %vecinit29
564}
565; CHECK-LABEL: avx_vhadd_ps
566; SSE3: haddps
567; SSE3-NEXT: haddps
568; SSSE3: haddps
569; SSSE3-NEXT: haddps
570; AVX: vhaddps
571; AVX2: vhaddps
572; CHECK: ret
573
574
575define <8 x float> @avx_vhsub_ps(<8 x float> %a, <8 x float> %b) {
576  %vecext = extractelement <8 x float> %a, i32 0
577  %vecext1 = extractelement <8 x float> %a, i32 1
578  %sub = fsub float %vecext, %vecext1
579  %vecinit = insertelement <8 x float> undef, float %sub, i32 0
580  %vecext2 = extractelement <8 x float> %a, i32 2
581  %vecext3 = extractelement <8 x float> %a, i32 3
582  %sub4 = fsub float %vecext2, %vecext3
583  %vecinit5 = insertelement <8 x float> %vecinit, float %sub4, i32 1
584  %vecext6 = extractelement <8 x float> %b, i32 0
585  %vecext7 = extractelement <8 x float> %b, i32 1
586  %sub8 = fsub float %vecext6, %vecext7
587  %vecinit9 = insertelement <8 x float> %vecinit5, float %sub8, i32 2
588  %vecext10 = extractelement <8 x float> %b, i32 2
589  %vecext11 = extractelement <8 x float> %b, i32 3
590  %sub12 = fsub float %vecext10, %vecext11
591  %vecinit13 = insertelement <8 x float> %vecinit9, float %sub12, i32 3
592  %vecext14 = extractelement <8 x float> %a, i32 4
593  %vecext15 = extractelement <8 x float> %a, i32 5
594  %sub16 = fsub float %vecext14, %vecext15
595  %vecinit17 = insertelement <8 x float> %vecinit13, float %sub16, i32 4
596  %vecext18 = extractelement <8 x float> %a, i32 6
597  %vecext19 = extractelement <8 x float> %a, i32 7
598  %sub20 = fsub float %vecext18, %vecext19
599  %vecinit21 = insertelement <8 x float> %vecinit17, float %sub20, i32 5
600  %vecext22 = extractelement <8 x float> %b, i32 4
601  %vecext23 = extractelement <8 x float> %b, i32 5
602  %sub24 = fsub float %vecext22, %vecext23
603  %vecinit25 = insertelement <8 x float> %vecinit21, float %sub24, i32 6
604  %vecext26 = extractelement <8 x float> %b, i32 6
605  %vecext27 = extractelement <8 x float> %b, i32 7
606  %sub28 = fsub float %vecext26, %vecext27
607  %vecinit29 = insertelement <8 x float> %vecinit25, float %sub28, i32 7
608  ret <8 x float> %vecinit29
609}
610; CHECK-LABEL: avx_vhsub_ps
611; SSE3: hsubps
612; SSE3-NEXT: hsubps
613; SSSE3: hsubps
614; SSSE3-NEXT: hsubps
615; AVX: vhsubps
616; AVX2: vhsubps
617; CHECK: ret
618
619
620define <4 x double> @avx_hadd_pd(<4 x double> %a, <4 x double> %b) {
621  %vecext = extractelement <4 x double> %a, i32 0
622  %vecext1 = extractelement <4 x double> %a, i32 1
623  %add = fadd double %vecext, %vecext1
624  %vecinit = insertelement <4 x double> undef, double %add, i32 0
625  %vecext2 = extractelement <4 x double> %b, i32 0
626  %vecext3 = extractelement <4 x double> %b, i32 1
627  %add4 = fadd double %vecext2, %vecext3
628  %vecinit5 = insertelement <4 x double> %vecinit, double %add4, i32 1
629  %vecext6 = extractelement <4 x double> %a, i32 2
630  %vecext7 = extractelement <4 x double> %a, i32 3
631  %add8 = fadd double %vecext6, %vecext7
632  %vecinit9 = insertelement <4 x double> %vecinit5, double %add8, i32 2
633  %vecext10 = extractelement <4 x double> %b, i32 2
634  %vecext11 = extractelement <4 x double> %b, i32 3
635  %add12 = fadd double %vecext10, %vecext11
636  %vecinit13 = insertelement <4 x double> %vecinit9, double %add12, i32 3
637  ret <4 x double> %vecinit13
638}
639; CHECK-LABEL: avx_hadd_pd
640; SSE3: haddpd
641; SSE3-NEXT: haddpd
642; SSSE3: haddpd
643; SSSE3-NEXT: haddpd
644; AVX: vhaddpd
645; AVX2: vhaddpd
646; CHECK: ret
647
648
649define <4 x double> @avx_hsub_pd(<4 x double> %a, <4 x double> %b) {
650  %vecext = extractelement <4 x double> %a, i32 0
651  %vecext1 = extractelement <4 x double> %a, i32 1
652  %sub = fsub double %vecext, %vecext1
653  %vecinit = insertelement <4 x double> undef, double %sub, i32 0
654  %vecext2 = extractelement <4 x double> %b, i32 0
655  %vecext3 = extractelement <4 x double> %b, i32 1
656  %sub4 = fsub double %vecext2, %vecext3
657  %vecinit5 = insertelement <4 x double> %vecinit, double %sub4, i32 1
658  %vecext6 = extractelement <4 x double> %a, i32 2
659  %vecext7 = extractelement <4 x double> %a, i32 3
660  %sub8 = fsub double %vecext6, %vecext7
661  %vecinit9 = insertelement <4 x double> %vecinit5, double %sub8, i32 2
662  %vecext10 = extractelement <4 x double> %b, i32 2
663  %vecext11 = extractelement <4 x double> %b, i32 3
664  %sub12 = fsub double %vecext10, %vecext11
665  %vecinit13 = insertelement <4 x double> %vecinit9, double %sub12, i32 3
666  ret <4 x double> %vecinit13
667}
668; CHECK-LABEL: avx_hsub_pd
669; SSE3: hsubpd
670; SSE3-NEXT: hsubpd
671; SSSE3: hsubpd
672; SSSE3-NEXT: hsubpd
673; AVX: vhsubpd
674; AVX2: vhsubpd
675; CHECK: ret
676
677
678; Test AVX2 horizontal add of packed integer values from 256-bit vectors.
679
680define <8 x i32> @avx2_hadd_d(<8 x i32> %a, <8 x i32> %b) {
681  %vecext = extractelement <8 x i32> %a, i32 0
682  %vecext1 = extractelement <8 x i32> %a, i32 1
683  %add = add i32 %vecext, %vecext1
684  %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
685  %vecext2 = extractelement <8 x i32> %a, i32 2
686  %vecext3 = extractelement <8 x i32> %a, i32 3
687  %add4 = add i32 %vecext2, %vecext3
688  %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 1
689  %vecext6 = extractelement <8 x i32> %b, i32 0
690  %vecext7 = extractelement <8 x i32> %b, i32 1
691  %add8 = add i32 %vecext6, %vecext7
692  %vecinit9 = insertelement <8 x i32> %vecinit5, i32 %add8, i32 2
693  %vecext10 = extractelement <8 x i32> %b, i32 2
694  %vecext11 = extractelement <8 x i32> %b, i32 3
695  %add12 = add i32 %vecext10, %vecext11
696  %vecinit13 = insertelement <8 x i32> %vecinit9, i32 %add12, i32 3
697  %vecext14 = extractelement <8 x i32> %a, i32 4
698  %vecext15 = extractelement <8 x i32> %a, i32 5
699  %add16 = add i32 %vecext14, %vecext15
700  %vecinit17 = insertelement <8 x i32> %vecinit13, i32 %add16, i32 4
701  %vecext18 = extractelement <8 x i32> %a, i32 6
702  %vecext19 = extractelement <8 x i32> %a, i32 7
703  %add20 = add i32 %vecext18, %vecext19
704  %vecinit21 = insertelement <8 x i32> %vecinit17, i32 %add20, i32 5
705  %vecext22 = extractelement <8 x i32> %b, i32 4
706  %vecext23 = extractelement <8 x i32> %b, i32 5
707  %add24 = add i32 %vecext22, %vecext23
708  %vecinit25 = insertelement <8 x i32> %vecinit21, i32 %add24, i32 6
709  %vecext26 = extractelement <8 x i32> %b, i32 6
710  %vecext27 = extractelement <8 x i32> %b, i32 7
711  %add28 = add i32 %vecext26, %vecext27
712  %vecinit29 = insertelement <8 x i32> %vecinit25, i32 %add28, i32 7
713  ret <8 x i32> %vecinit29
714}
715; CHECK-LABEL: avx2_hadd_d
716; SSE3-NOT: phaddd
717; SSSE3: phaddd
718; SSSE3-NEXT: phaddd
719; AVX: vphaddd
720; AVX: vphaddd
721; AVX2: vphaddd
722; AVX2-NOT: vphaddd
723; CHECK: ret
724
725
726define <16 x i16> @avx2_hadd_w(<16 x i16> %a, <16 x i16> %b) {
727  %vecext = extractelement <16 x i16> %a, i32 0
728  %vecext1 = extractelement <16 x i16> %a, i32 1
729  %add = add i16 %vecext, %vecext1
730  %vecinit = insertelement <16 x i16> undef, i16 %add, i32 0
731  %vecext4 = extractelement <16 x i16> %a, i32 2
732  %vecext6 = extractelement <16 x i16> %a, i32 3
733  %add8 = add i16 %vecext4, %vecext6
734  %vecinit10 = insertelement <16 x i16> %vecinit, i16 %add8, i32 1
735  %vecext11 = extractelement <16 x i16> %a, i32 4
736  %vecext13 = extractelement <16 x i16> %a, i32 5
737  %add15 = add i16 %vecext11, %vecext13
738  %vecinit17 = insertelement <16 x i16> %vecinit10, i16 %add15, i32 2
739  %vecext18 = extractelement <16 x i16> %a, i32 6
740  %vecext20 = extractelement <16 x i16> %a, i32 7
741  %add22 = add i16 %vecext18, %vecext20
742  %vecinit24 = insertelement <16 x i16> %vecinit17, i16 %add22, i32 3
743  %vecext25 = extractelement <16 x i16> %a, i32 8
744  %vecext27 = extractelement <16 x i16> %a, i32 9
745  %add29 = add i16 %vecext25, %vecext27
746  %vecinit31 = insertelement <16 x i16> %vecinit24, i16 %add29, i32 8
747  %vecext32 = extractelement <16 x i16> %a, i32 10
748  %vecext34 = extractelement <16 x i16> %a, i32 11
749  %add36 = add i16 %vecext32, %vecext34
750  %vecinit38 = insertelement <16 x i16> %vecinit31, i16 %add36, i32 9
751  %vecext39 = extractelement <16 x i16> %a, i32 12
752  %vecext41 = extractelement <16 x i16> %a, i32 13
753  %add43 = add i16 %vecext39, %vecext41
754  %vecinit45 = insertelement <16 x i16> %vecinit38, i16 %add43, i32 10
755  %vecext46 = extractelement <16 x i16> %a, i32 14
756  %vecext48 = extractelement <16 x i16> %a, i32 15
757  %add50 = add i16 %vecext46, %vecext48
758  %vecinit52 = insertelement <16 x i16> %vecinit45, i16 %add50, i32 11
759  %vecext53 = extractelement <16 x i16> %b, i32 0
760  %vecext55 = extractelement <16 x i16> %b, i32 1
761  %add57 = add i16 %vecext53, %vecext55
762  %vecinit59 = insertelement <16 x i16> %vecinit52, i16 %add57, i32 4
763  %vecext60 = extractelement <16 x i16> %b, i32 2
764  %vecext62 = extractelement <16 x i16> %b, i32 3
765  %add64 = add i16 %vecext60, %vecext62
766  %vecinit66 = insertelement <16 x i16> %vecinit59, i16 %add64, i32 5
767  %vecext67 = extractelement <16 x i16> %b, i32 4
768  %vecext69 = extractelement <16 x i16> %b, i32 5
769  %add71 = add i16 %vecext67, %vecext69
770  %vecinit73 = insertelement <16 x i16> %vecinit66, i16 %add71, i32 6
771  %vecext74 = extractelement <16 x i16> %b, i32 6
772  %vecext76 = extractelement <16 x i16> %b, i32 7
773  %add78 = add i16 %vecext74, %vecext76
774  %vecinit80 = insertelement <16 x i16> %vecinit73, i16 %add78, i32 7
775  %vecext81 = extractelement <16 x i16> %b, i32 8
776  %vecext83 = extractelement <16 x i16> %b, i32 9
777  %add85 = add i16 %vecext81, %vecext83
778  %vecinit87 = insertelement <16 x i16> %vecinit80, i16 %add85, i32 12
779  %vecext88 = extractelement <16 x i16> %b, i32 10
780  %vecext90 = extractelement <16 x i16> %b, i32 11
781  %add92 = add i16 %vecext88, %vecext90
782  %vecinit94 = insertelement <16 x i16> %vecinit87, i16 %add92, i32 13
783  %vecext95 = extractelement <16 x i16> %b, i32 12
784  %vecext97 = extractelement <16 x i16> %b, i32 13
785  %add99 = add i16 %vecext95, %vecext97
786  %vecinit101 = insertelement <16 x i16> %vecinit94, i16 %add99, i32 14
787  %vecext102 = extractelement <16 x i16> %b, i32 14
788  %vecext104 = extractelement <16 x i16> %b, i32 15
789  %add106 = add i16 %vecext102, %vecext104
790  %vecinit108 = insertelement <16 x i16> %vecinit101, i16 %add106, i32 15
791  ret <16 x i16> %vecinit108
792}
793; CHECK-LABEL: avx2_hadd_w
794; SSE3-NOT: phaddw
795; SSSE3: phaddw
796; SSSE3-NEXT: phaddw
797; AVX: vphaddw
798; AVX: vphaddw
799; AVX2: vphaddw
800; AVX2-NOT: vphaddw
801; CHECK: ret
802
803