1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
4 ; https://bugs.llvm.org/show_bug.cgi?id=37104
6 define i8 @out8(i8 %x, i8 %y, i8 %mask) {
9 ; CHECK-NEXT: and w8, w0, w2
10 ; CHECK-NEXT: bic w9, w1, w2
11 ; CHECK-NEXT: orr w0, w8, w9
13 %mx = and i8 %x, %mask
14 %notmask = xor i8 %mask, -1
15 %my = and i8 %y, %notmask
20 define i16 @out16(i16 %x, i16 %y, i16 %mask) {
23 ; CHECK-NEXT: and w8, w0, w2
24 ; CHECK-NEXT: bic w9, w1, w2
25 ; CHECK-NEXT: orr w0, w8, w9
27 %mx = and i16 %x, %mask
28 %notmask = xor i16 %mask, -1
29 %my = and i16 %y, %notmask
34 define i32 @out32(i32 %x, i32 %y, i32 %mask) {
37 ; CHECK-NEXT: and w8, w0, w2
38 ; CHECK-NEXT: bic w9, w1, w2
39 ; CHECK-NEXT: orr w0, w8, w9
41 %mx = and i32 %x, %mask
42 %notmask = xor i32 %mask, -1
43 %my = and i32 %y, %notmask
48 define i64 @out64(i64 %x, i64 %y, i64 %mask) {
51 ; CHECK-NEXT: and x8, x0, x2
52 ; CHECK-NEXT: bic x9, x1, x2
53 ; CHECK-NEXT: orr x0, x8, x9
55 %mx = and i64 %x, %mask
56 %notmask = xor i64 %mask, -1
57 %my = and i64 %y, %notmask
61 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
62 ; Should be the same as the previous one.
63 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65 define i8 @in8(i8 %x, i8 %y, i8 %mask) {
68 ; CHECK-NEXT: bic w8, w1, w2
69 ; CHECK-NEXT: and w9, w0, w2
70 ; CHECK-NEXT: orr w0, w9, w8
73 %n1 = and i8 %n0, %mask
78 define i16 @in16(i16 %x, i16 %y, i16 %mask) {
81 ; CHECK-NEXT: bic w8, w1, w2
82 ; CHECK-NEXT: and w9, w0, w2
83 ; CHECK-NEXT: orr w0, w9, w8
86 %n1 = and i16 %n0, %mask
91 define i32 @in32(i32 %x, i32 %y, i32 %mask) {
94 ; CHECK-NEXT: bic w8, w1, w2
95 ; CHECK-NEXT: and w9, w0, w2
96 ; CHECK-NEXT: orr w0, w9, w8
99 %n1 = and i32 %n0, %mask
104 define i64 @in64(i64 %x, i64 %y, i64 %mask) {
107 ; CHECK-NEXT: bic x8, x1, x2
108 ; CHECK-NEXT: and x9, x0, x2
109 ; CHECK-NEXT: orr x0, x9, x8
112 %n1 = and i64 %n0, %mask
116 ; ============================================================================ ;
117 ; Commutativity tests.
118 ; ============================================================================ ;
119 define i32 @in_commutativity_0_0_1(i32 %x, i32 %y, i32 %mask) {
120 ; CHECK-LABEL: in_commutativity_0_0_1:
122 ; CHECK-NEXT: bic w8, w1, w2
123 ; CHECK-NEXT: and w9, w0, w2
124 ; CHECK-NEXT: orr w0, w9, w8
127 %n1 = and i32 %mask, %n0 ; swapped
131 define i32 @in_commutativity_0_1_0(i32 %x, i32 %y, i32 %mask) {
132 ; CHECK-LABEL: in_commutativity_0_1_0:
134 ; CHECK-NEXT: bic w8, w1, w2
135 ; CHECK-NEXT: and w9, w0, w2
136 ; CHECK-NEXT: orr w0, w9, w8
139 %n1 = and i32 %n0, %mask
140 %r = xor i32 %y, %n1 ; swapped
143 define i32 @in_commutativity_0_1_1(i32 %x, i32 %y, i32 %mask) {
144 ; CHECK-LABEL: in_commutativity_0_1_1:
146 ; CHECK-NEXT: bic w8, w1, w2
147 ; CHECK-NEXT: and w9, w0, w2
148 ; CHECK-NEXT: orr w0, w9, w8
151 %n1 = and i32 %mask, %n0 ; swapped
152 %r = xor i32 %y, %n1 ; swapped
155 define i32 @in_commutativity_1_0_0(i32 %x, i32 %y, i32 %mask) {
156 ; CHECK-LABEL: in_commutativity_1_0_0:
158 ; CHECK-NEXT: bic w8, w0, w2
159 ; CHECK-NEXT: and w9, w1, w2
160 ; CHECK-NEXT: orr w0, w9, w8
163 %n1 = and i32 %n0, %mask
164 %r = xor i32 %n1, %x ; %x instead of %y
167 define i32 @in_commutativity_1_0_1(i32 %x, i32 %y, i32 %mask) {
168 ; CHECK-LABEL: in_commutativity_1_0_1:
170 ; CHECK-NEXT: bic w8, w0, w2
171 ; CHECK-NEXT: and w9, w1, w2
172 ; CHECK-NEXT: orr w0, w9, w8
175 %n1 = and i32 %mask, %n0 ; swapped
176 %r = xor i32 %n1, %x ; %x instead of %y
179 define i32 @in_commutativity_1_1_0(i32 %x, i32 %y, i32 %mask) {
180 ; CHECK-LABEL: in_commutativity_1_1_0:
182 ; CHECK-NEXT: bic w8, w0, w2
183 ; CHECK-NEXT: and w9, w1, w2
184 ; CHECK-NEXT: orr w0, w9, w8
187 %n1 = and i32 %n0, %mask
188 %r = xor i32 %x, %n1 ; swapped, %x instead of %y
191 define i32 @in_commutativity_1_1_1(i32 %x, i32 %y, i32 %mask) {
192 ; CHECK-LABEL: in_commutativity_1_1_1:
194 ; CHECK-NEXT: bic w8, w0, w2
195 ; CHECK-NEXT: and w9, w1, w2
196 ; CHECK-NEXT: orr w0, w9, w8
199 %n1 = and i32 %mask, %n0 ; swapped
200 %r = xor i32 %x, %n1 ; swapped, %x instead of %y
203 ; ============================================================================ ;
205 ; ============================================================================ ;
206 define i32 @in_complex_y0(i32 %x, i32 %y_hi, i32 %y_low, i32 %mask) {
207 ; CHECK-LABEL: in_complex_y0:
209 ; CHECK-NEXT: and w8, w1, w2
210 ; CHECK-NEXT: and w9, w0, w3
211 ; CHECK-NEXT: bic w8, w8, w3
212 ; CHECK-NEXT: orr w0, w9, w8
214 %y = and i32 %y_hi, %y_low
216 %n1 = and i32 %n0, %mask
220 define i32 @in_complex_y1(i32 %x, i32 %y_hi, i32 %y_low, i32 %mask) {
221 ; CHECK-LABEL: in_complex_y1:
223 ; CHECK-NEXT: and w8, w1, w2
224 ; CHECK-NEXT: and w9, w0, w3
225 ; CHECK-NEXT: bic w8, w8, w3
226 ; CHECK-NEXT: orr w0, w9, w8
228 %y = and i32 %y_hi, %y_low
230 %n1 = and i32 %n0, %mask
234 ; ============================================================================ ;
236 ; ============================================================================ ;
237 define i32 @in_complex_m0(i32 %x, i32 %y, i32 %m_a, i32 %m_b) {
238 ; CHECK-LABEL: in_complex_m0:
240 ; CHECK-NEXT: eor w8, w2, w3
241 ; CHECK-NEXT: bic w9, w1, w8
242 ; CHECK-NEXT: and w8, w0, w8
243 ; CHECK-NEXT: orr w0, w8, w9
245 %mask = xor i32 %m_a, %m_b
247 %n1 = and i32 %n0, %mask
251 define i32 @in_complex_m1(i32 %x, i32 %y, i32 %m_a, i32 %m_b) {
252 ; CHECK-LABEL: in_complex_m1:
254 ; CHECK-NEXT: eor w8, w2, w3
255 ; CHECK-NEXT: bic w9, w1, w8
256 ; CHECK-NEXT: and w8, w0, w8
257 ; CHECK-NEXT: orr w0, w8, w9
259 %mask = xor i32 %m_a, %m_b
261 %n1 = and i32 %mask, %n0
265 ; ============================================================================ ;
266 ; Both Y and M are complex.
267 ; ============================================================================ ;
268 define i32 @in_complex_y0_m0(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
269 ; CHECK-LABEL: in_complex_y0_m0:
271 ; CHECK-NEXT: and w8, w1, w2
272 ; CHECK-NEXT: eor w9, w3, w4
273 ; CHECK-NEXT: bic w8, w8, w9
274 ; CHECK-NEXT: and w9, w0, w9
275 ; CHECK-NEXT: orr w0, w9, w8
277 %y = and i32 %y_hi, %y_low
278 %mask = xor i32 %m_a, %m_b
280 %n1 = and i32 %n0, %mask
284 define i32 @in_complex_y1_m0(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
285 ; CHECK-LABEL: in_complex_y1_m0:
287 ; CHECK-NEXT: and w8, w1, w2
288 ; CHECK-NEXT: eor w9, w3, w4
289 ; CHECK-NEXT: bic w8, w8, w9
290 ; CHECK-NEXT: and w9, w0, w9
291 ; CHECK-NEXT: orr w0, w9, w8
293 %y = and i32 %y_hi, %y_low
294 %mask = xor i32 %m_a, %m_b
296 %n1 = and i32 %n0, %mask
300 define i32 @in_complex_y0_m1(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
301 ; CHECK-LABEL: in_complex_y0_m1:
303 ; CHECK-NEXT: and w8, w1, w2
304 ; CHECK-NEXT: eor w9, w3, w4
305 ; CHECK-NEXT: bic w8, w8, w9
306 ; CHECK-NEXT: and w9, w0, w9
307 ; CHECK-NEXT: orr w0, w9, w8
309 %y = and i32 %y_hi, %y_low
310 %mask = xor i32 %m_a, %m_b
312 %n1 = and i32 %mask, %n0
316 define i32 @in_complex_y1_m1(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
317 ; CHECK-LABEL: in_complex_y1_m1:
319 ; CHECK-NEXT: and w8, w1, w2
320 ; CHECK-NEXT: eor w9, w3, w4
321 ; CHECK-NEXT: bic w8, w8, w9
322 ; CHECK-NEXT: and w9, w0, w9
323 ; CHECK-NEXT: orr w0, w9, w8
325 %y = and i32 %y_hi, %y_low
326 %mask = xor i32 %m_a, %m_b
328 %n1 = and i32 %mask, %n0
332 ; ============================================================================ ;
333 ; Various cases with %x and/or %y being a constant
334 ; ============================================================================ ;
335 define i32 @out_constant_varx_mone(i32 %x, i32 %y, i32 %mask) {
336 ; CHECK-LABEL: out_constant_varx_mone:
338 ; CHECK-NEXT: and w8, w2, w0
339 ; CHECK-NEXT: orn w0, w8, w2
341 %notmask = xor i32 %mask, -1
342 %mx = and i32 %mask, %x
343 %my = and i32 %notmask, -1
347 define i32 @in_constant_varx_mone(i32 %x, i32 %y, i32 %mask) {
348 ; CHECK-LABEL: in_constant_varx_mone:
350 ; CHECK-NEXT: bic w8, w2, w0
351 ; CHECK-NEXT: mvn w0, w8
353 %n0 = xor i32 %x, -1 ; %x
354 %n1 = and i32 %n0, %mask
358 ; This is not a canonical form. Testing for completeness only.
359 define i32 @out_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
360 ; CHECK-LABEL: out_constant_varx_mone_invmask:
362 ; CHECK-NEXT: bic w8, w0, w2
363 ; CHECK-NEXT: orr w0, w8, w2
365 %notmask = xor i32 %mask, -1
366 %mx = and i32 %notmask, %x
367 %my = and i32 %mask, -1
371 ; This is not a canonical form. Testing for completeness only.
372 define i32 @in_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
373 ; CHECK-LABEL: in_constant_varx_mone_invmask:
375 ; CHECK-NEXT: mvn w8, w0
376 ; CHECK-NEXT: bic w8, w8, w2
377 ; CHECK-NEXT: mvn w0, w8
379 %notmask = xor i32 %mask, -1
380 %n0 = xor i32 %x, -1 ; %x
381 %n1 = and i32 %n0, %notmask
385 define i32 @out_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
386 ; CHECK-LABEL: out_constant_varx_42:
388 ; CHECK-NEXT: mov w9, #42
389 ; CHECK-NEXT: and w8, w2, w0
390 ; CHECK-NEXT: bic w9, w9, w2
391 ; CHECK-NEXT: orr w0, w8, w9
393 %notmask = xor i32 %mask, -1
394 %mx = and i32 %mask, %x
395 %my = and i32 %notmask, 42
399 define i32 @in_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
400 ; CHECK-LABEL: in_constant_varx_42:
402 ; CHECK-NEXT: mov w8, #42
403 ; CHECK-NEXT: bic w8, w8, w2
404 ; CHECK-NEXT: and w9, w0, w2
405 ; CHECK-NEXT: orr w0, w9, w8
407 %n0 = xor i32 %x, 42 ; %x
408 %n1 = and i32 %n0, %mask
412 ; This is not a canonical form. Testing for completeness only.
413 define i32 @out_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
414 ; CHECK-LABEL: out_constant_varx_42_invmask:
416 ; CHECK-NEXT: mov w9, #42
417 ; CHECK-NEXT: bic w8, w0, w2
418 ; CHECK-NEXT: and w9, w2, w9
419 ; CHECK-NEXT: orr w0, w8, w9
421 %notmask = xor i32 %mask, -1
422 %mx = and i32 %notmask, %x
423 %my = and i32 %mask, 42
427 ; This is not a canonical form. Testing for completeness only.
428 define i32 @in_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
429 ; CHECK-LABEL: in_constant_varx_42_invmask:
431 ; CHECK-NEXT: mov w8, #42
432 ; CHECK-NEXT: and w8, w2, w8
433 ; CHECK-NEXT: bic w9, w0, w2
434 ; CHECK-NEXT: orr w0, w9, w8
436 %notmask = xor i32 %mask, -1
437 %n0 = xor i32 %x, 42 ; %x
438 %n1 = and i32 %n0, %notmask
442 define i32 @out_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
443 ; CHECK-LABEL: out_constant_mone_vary:
445 ; CHECK-NEXT: bic w8, w1, w2
446 ; CHECK-NEXT: orr w0, w2, w8
448 %notmask = xor i32 %mask, -1
449 %mx = and i32 %mask, -1
450 %my = and i32 %notmask, %y
454 define i32 @in_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
455 ; CHECK-LABEL: in_constant_mone_vary:
457 ; CHECK-NEXT: bic w8, w2, w1
458 ; CHECK-NEXT: eor w0, w8, w1
460 %n0 = xor i32 -1, %y ; %x
461 %n1 = and i32 %n0, %mask
465 ; This is not a canonical form. Testing for completeness only.
466 define i32 @out_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
467 ; CHECK-LABEL: out_constant_mone_vary_invmask:
469 ; CHECK-NEXT: and w8, w2, w1
470 ; CHECK-NEXT: orn w0, w8, w2
472 %notmask = xor i32 %mask, -1
473 %mx = and i32 %notmask, -1
474 %my = and i32 %mask, %y
478 ; This is not a canonical form. Testing for completeness only.
479 define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
480 ; CHECK-LABEL: in_constant_mone_vary_invmask:
482 ; CHECK-NEXT: mvn w8, w1
483 ; CHECK-NEXT: bic w8, w8, w2
484 ; CHECK-NEXT: eor w0, w8, w1
486 %notmask = xor i32 %mask, -1
487 %n0 = xor i32 -1, %y ; %x
488 %n1 = and i32 %n0, %notmask
492 define i32 @out_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
493 ; CHECK-LABEL: out_constant_42_vary:
495 ; CHECK-NEXT: mov w8, #42
496 ; CHECK-NEXT: and w8, w2, w8
497 ; CHECK-NEXT: bic w9, w1, w2
498 ; CHECK-NEXT: orr w0, w8, w9
500 %notmask = xor i32 %mask, -1
501 %mx = and i32 %mask, 42
502 %my = and i32 %notmask, %y
506 define i32 @in_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
507 ; CHECK-LABEL: in_constant_42_vary:
509 ; CHECK-NEXT: mov w9, #42
510 ; CHECK-NEXT: bic w8, w1, w2
511 ; CHECK-NEXT: and w9, w2, w9
512 ; CHECK-NEXT: orr w0, w9, w8
514 %n0 = xor i32 42, %y ; %x
515 %n1 = and i32 %n0, %mask
519 ; This is not a canonical form. Testing for completeness only.
520 define i32 @out_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
521 ; CHECK-LABEL: out_constant_42_vary_invmask:
523 ; CHECK-NEXT: mov w8, #42
524 ; CHECK-NEXT: bic w8, w8, w2
525 ; CHECK-NEXT: and w9, w2, w1
526 ; CHECK-NEXT: orr w0, w8, w9
528 %notmask = xor i32 %mask, -1
529 %mx = and i32 %notmask, 42
530 %my = and i32 %mask, %y
534 ; This is not a canonical form. Testing for completeness only.
535 define i32 @in_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
536 ; CHECK-LABEL: in_constant_42_vary_invmask:
538 ; CHECK-NEXT: mov w9, #42
539 ; CHECK-NEXT: and w8, w1, w2
540 ; CHECK-NEXT: bic w9, w9, w2
541 ; CHECK-NEXT: orr w0, w9, w8
543 %notmask = xor i32 %mask, -1
544 %n0 = xor i32 42, %y ; %x
545 %n1 = and i32 %n0, %notmask
549 ; ============================================================================ ;
550 ; Negative tests. Should not be folded.
551 ; ============================================================================ ;
553 declare void @use32(i32) nounwind
554 define i32 @in_multiuse_A(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
555 ; CHECK-LABEL: in_multiuse_A:
557 ; CHECK-NEXT: str x20, [sp, #-32]! // 8-byte Folded Spill
558 ; CHECK-NEXT: eor w8, w0, w1
559 ; CHECK-NEXT: and w20, w8, w3
560 ; CHECK-NEXT: mov w0, w20
561 ; CHECK-NEXT: stp x19, x30, [sp, #16] // 16-byte Folded Spill
562 ; CHECK-NEXT: mov w19, w1
563 ; CHECK-NEXT: bl use32
564 ; CHECK-NEXT: eor w0, w20, w19
565 ; CHECK-NEXT: ldp x19, x30, [sp, #16] // 16-byte Folded Reload
566 ; CHECK-NEXT: ldr x20, [sp], #32 // 8-byte Folded Reload
569 %n1 = and i32 %n0, %mask
570 call void @use32(i32 %n1)
574 define i32 @in_multiuse_B(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
575 ; CHECK-LABEL: in_multiuse_B:
577 ; CHECK-NEXT: str x20, [sp, #-32]! // 8-byte Folded Spill
578 ; CHECK-NEXT: eor w0, w0, w1
579 ; CHECK-NEXT: stp x19, x30, [sp, #16] // 16-byte Folded Spill
580 ; CHECK-NEXT: mov w19, w1
581 ; CHECK-NEXT: and w20, w0, w3
582 ; CHECK-NEXT: bl use32
583 ; CHECK-NEXT: eor w0, w20, w19
584 ; CHECK-NEXT: ldp x19, x30, [sp, #16] // 16-byte Folded Reload
585 ; CHECK-NEXT: ldr x20, [sp], #32 // 8-byte Folded Reload
588 %n1 = and i32 %n0, %mask
589 call void @use32(i32 %n0)
593 ; Various bad variants
594 define i32 @n0_badmask(i32 %x, i32 %y, i32 %mask, i32 %mask2) {
595 ; CHECK-LABEL: n0_badmask:
597 ; CHECK-NEXT: and w8, w0, w2
598 ; CHECK-NEXT: bic w9, w1, w3
599 ; CHECK-NEXT: orr w0, w8, w9
601 %mx = and i32 %x, %mask
602 %notmask = xor i32 %mask2, -1 ; %mask2 instead of %mask
603 %my = and i32 %y, %notmask
607 define i32 @n0_badxor(i32 %x, i32 %y, i32 %mask) {
608 ; CHECK-LABEL: n0_badxor:
610 ; CHECK-NEXT: eor w9, w2, #0x1
611 ; CHECK-NEXT: and w8, w0, w2
612 ; CHECK-NEXT: and w9, w1, w9
613 ; CHECK-NEXT: orr w0, w8, w9
615 %mx = and i32 %x, %mask
616 %notmask = xor i32 %mask, 1 ; instead of -1
617 %my = and i32 %y, %notmask
621 define i32 @n1_thirdvar(i32 %x, i32 %y, i32 %z, i32 %mask) {
622 ; CHECK-LABEL: n1_thirdvar:
624 ; CHECK-NEXT: eor w8, w0, w1
625 ; CHECK-NEXT: and w8, w8, w3
626 ; CHECK-NEXT: eor w0, w8, w2
629 %n1 = and i32 %n0, %mask
630 %r = xor i32 %n1, %z ; instead of %y