1; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -mcpu=core2 | FileCheck %s -check-prefix=CHECK -check-prefix=SSE
2; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7-avx | FileCheck %s -check-prefix=CHECK -check-prefix=AVX
3
4
5; Verify that we correctly generate 'addsub' instructions from
6; a sequence of vector extracts + float add/sub + vector inserts.
7
8define <4 x float> @test1(<4 x float> %A, <4 x float> %B) {
9  %1 = extractelement <4 x float> %A, i32 0
10  %2 = extractelement <4 x float> %B, i32 0
11  %sub = fsub float %1, %2
12  %3 = extractelement <4 x float> %A, i32 2
13  %4 = extractelement <4 x float> %B, i32 2
14  %sub2 = fsub float %3, %4
15  %5 = extractelement <4 x float> %A, i32 1
16  %6 = extractelement <4 x float> %B, i32 1
17  %add = fadd float %5, %6
18  %7 = extractelement <4 x float> %A, i32 3
19  %8 = extractelement <4 x float> %B, i32 3
20  %add2 = fadd float %7, %8
21  %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1
22  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3
23  %vecinsert3 = insertelement <4 x float> %vecinsert2, float %sub, i32 0
24  %vecinsert4 = insertelement <4 x float> %vecinsert3, float %sub2, i32 2
25  ret <4 x float> %vecinsert4
26}
27; CHECK-LABEL: test1
28; SSE: addsubps
29; AVX: vaddsubps
30; CHECK-NEXT: ret
31
32
33define <4 x float> @test2(<4 x float> %A, <4 x float> %B) {
34  %1 = extractelement <4 x float> %A, i32 2
35  %2 = extractelement <4 x float> %B, i32 2
36  %sub2 = fsub float %1, %2
37  %3 = extractelement <4 x float> %A, i32 3
38  %4 = extractelement <4 x float> %B, i32 3
39  %add2 = fadd float %3, %4
40  %vecinsert1 = insertelement <4 x float> undef, float %sub2, i32 2
41  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3
42  ret <4 x float> %vecinsert2
43}
44; CHECK-LABEL: test2
45; SSE: addsubps
46; AVX: vaddsubps
47; CHECK-NEXT: ret
48
49
50define <4 x float> @test3(<4 x float> %A, <4 x float> %B) {
51  %1 = extractelement <4 x float> %A, i32 0
52  %2 = extractelement <4 x float> %B, i32 0
53  %sub = fsub float %1, %2
54  %3 = extractelement <4 x float> %A, i32 3
55  %4 = extractelement <4 x float> %B, i32 3
56  %add = fadd float %4, %3
57  %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 0
58  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add, i32 3
59  ret <4 x float> %vecinsert2
60}
61; CHECK-LABEL: test3
62; SSE: addsubps
63; AVX: vaddsubps
64; CHECK-NEXT: ret
65
66
67define <4 x float> @test4(<4 x float> %A, <4 x float> %B) {
68  %1 = extractelement <4 x float> %A, i32 2
69  %2 = extractelement <4 x float> %B, i32 2
70  %sub = fsub float %1, %2
71  %3 = extractelement <4 x float> %A, i32 1
72  %4 = extractelement <4 x float> %B, i32 1
73  %add = fadd float %3, %4
74  %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 2
75  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add, i32 1
76  ret <4 x float> %vecinsert2
77}
78; CHECK-LABEL: test4
79; SSE: addsubps
80; AVX: vaddsubps
81; CHECK-NEXT: ret
82
83
84define <4 x float> @test5(<4 x float> %A, <4 x float> %B) {
85  %1 = extractelement <4 x float> %A, i32 0
86  %2 = extractelement <4 x float> %B, i32 0
87  %sub2 = fsub float %1, %2
88  %3 = extractelement <4 x float> %A, i32 1
89  %4 = extractelement <4 x float> %B, i32 1
90  %add2 = fadd float %3, %4
91  %vecinsert1 = insertelement <4 x float> undef, float %sub2, i32 0
92  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 1
93  ret <4 x float> %vecinsert2
94}
95; CHECK-LABEL: test5
96; SSE: addsubps
97; AVX: vaddsubps
98; CHECK-NEXT: ret
99
100
101define <4 x float> @test6(<4 x float> %A, <4 x float> %B) {
102  %1 = extractelement <4 x float> %A, i32 0
103  %2 = extractelement <4 x float> %B, i32 0
104  %sub = fsub float %1, %2
105  %3 = extractelement <4 x float> %A, i32 2
106  %4 = extractelement <4 x float> %B, i32 2
107  %sub2 = fsub float %3, %4
108  %5 = extractelement <4 x float> %A, i32 1
109  %6 = extractelement <4 x float> %B, i32 1
110  %add = fadd float %5, %6
111  %7 = extractelement <4 x float> %A, i32 3
112  %8 = extractelement <4 x float> %B, i32 3
113  %add2 = fadd float %7, %8
114  %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1
115  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3
116  %vecinsert3 = insertelement <4 x float> %vecinsert2, float %sub, i32 0
117  %vecinsert4 = insertelement <4 x float> %vecinsert3, float %sub2, i32 2
118  ret <4 x float> %vecinsert4
119}
120; CHECK-LABEL: test6
121; SSE: addsubps
122; AVX: vaddsubps
123; CHECK-NEXT: ret
124
125
126define <4 x double> @test7(<4 x double> %A, <4 x double> %B) {
127  %1 = extractelement <4 x double> %A, i32 0
128  %2 = extractelement <4 x double> %B, i32 0
129  %sub = fsub double %1, %2
130  %3 = extractelement <4 x double> %A, i32 2
131  %4 = extractelement <4 x double> %B, i32 2
132  %sub2 = fsub double %3, %4
133  %5 = extractelement <4 x double> %A, i32 1
134  %6 = extractelement <4 x double> %B, i32 1
135  %add = fadd double %5, %6
136  %7 = extractelement <4 x double> %A, i32 3
137  %8 = extractelement <4 x double> %B, i32 3
138  %add2 = fadd double %7, %8
139  %vecinsert1 = insertelement <4 x double> undef, double %add, i32 1
140  %vecinsert2 = insertelement <4 x double> %vecinsert1, double %add2, i32 3
141  %vecinsert3 = insertelement <4 x double> %vecinsert2, double %sub, i32 0
142  %vecinsert4 = insertelement <4 x double> %vecinsert3, double %sub2, i32 2
143  ret <4 x double> %vecinsert4
144}
145; CHECK-LABEL: test7
146; SSE: addsubpd
147; SSE-NEXT: addsubpd
148; AVX: vaddsubpd
149; AVX-NOT: vaddsubpd
150; CHECK: ret
151
152
153define <2 x double> @test8(<2 x double> %A, <2 x double> %B) {
154  %1 = extractelement <2 x double> %A, i32 0
155  %2 = extractelement <2 x double> %B, i32 0
156  %sub = fsub double %1, %2
157  %3 = extractelement <2 x double> %A, i32 1
158  %4 = extractelement <2 x double> %B, i32 1
159  %add = fadd double %3, %4
160  %vecinsert1 = insertelement <2 x double> undef, double %sub, i32 0
161  %vecinsert2 = insertelement <2 x double> %vecinsert1, double %add, i32 1
162  ret <2 x double> %vecinsert2
163}
164; CHECK-LABEL: test8
165; SSE: addsubpd
166; AVX: vaddsubpd
167; CHECK: ret
168
169
170define <8 x float> @test9(<8 x float> %A, <8 x float> %B) {
171  %1 = extractelement <8 x float> %A, i32 0
172  %2 = extractelement <8 x float> %B, i32 0
173  %sub = fsub float %1, %2
174  %3 = extractelement <8 x float> %A, i32 2
175  %4 = extractelement <8 x float> %B, i32 2
176  %sub2 = fsub float %3, %4
177  %5 = extractelement <8 x float> %A, i32 1
178  %6 = extractelement <8 x float> %B, i32 1
179  %add = fadd float %5, %6
180  %7 = extractelement <8 x float> %A, i32 3
181  %8 = extractelement <8 x float> %B, i32 3
182  %add2 = fadd float %7, %8
183  %9 = extractelement <8 x float> %A, i32 4
184  %10 = extractelement <8 x float> %B, i32 4
185  %sub3 = fsub float %9, %10
186  %11 = extractelement <8 x float> %A, i32 6
187  %12 = extractelement <8 x float> %B, i32 6
188  %sub4 = fsub float %11, %12
189  %13 = extractelement <8 x float> %A, i32 5
190  %14 = extractelement <8 x float> %B, i32 5
191  %add3 = fadd float %13, %14
192  %15 = extractelement <8 x float> %A, i32 7
193  %16 = extractelement <8 x float> %B, i32 7
194  %add4 = fadd float %15, %16
195  %vecinsert1 = insertelement <8 x float> undef, float %add, i32 1
196  %vecinsert2 = insertelement <8 x float> %vecinsert1, float %add2, i32 3
197  %vecinsert3 = insertelement <8 x float> %vecinsert2, float %sub, i32 0
198  %vecinsert4 = insertelement <8 x float> %vecinsert3, float %sub2, i32 2
199  %vecinsert5 = insertelement <8 x float> %vecinsert4, float %add3, i32 5
200  %vecinsert6 = insertelement <8 x float> %vecinsert5, float %add4, i32 7
201  %vecinsert7 = insertelement <8 x float> %vecinsert6, float %sub3, i32 4
202  %vecinsert8 = insertelement <8 x float> %vecinsert7, float %sub4, i32 6
203  ret <8 x float> %vecinsert8
204}
205; CHECK-LABEL: test9
206; SSE: addsubps
207; SSE-NEXT: addsubps
208; AVX: vaddsubps
209; AVX-NOT: vaddsubps
210; CHECK: ret
211
212
213; Verify that we don't generate addsub instruction for the following
214; functions.
215define <4 x float> @test10(<4 x float> %A, <4 x float> %B) {
216  %1 = extractelement <4 x float> %A, i32 0
217  %2 = extractelement <4 x float> %B, i32 0
218  %sub = fsub float %1, %2
219  %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 0
220  ret <4 x float> %vecinsert1
221}
222; CHECK-LABEL: test10
223; CHECK-NOT: addsubps
224; CHECK: ret
225
226
227define <4 x float> @test11(<4 x float> %A, <4 x float> %B) {
228  %1 = extractelement <4 x float> %A, i32 2
229  %2 = extractelement <4 x float> %B, i32 2
230  %sub = fsub float %1, %2
231  %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 2
232  ret <4 x float> %vecinsert1
233}
234; CHECK-LABEL: test11
235; CHECK-NOT: addsubps
236; CHECK: ret
237
238
239define <4 x float> @test12(<4 x float> %A, <4 x float> %B) {
240  %1 = extractelement <4 x float> %A, i32 1
241  %2 = extractelement <4 x float> %B, i32 1
242  %add = fadd float %1, %2
243  %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1
244  ret <4 x float> %vecinsert1
245}
246; CHECK-LABEL: test12
247; CHECK-NOT: addsubps
248; CHECK: ret
249
250
251define <4 x float> @test13(<4 x float> %A, <4 x float> %B) {
252  %1 = extractelement <4 x float> %A, i32 3
253  %2 = extractelement <4 x float> %B, i32 3
254  %add = fadd float %1, %2
255  %vecinsert1 = insertelement <4 x float> undef, float %add, i32 3
256  ret <4 x float> %vecinsert1
257}
258; CHECK-LABEL: test13
259; CHECK-NOT: addsubps
260; CHECK: ret
261
262
263define <4 x float> @test14(<4 x float> %A, <4 x float> %B) {
264  %1 = extractelement <4 x float> %A, i32 0
265  %2 = extractelement <4 x float> %B, i32 0
266  %sub = fsub float %1, %2
267  %3 = extractelement <4 x float> %A, i32 2
268  %4 = extractelement <4 x float> %B, i32 2
269  %sub2 = fsub float %3, %4
270  %vecinsert1 = insertelement <4 x float> undef, float %sub, i32 0
271  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %sub2, i32 2
272  ret <4 x float> %vecinsert2
273}
274; CHECK-LABEL: test14
275; CHECK-NOT: addsubps
276; CHECK: ret
277
278
279define <4 x float> @test15(<4 x float> %A, <4 x float> %B) {
280  %1 = extractelement <4 x float> %A, i32 1
281  %2 = extractelement <4 x float> %B, i32 1
282  %add = fadd float %1, %2
283  %3 = extractelement <4 x float> %A, i32 3
284  %4 = extractelement <4 x float> %B, i32 3
285  %add2 = fadd float %3, %4
286  %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1
287  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3
288  ret <4 x float> %vecinsert2
289}
290; CHECK-LABEL: test15
291; CHECK-NOT: addsubps
292; CHECK: ret
293
294
295define <4 x float> @test16(<4 x float> %A, <4 x float> %B) {
296  %1 = extractelement <4 x float> %A, i32 0
297  %2 = extractelement <4 x float> %B, i32 0
298  %sub = fsub float %1, undef
299  %3 = extractelement <4 x float> %A, i32 2
300  %4 = extractelement <4 x float> %B, i32 2
301  %sub2 = fsub float %3, %4
302  %5 = extractelement <4 x float> %A, i32 1
303  %6 = extractelement <4 x float> %B, i32 1
304  %add = fadd float %5, undef
305  %7 = extractelement <4 x float> %A, i32 3
306  %8 = extractelement <4 x float> %B, i32 3
307  %add2 = fadd float %7, %8
308  %vecinsert1 = insertelement <4 x float> undef, float %add, i32 1
309  %vecinsert2 = insertelement <4 x float> %vecinsert1, float %add2, i32 3
310  %vecinsert3 = insertelement <4 x float> %vecinsert2, float %sub, i32 0
311  %vecinsert4 = insertelement <4 x float> %vecinsert3, float %sub2, i32 2
312  ret <4 x float> %vecinsert4
313}
314; CHECK-LABEL: test16
315; CHECK-NOT: addsubps
316; CHECK: ret
317
318
319