[ARM] Adjust how NEON shifts are lowered
[llvm-core.git] / test / CodeGen / X86 / combine-add.ll
blob1d20fcf33d7427cdd834eaf81752516851d9cf11
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.1 | FileCheck %s --check-prefix=SSE
3 ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefix=AVX
5 ; fold (add x, 0) -> x
6 define <4 x i32> @combine_vec_add_to_zero(<4 x i32> %a) {
7 ; SSE-LABEL: combine_vec_add_to_zero:
8 ; SSE:       # %bb.0:
9 ; SSE-NEXT:    retq
11 ; AVX-LABEL: combine_vec_add_to_zero:
12 ; AVX:       # %bb.0:
13 ; AVX-NEXT:    retq
14   %1 = add <4 x i32> %a, zeroinitializer
15   ret <4 x i32> %1
18 ; fold ((c1-A)+c2) -> (c1+c2)-A
19 define <4 x i32> @combine_vec_add_constant_sub(<4 x i32> %a) {
20 ; SSE-LABEL: combine_vec_add_constant_sub:
21 ; SSE:       # %bb.0:
22 ; SSE-NEXT:    movdqa {{.*#+}} xmm1 = [0,2,4,6]
23 ; SSE-NEXT:    psubd %xmm0, %xmm1
24 ; SSE-NEXT:    movdqa %xmm1, %xmm0
25 ; SSE-NEXT:    retq
27 ; AVX-LABEL: combine_vec_add_constant_sub:
28 ; AVX:       # %bb.0:
29 ; AVX-NEXT:    vmovdqa {{.*#+}} xmm1 = [0,2,4,6]
30 ; AVX-NEXT:    vpsubd %xmm0, %xmm1, %xmm0
31 ; AVX-NEXT:    retq
32   %1 = sub <4 x i32> <i32 0, i32 1, i32 2, i32 3>, %a
33   %2 = add <4 x i32> <i32 0, i32 1, i32 2, i32 3>, %1
34   ret <4 x i32> %2
37 ; fold ((0-A) + B) -> B-A
38 define <4 x i32> @combine_vec_add_neg0(<4 x i32> %a, <4 x i32> %b) {
39 ; SSE-LABEL: combine_vec_add_neg0:
40 ; SSE:       # %bb.0:
41 ; SSE-NEXT:    psubd %xmm0, %xmm1
42 ; SSE-NEXT:    movdqa %xmm1, %xmm0
43 ; SSE-NEXT:    retq
45 ; AVX-LABEL: combine_vec_add_neg0:
46 ; AVX:       # %bb.0:
47 ; AVX-NEXT:    vpsubd %xmm0, %xmm1, %xmm0
48 ; AVX-NEXT:    retq
49   %1 = sub <4 x i32> zeroinitializer, %a
50   %2 = add <4 x i32> %1, %b
51   ret <4 x i32> %2
54 ; fold (A + (0-B)) -> A-B
55 define <4 x i32> @combine_vec_add_neg1(<4 x i32> %a, <4 x i32> %b) {
56 ; SSE-LABEL: combine_vec_add_neg1:
57 ; SSE:       # %bb.0:
58 ; SSE-NEXT:    psubd %xmm1, %xmm0
59 ; SSE-NEXT:    retq
61 ; AVX-LABEL: combine_vec_add_neg1:
62 ; AVX:       # %bb.0:
63 ; AVX-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
64 ; AVX-NEXT:    retq
65   %1 = sub <4 x i32> zeroinitializer, %b
66   %2 = add <4 x i32> %a, %1
67   ret <4 x i32> %2
70 ; fold (A+(B-A)) -> B
71 define <4 x i32> @combine_vec_add_sub0(<4 x i32> %a, <4 x i32> %b) {
72 ; SSE-LABEL: combine_vec_add_sub0:
73 ; SSE:       # %bb.0:
74 ; SSE-NEXT:    movaps %xmm1, %xmm0
75 ; SSE-NEXT:    retq
77 ; AVX-LABEL: combine_vec_add_sub0:
78 ; AVX:       # %bb.0:
79 ; AVX-NEXT:    vmovaps %xmm1, %xmm0
80 ; AVX-NEXT:    retq
81   %1 = sub <4 x i32> %b, %a
82   %2 = add <4 x i32> %a, %1
83   ret <4 x i32> %2
86 ; fold ((B-A)+A) -> B
87 define <4 x i32> @combine_vec_add_sub1(<4 x i32> %a, <4 x i32> %b) {
88 ; SSE-LABEL: combine_vec_add_sub1:
89 ; SSE:       # %bb.0:
90 ; SSE-NEXT:    movaps %xmm1, %xmm0
91 ; SSE-NEXT:    retq
93 ; AVX-LABEL: combine_vec_add_sub1:
94 ; AVX:       # %bb.0:
95 ; AVX-NEXT:    vmovaps %xmm1, %xmm0
96 ; AVX-NEXT:    retq
97   %1 = sub <4 x i32> %b, %a
98   %2 = add <4 x i32> %1, %a
99   ret <4 x i32> %2
102 ; fold ((A-B)+(C-A)) -> (C-B)
103 define <4 x i32> @combine_vec_add_sub_sub0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
104 ; SSE-LABEL: combine_vec_add_sub_sub0:
105 ; SSE:       # %bb.0:
106 ; SSE-NEXT:    movdqa %xmm2, %xmm0
107 ; SSE-NEXT:    psubd %xmm1, %xmm0
108 ; SSE-NEXT:    retq
110 ; AVX-LABEL: combine_vec_add_sub_sub0:
111 ; AVX:       # %bb.0:
112 ; AVX-NEXT:    vpsubd %xmm1, %xmm2, %xmm0
113 ; AVX-NEXT:    retq
114   %1 = sub <4 x i32> %a, %b
115   %2 = sub <4 x i32> %c, %a
116   %3 = add <4 x i32> %1, %2
117   ret <4 x i32> %3
120 ; fold ((A-B)+(B-C)) -> (A-C)
121 define <4 x i32> @combine_vec_add_sub_sub1(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
122 ; SSE-LABEL: combine_vec_add_sub_sub1:
123 ; SSE:       # %bb.0:
124 ; SSE-NEXT:    psubd %xmm2, %xmm0
125 ; SSE-NEXT:    retq
127 ; AVX-LABEL: combine_vec_add_sub_sub1:
128 ; AVX:       # %bb.0:
129 ; AVX-NEXT:    vpsubd %xmm2, %xmm0, %xmm0
130 ; AVX-NEXT:    retq
131   %1 = sub <4 x i32> %a, %b
132   %2 = sub <4 x i32> %b, %c
133   %3 = add <4 x i32> %1, %2
134   ret <4 x i32> %3
137 ; fold (A+(B-(A+C))) to (B-C)
138 define <4 x i32> @combine_vec_add_sub_add0(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
139 ; SSE-LABEL: combine_vec_add_sub_add0:
140 ; SSE:       # %bb.0:
141 ; SSE-NEXT:    movdqa %xmm1, %xmm0
142 ; SSE-NEXT:    psubd %xmm2, %xmm0
143 ; SSE-NEXT:    retq
145 ; AVX-LABEL: combine_vec_add_sub_add0:
146 ; AVX:       # %bb.0:
147 ; AVX-NEXT:    vpsubd %xmm2, %xmm1, %xmm0
148 ; AVX-NEXT:    retq
149   %1 = add <4 x i32> %a, %c
150   %2 = sub <4 x i32> %b, %1
151   %3 = add <4 x i32> %a, %2
152   ret <4 x i32> %3
155 ; fold (A+(B-(C+A))) to (B-C)
156 define <4 x i32> @combine_vec_add_sub_add1(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
157 ; SSE-LABEL: combine_vec_add_sub_add1:
158 ; SSE:       # %bb.0:
159 ; SSE-NEXT:    movdqa %xmm1, %xmm0
160 ; SSE-NEXT:    psubd %xmm2, %xmm0
161 ; SSE-NEXT:    retq
163 ; AVX-LABEL: combine_vec_add_sub_add1:
164 ; AVX:       # %bb.0:
165 ; AVX-NEXT:    vpsubd %xmm2, %xmm1, %xmm0
166 ; AVX-NEXT:    retq
167   %1 = add <4 x i32> %c, %a
168   %2 = sub <4 x i32> %b, %1
169   %3 = add <4 x i32> %a, %2
170   ret <4 x i32> %3
173 ; fold (A+((B-A)+C)) to (B+C)
174 define <4 x i32> @combine_vec_add_sub_add2(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
175 ; SSE-LABEL: combine_vec_add_sub_add2:
176 ; SSE:       # %bb.0:
177 ; SSE-NEXT:    movdqa %xmm1, %xmm0
178 ; SSE-NEXT:    paddd %xmm2, %xmm0
179 ; SSE-NEXT:    retq
181 ; AVX-LABEL: combine_vec_add_sub_add2:
182 ; AVX:       # %bb.0:
183 ; AVX-NEXT:    vpaddd %xmm2, %xmm1, %xmm0
184 ; AVX-NEXT:    retq
185   %1 = sub <4 x i32> %b, %a
186   %2 = add <4 x i32> %1, %c
187   %3 = add <4 x i32> %a, %2
188   ret <4 x i32> %3
191 ; fold (A+((B-A)-C)) to (B-C)
192 define <4 x i32> @combine_vec_add_sub_add3(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
193 ; SSE-LABEL: combine_vec_add_sub_add3:
194 ; SSE:       # %bb.0:
195 ; SSE-NEXT:    movdqa %xmm1, %xmm0
196 ; SSE-NEXT:    psubd %xmm2, %xmm0
197 ; SSE-NEXT:    retq
199 ; AVX-LABEL: combine_vec_add_sub_add3:
200 ; AVX:       # %bb.0:
201 ; AVX-NEXT:    vpsubd %xmm2, %xmm1, %xmm0
202 ; AVX-NEXT:    retq
203   %1 = sub <4 x i32> %b, %a
204   %2 = sub <4 x i32> %1, %c
205   %3 = add <4 x i32> %a, %2
206   ret <4 x i32> %3
209 ; fold (A-B)+(C-D) to (A+C)-(B+D) when A or C is constant
210 define <4 x i32> @combine_vec_add_sub_sub(<4 x i32> %a, <4 x i32> %b, <4 x i32> %d) {
211 ; SSE-LABEL: combine_vec_add_sub_sub:
212 ; SSE:       # %bb.0:
213 ; SSE-NEXT:    paddd %xmm2, %xmm1
214 ; SSE-NEXT:    psubd %xmm1, %xmm0
215 ; SSE-NEXT:    paddd {{.*}}(%rip), %xmm0
216 ; SSE-NEXT:    retq
218 ; AVX-LABEL: combine_vec_add_sub_sub:
219 ; AVX:       # %bb.0:
220 ; AVX-NEXT:    vpaddd %xmm2, %xmm1, %xmm1
221 ; AVX-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
222 ; AVX-NEXT:    vpaddd {{.*}}(%rip), %xmm0, %xmm0
223 ; AVX-NEXT:    retq
224   %1 = sub <4 x i32> %a, %b
225   %2 = sub <4 x i32> <i32 0, i32 1, i32 2, i32 3>, %d
226   %3 = add <4 x i32> %1, %2
227   ret <4 x i32> %3
230 ; fold (a+b) -> (a|b) iff a and b share no bits.
231 define <4 x i32> @combine_vec_add_uniquebits(<4 x i32> %a, <4 x i32> %b) {
232 ; SSE-LABEL: combine_vec_add_uniquebits:
233 ; SSE:       # %bb.0:
234 ; SSE-NEXT:    andps {{.*}}(%rip), %xmm0
235 ; SSE-NEXT:    andps {{.*}}(%rip), %xmm1
236 ; SSE-NEXT:    orps %xmm1, %xmm0
237 ; SSE-NEXT:    retq
239 ; AVX-LABEL: combine_vec_add_uniquebits:
240 ; AVX:       # %bb.0:
241 ; AVX-NEXT:    vbroadcastss {{.*#+}} xmm2 = [61680,61680,61680,61680]
242 ; AVX-NEXT:    vandps %xmm2, %xmm0, %xmm0
243 ; AVX-NEXT:    vbroadcastss {{.*#+}} xmm2 = [3855,3855,3855,3855]
244 ; AVX-NEXT:    vandps %xmm2, %xmm1, %xmm1
245 ; AVX-NEXT:    vorps %xmm1, %xmm0, %xmm0
246 ; AVX-NEXT:    retq
247   %1 = and <4 x i32> %a, <i32 61680, i32 61680, i32 61680, i32 61680>
248   %2 = and <4 x i32> %b, <i32 3855, i32 3855, i32 3855, i32 3855>
249   %3 = add <4 x i32> %1, %2
250   ret <4 x i32> %3
253 ; fold (add x, shl(0 - y, n)) -> sub(x, shl(y, n))
254 define <4 x i32> @combine_vec_add_shl_neg0(<4 x i32> %x, <4 x i32> %y) {
255 ; SSE-LABEL: combine_vec_add_shl_neg0:
256 ; SSE:       # %bb.0:
257 ; SSE-NEXT:    pslld $5, %xmm1
258 ; SSE-NEXT:    psubd %xmm1, %xmm0
259 ; SSE-NEXT:    retq
261 ; AVX-LABEL: combine_vec_add_shl_neg0:
262 ; AVX:       # %bb.0:
263 ; AVX-NEXT:    vpslld $5, %xmm1, %xmm1
264 ; AVX-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
265 ; AVX-NEXT:    retq
266   %1 = sub <4 x i32> zeroinitializer, %y
267   %2 = shl <4 x i32> %1, <i32 5, i32 5, i32 5, i32 5>
268   %3 = add <4 x i32> %x, %2
269   ret <4 x i32> %3
272 ; fold (add shl(0 - y, n), x) -> sub(x, shl(y, n))
273 define <4 x i32> @combine_vec_add_shl_neg1(<4 x i32> %x, <4 x i32> %y) {
274 ; SSE-LABEL: combine_vec_add_shl_neg1:
275 ; SSE:       # %bb.0:
276 ; SSE-NEXT:    pslld $5, %xmm1
277 ; SSE-NEXT:    psubd %xmm1, %xmm0
278 ; SSE-NEXT:    retq
280 ; AVX-LABEL: combine_vec_add_shl_neg1:
281 ; AVX:       # %bb.0:
282 ; AVX-NEXT:    vpslld $5, %xmm1, %xmm1
283 ; AVX-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
284 ; AVX-NEXT:    retq
285   %1 = sub <4 x i32> zeroinitializer, %y
286   %2 = shl <4 x i32> %1, <i32 5, i32 5, i32 5, i32 5>
287   %3 = add <4 x i32> %2, %x
288   ret <4 x i32> %3
291 ; (add z, (and (sbbl x, x), 1)) -> (sub z, (sbbl x, x))
292 ; and similar xforms where the inner op is either ~0 or 0.
293 define <4 x i32> @combine_vec_add_and_compare(<4 x i32> %a0, <4 x i32> %a1, <4 x i32> %a2) {
294 ; SSE-LABEL: combine_vec_add_and_compare:
295 ; SSE:       # %bb.0:
296 ; SSE-NEXT:    pcmpeqd %xmm2, %xmm1
297 ; SSE-NEXT:    psubd %xmm1, %xmm0
298 ; SSE-NEXT:    retq
300 ; AVX-LABEL: combine_vec_add_and_compare:
301 ; AVX:       # %bb.0:
302 ; AVX-NEXT:    vpcmpeqd %xmm2, %xmm1, %xmm1
303 ; AVX-NEXT:    vpsubd %xmm1, %xmm0, %xmm0
304 ; AVX-NEXT:    retq
305   %1 = icmp eq <4 x i32> %a1, %a2
306   %2 = sext <4 x i1> %1 to <4 x i32>
307   %3 = and <4 x i32> %2, <i32 1, i32 1, i32 1, i32 1>
308   %4 = add <4 x i32> %a0, %3
309   ret <4 x i32> %4
312 ; add (sext i1), X -> sub X, (zext i1)
313 define <4 x i32> @combine_vec_add_sext(<4 x i1> %a0, <4 x i32> %a1) {
314 ; SSE-LABEL: combine_vec_add_sext:
315 ; SSE:       # %bb.0:
316 ; SSE-NEXT:    pslld $31, %xmm0
317 ; SSE-NEXT:    psrad $31, %xmm0
318 ; SSE-NEXT:    paddd %xmm1, %xmm0
319 ; SSE-NEXT:    retq
321 ; AVX-LABEL: combine_vec_add_sext:
322 ; AVX:       # %bb.0:
323 ; AVX-NEXT:    vpslld $31, %xmm0, %xmm0
324 ; AVX-NEXT:    vpsrad $31, %xmm0, %xmm0
325 ; AVX-NEXT:    vpaddd %xmm1, %xmm0, %xmm0
326 ; AVX-NEXT:    retq
327   %1 = sext <4 x i1> %a0 to <4 x i32>
328   %2 = add <4 x i32> %1, %a1
329   ret <4 x i32> %2
332 ; add (sext i1), X -> sub X, (zext i1)
333 define <4 x i32> @combine_vec_add_sextinreg(<4 x i32> %a0, <4 x i32> %a1) {
334 ; SSE-LABEL: combine_vec_add_sextinreg:
335 ; SSE:       # %bb.0:
336 ; SSE-NEXT:    pslld $31, %xmm0
337 ; SSE-NEXT:    psrad $31, %xmm0
338 ; SSE-NEXT:    paddd %xmm1, %xmm0
339 ; SSE-NEXT:    retq
341 ; AVX-LABEL: combine_vec_add_sextinreg:
342 ; AVX:       # %bb.0:
343 ; AVX-NEXT:    vpslld $31, %xmm0, %xmm0
344 ; AVX-NEXT:    vpsrad $31, %xmm0, %xmm0
345 ; AVX-NEXT:    vpaddd %xmm1, %xmm0, %xmm0
346 ; AVX-NEXT:    retq
347   %1 = shl <4 x i32> %a0, <i32 31, i32 31, i32 31, i32 31>
348   %2 = ashr <4 x i32> %1, <i32 31, i32 31, i32 31, i32 31>
349   %3 = add <4 x i32> %2, %a1
350   ret <4 x i32> %3
353 ; (add (add (xor a, -1), b), 1) -> (sub b, a)
354 define i32 @combine_add_add_not(i32 %a, i32 %b) {
355 ; SSE-LABEL: combine_add_add_not:
356 ; SSE:       # %bb.0:
357 ; SSE-NEXT:    movl %esi, %eax
358 ; SSE-NEXT:    subl %edi, %eax
359 ; SSE-NEXT:    retq
361 ; AVX-LABEL: combine_add_add_not:
362 ; AVX:       # %bb.0:
363 ; AVX-NEXT:    movl %esi, %eax
364 ; AVX-NEXT:    subl %edi, %eax
365 ; AVX-NEXT:    retq
366   %nota = xor i32 %a, -1
367   %add = add i32 %nota, %b
368   %r = add i32 %add, 1
369   ret i32 %r
372 define <4 x i32> @combine_vec_add_add_not(<4 x i32> %a, <4 x i32> %b) {
373 ; SSE-LABEL: combine_vec_add_add_not:
374 ; SSE:       # %bb.0:
375 ; SSE-NEXT:    psubd %xmm0, %xmm1
376 ; SSE-NEXT:    movdqa %xmm1, %xmm0
377 ; SSE-NEXT:    retq
379 ; AVX-LABEL: combine_vec_add_add_not:
380 ; AVX:       # %bb.0:
381 ; AVX-NEXT:    vpsubd %xmm0, %xmm1, %xmm0
382 ; AVX-NEXT:    retq
383   %nota = xor <4 x i32> %a, <i32 -1, i32 -1, i32 -1, i32 -1>
384   %add = add <4 x i32> %nota, %b
385   %r = add <4 x i32> %add, <i32 1, i32 1, i32 1, i32 1>
386   ret <4 x i32> %r