[x86] Factor out the zero vector insertion logic in the new vector
[oota-llvm.git] / test / CodeGen / X86 / sse3-avx-addsub-2.ll
1 ; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 | 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
8 define <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
33 define <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
50 define <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
67 define <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
84 define <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
101 define <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
126 define <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
153 define <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
170 define <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.
215 define <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
227 define <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
239 define <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
251 define <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
263 define <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
279 define <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
295 define <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