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
5 ; Verify that we correctly generate 'addsub' instructions from
6 ; a sequence of vector extracts + float add/sub + vector inserts.
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
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
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
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
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
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
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
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
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
213 ; Verify that we don't generate addsub instruction for the following
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
222 ; CHECK-LABEL: test10
223 ; CHECK-NOT: addsubps
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
234 ; CHECK-LABEL: test11
235 ; CHECK-NOT: addsubps
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
246 ; CHECK-LABEL: test12
247 ; CHECK-NOT: addsubps
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
258 ; CHECK-LABEL: test13
259 ; CHECK-NOT: addsubps
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
274 ; CHECK-LABEL: test14
275 ; CHECK-NOT: addsubps
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
290 ; CHECK-LABEL: test15
291 ; CHECK-NOT: addsubps
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
314 ; CHECK-LABEL: test16
315 ; CHECK-NOT: addsubps
318 define <2 x float> @test_v2f32(<2 x float> %v0, <2 x float> %v1) {
319 %v2 = extractelement <2 x float> %v0, i32 0
320 %v3 = extractelement <2 x float> %v1, i32 0
321 %v4 = extractelement <2 x float> %v0, i32 1
322 %v5 = extractelement <2 x float> %v1, i32 1
323 %sub = fsub float %v2, %v3
324 %add = fadd float %v5, %v4
325 %res0 = insertelement <2 x float> undef, float %sub, i32 0
326 %res1 = insertelement <2 x float> %res0, float %add, i32 1
327 ret <2 x float> %res1
329 ; CHECK-LABEL: test_v2f32
330 ; CHECK: addsubps %xmm1, %xmm0