blob: 954a9d994e61eb25f82edf31974812f6ca7140b3 [file] [log] [blame]
Andrea Di Biagio54b09492014-06-19 10:29:41 +00001; RUN: llc < %s -march=x86-64 -mcpu=corei7 -mattr=+ssse3 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE
2; RUN: llc < %s -march=x86-64 -mcpu=corei7-avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX
3; RUN: llc < %s -march=x86-64 -mcpu=core-avx2 | FileCheck %s -check-prefix=CHECK -check-prefix=AVX2
4
5; Verify that we correctly fold horizontal binop even in the presence of UNDEFs.
6
7define <4 x float> @test1_undef(<4 x float> %a, <4 x float> %b) {
8 %vecext = extractelement <4 x float> %a, i32 0
9 %vecext1 = extractelement <4 x float> %a, i32 1
10 %add = fadd float %vecext, %vecext1
11 %vecinit = insertelement <4 x float> undef, float %add, i32 0
12 %vecext2 = extractelement <4 x float> %a, i32 2
13 %vecext3 = extractelement <4 x float> %a, i32 3
14 %add4 = fadd float %vecext2, %vecext3
15 %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
16 %vecext10 = extractelement <4 x float> %b, i32 2
17 %vecext11 = extractelement <4 x float> %b, i32 3
18 %add12 = fadd float %vecext10, %vecext11
19 %vecinit13 = insertelement <4 x float> %vecinit5, float %add12, i32 3
20 ret <4 x float> %vecinit13
21}
22; CHECK-LABEL: test1_undef
23; SSE: haddps
24; AVX: vhaddps
25; AVX2: vhaddps
26; CHECK-NEXT: ret
27
28
29define <4 x float> @test2_undef(<4 x float> %a, <4 x float> %b) {
30 %vecext = extractelement <4 x float> %a, i32 0
31 %vecext1 = extractelement <4 x float> %a, i32 1
32 %add = fadd float %vecext, %vecext1
33 %vecinit = insertelement <4 x float> undef, float %add, i32 0
34 %vecext6 = extractelement <4 x float> %b, i32 0
35 %vecext7 = extractelement <4 x float> %b, i32 1
36 %add8 = fadd float %vecext6, %vecext7
37 %vecinit9 = insertelement <4 x float> %vecinit, float %add8, i32 2
38 %vecext10 = extractelement <4 x float> %b, i32 2
39 %vecext11 = extractelement <4 x float> %b, i32 3
40 %add12 = fadd float %vecext10, %vecext11
41 %vecinit13 = insertelement <4 x float> %vecinit9, float %add12, i32 3
42 ret <4 x float> %vecinit13
43}
44; CHECK-LABEL: test2_undef
45; SSE: haddps
46; AVX: vhaddps
47; AVX2: vhaddps
48; CHECK-NEXT: ret
49
50
51define <4 x float> @test3_undef(<4 x float> %a, <4 x float> %b) {
52 %vecext = extractelement <4 x float> %a, i32 0
53 %vecext1 = extractelement <4 x float> %a, i32 1
54 %add = fadd float %vecext, %vecext1
55 %vecinit = insertelement <4 x float> undef, float %add, i32 0
56 %vecext2 = extractelement <4 x float> %a, i32 2
57 %vecext3 = extractelement <4 x float> %a, i32 3
58 %add4 = fadd float %vecext2, %vecext3
59 %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
60 %vecext6 = extractelement <4 x float> %b, i32 0
61 %vecext7 = extractelement <4 x float> %b, i32 1
62 %add8 = fadd float %vecext6, %vecext7
63 %vecinit9 = insertelement <4 x float> %vecinit5, float %add8, i32 2
64 ret <4 x float> %vecinit9
65}
66; CHECK-LABEL: test3_undef
67; SSE: haddps
68; AVX: vhaddps
69; AVX2: vhaddps
70; CHECK-NEXT: ret
71
72
73define <4 x float> @test4_undef(<4 x float> %a, <4 x float> %b) {
74 %vecext = extractelement <4 x float> %a, i32 0
75 %vecext1 = extractelement <4 x float> %a, i32 1
76 %add = fadd float %vecext, %vecext1
77 %vecinit = insertelement <4 x float> undef, float %add, i32 0
78 ret <4 x float> %vecinit
79}
80; CHECK-LABEL: test4_undef
81; CHECK-NOT: haddps
82; CHECK: ret
83
84
85define <2 x double> @test5_undef(<2 x double> %a, <2 x double> %b) {
86 %vecext = extractelement <2 x double> %a, i32 0
87 %vecext1 = extractelement <2 x double> %a, i32 1
88 %add = fadd double %vecext, %vecext1
89 %vecinit = insertelement <2 x double> undef, double %add, i32 0
90 ret <2 x double> %vecinit
91}
92; CHECK-LABEL: test5_undef
93; CHECK-NOT: haddpd
94; CHECK: ret
95
96
97define <4 x float> @test6_undef(<4 x float> %a, <4 x float> %b) {
98 %vecext = extractelement <4 x float> %a, i32 0
99 %vecext1 = extractelement <4 x float> %a, i32 1
100 %add = fadd float %vecext, %vecext1
101 %vecinit = insertelement <4 x float> undef, float %add, i32 0
102 %vecext2 = extractelement <4 x float> %a, i32 2
103 %vecext3 = extractelement <4 x float> %a, i32 3
104 %add4 = fadd float %vecext2, %vecext3
105 %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 1
106 ret <4 x float> %vecinit5
107}
108; CHECK-LABEL: test6_undef
109; SSE: haddps
110; AVX: vhaddps
111; AVX2: vhaddps
112; CHECK-NEXT: ret
113
114
115define <4 x float> @test7_undef(<4 x float> %a, <4 x float> %b) {
116 %vecext = extractelement <4 x float> %b, i32 0
117 %vecext1 = extractelement <4 x float> %b, i32 1
118 %add = fadd float %vecext, %vecext1
119 %vecinit = insertelement <4 x float> undef, float %add, i32 2
120 %vecext2 = extractelement <4 x float> %b, i32 2
121 %vecext3 = extractelement <4 x float> %b, i32 3
122 %add4 = fadd float %vecext2, %vecext3
123 %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 3
124 ret <4 x float> %vecinit5
125}
126; CHECK-LABEL: test7_undef
127; SSE: haddps
128; AVX: vhaddps
129; AVX2: vhaddps
130; CHECK-NEXT: ret
131
132
133define <4 x float> @test8_undef(<4 x float> %a, <4 x float> %b) {
134 %vecext = extractelement <4 x float> %a, i32 0
135 %vecext1 = extractelement <4 x float> %a, i32 1
136 %add = fadd float %vecext, %vecext1
137 %vecinit = insertelement <4 x float> undef, float %add, i32 0
138 %vecext2 = extractelement <4 x float> %a, i32 2
139 %vecext3 = extractelement <4 x float> %a, i32 3
140 %add4 = fadd float %vecext2, %vecext3
141 %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 2
142 ret <4 x float> %vecinit5
143}
144; CHECK-LABEL: test8_undef
145; CHECK-NOT: haddps
146; CHECK: ret
147
148
149define <4 x float> @test9_undef(<4 x float> %a, <4 x float> %b) {
150 %vecext = extractelement <4 x float> %a, i32 0
151 %vecext1 = extractelement <4 x float> %a, i32 1
152 %add = fadd float %vecext, %vecext1
153 %vecinit = insertelement <4 x float> undef, float %add, i32 0
154 %vecext2 = extractelement <4 x float> %b, i32 2
155 %vecext3 = extractelement <4 x float> %b, i32 3
156 %add4 = fadd float %vecext2, %vecext3
157 %vecinit5 = insertelement <4 x float> %vecinit, float %add4, i32 3
158 ret <4 x float> %vecinit5
159}
160; CHECK-LABEL: test9_undef
161; CHECK: haddps
162; CHECK-NEXT: ret
163
164define <8 x float> @test10_undef(<8 x float> %a, <8 x float> %b) {
165 %vecext = extractelement <8 x float> %a, i32 0
166 %vecext1 = extractelement <8 x float> %a, i32 1
167 %add = fadd float %vecext, %vecext1
168 %vecinit = insertelement <8 x float> undef, float %add, i32 0
169 %vecext2 = extractelement <8 x float> %b, i32 2
170 %vecext3 = extractelement <8 x float> %b, i32 3
171 %add4 = fadd float %vecext2, %vecext3
172 %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 3
173 ret <8 x float> %vecinit5
174}
175; CHECK-LABEL: test10_undef
176; SSE: haddps
177; AVX: vhaddps
178; AVX2: vhaddps
179; CHECK-NOT: haddps
180; CHECK: ret
181
182define <8 x float> @test11_undef(<8 x float> %a, <8 x float> %b) {
183 %vecext = extractelement <8 x float> %a, i32 0
184 %vecext1 = extractelement <8 x float> %a, i32 1
185 %add = fadd float %vecext, %vecext1
186 %vecinit = insertelement <8 x float> undef, float %add, i32 0
187 %vecext2 = extractelement <8 x float> %b, i32 4
188 %vecext3 = extractelement <8 x float> %b, i32 5
189 %add4 = fadd float %vecext2, %vecext3
190 %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 6
191 ret <8 x float> %vecinit5
192}
193; CHECK-LABEL: test11_undef
194; SSE-NOT: haddps
195; AVX: vhaddps
196; AVX2: vhaddps
197; CHECK: ret
198
199define <8 x float> @test12_undef(<8 x float> %a, <8 x float> %b) {
200 %vecext = extractelement <8 x float> %a, i32 0
201 %vecext1 = extractelement <8 x float> %a, i32 1
202 %add = fadd float %vecext, %vecext1
203 %vecinit = insertelement <8 x float> undef, float %add, i32 0
204 %vecext2 = extractelement <8 x float> %a, i32 2
205 %vecext3 = extractelement <8 x float> %a, i32 3
206 %add4 = fadd float %vecext2, %vecext3
207 %vecinit5 = insertelement <8 x float> %vecinit, float %add4, i32 1
208 ret <8 x float> %vecinit5
209}
210; CHECK-LABEL: test12_undef
211; SSE: haddps
212; AVX: vhaddps
213; AVX2: vhaddps
214; CHECK-NOT: haddps
215; CHECK: ret
216
217define <8 x float> @test13_undef(<8 x float> %a, <8 x float> %b) {
218 %vecext = extractelement <8 x float> %a, i32 0
219 %vecext1 = extractelement <8 x float> %a, i32 1
220 %add1 = fadd float %vecext, %vecext1
221 %vecinit1 = insertelement <8 x float> undef, float %add1, i32 0
222 %vecext2 = extractelement <8 x float> %a, i32 2
223 %vecext3 = extractelement <8 x float> %a, i32 3
224 %add2 = fadd float %vecext2, %vecext3
225 %vecinit2 = insertelement <8 x float> %vecinit1, float %add2, i32 1
226 %vecext4 = extractelement <8 x float> %a, i32 4
227 %vecext5 = extractelement <8 x float> %a, i32 5
228 %add3 = fadd float %vecext4, %vecext5
229 %vecinit3 = insertelement <8 x float> %vecinit2, float %add3, i32 2
230 %vecext6 = extractelement <8 x float> %a, i32 6
231 %vecext7 = extractelement <8 x float> %a, i32 7
232 %add4 = fadd float %vecext6, %vecext7
233 %vecinit4 = insertelement <8 x float> %vecinit3, float %add4, i32 3
234 ret <8 x float> %vecinit4
235}
236; CHECK-LABEL: test13_undef
237; SSE: haddps
238; SSE-NOT: haddps
239; AVX: vhaddps
240; AVX2: vhaddps
241; CHECK-NOT: haddps
242; CHECK: ret
243
244define <8 x i32> @test14_undef(<8 x i32> %a, <8 x i32> %b) {
245 %vecext = extractelement <8 x i32> %a, i32 0
246 %vecext1 = extractelement <8 x i32> %a, i32 1
247 %add = add i32 %vecext, %vecext1
248 %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
249 %vecext2 = extractelement <8 x i32> %b, i32 2
250 %vecext3 = extractelement <8 x i32> %b, i32 3
251 %add4 = add i32 %vecext2, %vecext3
252 %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 3
253 ret <8 x i32> %vecinit5
254}
255; CHECK-LABEL: test14_undef
256; SSE: phaddd
257; AVX: vphaddd
258; AVX2: vphaddd
259; CHECK-NOT: phaddd
260; CHECK: ret
261
262; On AVX2, the following sequence can be folded into a single horizontal add.
263; If the Subtarget doesn't support AVX2, then we avoid emitting two packed
264; integer horizontal adds instead of two scalar adds followed by vector inserts.
265define <8 x i32> @test15_undef(<8 x i32> %a, <8 x i32> %b) {
266 %vecext = extractelement <8 x i32> %a, i32 0
267 %vecext1 = extractelement <8 x i32> %a, i32 1
268 %add = add i32 %vecext, %vecext1
269 %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
270 %vecext2 = extractelement <8 x i32> %b, i32 4
271 %vecext3 = extractelement <8 x i32> %b, i32 5
272 %add4 = add i32 %vecext2, %vecext3
273 %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 6
274 ret <8 x i32> %vecinit5
275}
276; CHECK-LABEL: test15_undef
277; SSE-NOT: phaddd
278; AVX-NOT: vphaddd
279; AVX2: vphaddd
280; CHECK: ret
281
282define <8 x i32> @test16_undef(<8 x i32> %a, <8 x i32> %b) {
283 %vecext = extractelement <8 x i32> %a, i32 0
284 %vecext1 = extractelement <8 x i32> %a, i32 1
285 %add = add i32 %vecext, %vecext1
286 %vecinit = insertelement <8 x i32> undef, i32 %add, i32 0
287 %vecext2 = extractelement <8 x i32> %a, i32 2
288 %vecext3 = extractelement <8 x i32> %a, i32 3
289 %add4 = add i32 %vecext2, %vecext3
290 %vecinit5 = insertelement <8 x i32> %vecinit, i32 %add4, i32 1
291 ret <8 x i32> %vecinit5
292}
293; CHECK-LABEL: test16_undef
294; SSE: phaddd
295; AVX: vphaddd
296; AVX2: vphaddd
297; CHECK-NOT: haddps
298; CHECK: ret
299
300define <8 x i32> @test17_undef(<8 x i32> %a, <8 x i32> %b) {
301 %vecext = extractelement <8 x i32> %a, i32 0
302 %vecext1 = extractelement <8 x i32> %a, i32 1
303 %add1 = add i32 %vecext, %vecext1
304 %vecinit1 = insertelement <8 x i32> undef, i32 %add1, i32 0
305 %vecext2 = extractelement <8 x i32> %a, i32 2
306 %vecext3 = extractelement <8 x i32> %a, i32 3
307 %add2 = add i32 %vecext2, %vecext3
308 %vecinit2 = insertelement <8 x i32> %vecinit1, i32 %add2, i32 1
309 %vecext4 = extractelement <8 x i32> %a, i32 4
310 %vecext5 = extractelement <8 x i32> %a, i32 5
311 %add3 = add i32 %vecext4, %vecext5
312 %vecinit3 = insertelement <8 x i32> %vecinit2, i32 %add3, i32 2
313 %vecext6 = extractelement <8 x i32> %a, i32 6
314 %vecext7 = extractelement <8 x i32> %a, i32 7
315 %add4 = add i32 %vecext6, %vecext7
316 %vecinit4 = insertelement <8 x i32> %vecinit3, i32 %add4, i32 3
317 ret <8 x i32> %vecinit4
318}
319; CHECK-LABEL: test17_undef
320; SSE: phaddd
321; AVX: vphaddd
322; AVX2: vphaddd
323; CHECK-NOT: haddps
324; CHECK: ret
325