1 ; 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
5 ; Verify that we correctly fold horizontal binop even in the presence of UNDEFs.
7 define <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
22 ; CHECK-LABEL: test1_undef
29 define <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
44 ; CHECK-LABEL: test2_undef
51 define <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
66 ; CHECK-LABEL: test3_undef
73 define <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
80 ; CHECK-LABEL: test4_undef
85 define <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
92 ; CHECK-LABEL: test5_undef
97 define <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
108 ; CHECK-LABEL: test6_undef
115 define <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
126 ; CHECK-LABEL: test7_undef
133 define <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
144 ; CHECK-LABEL: test8_undef
149 define <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
160 ; CHECK-LABEL: test9_undef
164 define <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
175 ; CHECK-LABEL: test10_undef
182 define <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
193 ; CHECK-LABEL: test11_undef
199 define <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
210 ; CHECK-LABEL: test12_undef
217 define <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
236 ; CHECK-LABEL: test13_undef
244 define <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
255 ; CHECK-LABEL: test14_undef
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.
265 define <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
276 ; CHECK-LABEL: test15_undef
282 define <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
293 ; CHECK-LABEL: test16_undef
300 define <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
319 ; CHECK-LABEL: test17_undef