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: orr w0, w0, w2
364 %notmask = xor i32 %mask, -1
365 %mx = and i32 %notmask, %x
366 %my = and i32 %mask, -1
370 ; This is not a canonical form. Testing for completeness only.
371 define i32 @in_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
372 ; CHECK-LABEL: in_constant_varx_mone_invmask:
374 ; CHECK-NEXT: mvn w8, w0
375 ; CHECK-NEXT: bic w8, w8, w2
376 ; CHECK-NEXT: mvn w0, w8
378 %notmask = xor i32 %mask, -1
379 %n0 = xor i32 %x, -1 ; %x
380 %n1 = and i32 %n0, %notmask
384 define i32 @out_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
385 ; CHECK-LABEL: out_constant_varx_42:
387 ; CHECK-NEXT: mov w9, #42
388 ; CHECK-NEXT: and w8, w2, w0
389 ; CHECK-NEXT: bic w9, w9, w2
390 ; CHECK-NEXT: orr w0, w8, w9
392 %notmask = xor i32 %mask, -1
393 %mx = and i32 %mask, %x
394 %my = and i32 %notmask, 42
398 define i32 @in_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
399 ; CHECK-LABEL: in_constant_varx_42:
401 ; CHECK-NEXT: mov w8, #42
402 ; CHECK-NEXT: bic w8, w8, w2
403 ; CHECK-NEXT: and w9, w0, w2
404 ; CHECK-NEXT: orr w0, w9, w8
406 %n0 = xor i32 %x, 42 ; %x
407 %n1 = and i32 %n0, %mask
411 ; This is not a canonical form. Testing for completeness only.
412 define i32 @out_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
413 ; CHECK-LABEL: out_constant_varx_42_invmask:
415 ; CHECK-NEXT: mov w9, #42
416 ; CHECK-NEXT: bic w8, w0, w2
417 ; CHECK-NEXT: and w9, w2, w9
418 ; CHECK-NEXT: orr w0, w8, w9
420 %notmask = xor i32 %mask, -1
421 %mx = and i32 %notmask, %x
422 %my = and i32 %mask, 42
426 ; This is not a canonical form. Testing for completeness only.
427 define i32 @in_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
428 ; CHECK-LABEL: in_constant_varx_42_invmask:
430 ; CHECK-NEXT: mov w8, #42
431 ; CHECK-NEXT: and w8, w2, w8
432 ; CHECK-NEXT: bic w9, w0, w2
433 ; CHECK-NEXT: orr w0, w9, w8
435 %notmask = xor i32 %mask, -1
436 %n0 = xor i32 %x, 42 ; %x
437 %n1 = and i32 %n0, %notmask
441 define i32 @out_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
442 ; CHECK-LABEL: out_constant_mone_vary:
444 ; CHECK-NEXT: orr w0, w1, w2
446 %notmask = xor i32 %mask, -1
447 %mx = and i32 %mask, -1
448 %my = and i32 %notmask, %y
452 define i32 @in_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
453 ; CHECK-LABEL: in_constant_mone_vary:
455 ; CHECK-NEXT: bic w8, w2, w1
456 ; CHECK-NEXT: eor w0, w8, w1
458 %n0 = xor i32 -1, %y ; %x
459 %n1 = and i32 %n0, %mask
463 ; This is not a canonical form. Testing for completeness only.
464 define i32 @out_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
465 ; CHECK-LABEL: out_constant_mone_vary_invmask:
467 ; CHECK-NEXT: and w8, w2, w1
468 ; CHECK-NEXT: orn w0, w8, w2
470 %notmask = xor i32 %mask, -1
471 %mx = and i32 %notmask, -1
472 %my = and i32 %mask, %y
476 ; This is not a canonical form. Testing for completeness only.
477 define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
478 ; CHECK-LABEL: in_constant_mone_vary_invmask:
480 ; CHECK-NEXT: mvn w8, w1
481 ; CHECK-NEXT: bic w8, w8, w2
482 ; CHECK-NEXT: eor w0, w8, w1
484 %notmask = xor i32 %mask, -1
485 %n0 = xor i32 -1, %y ; %x
486 %n1 = and i32 %n0, %notmask
490 define i32 @out_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
491 ; CHECK-LABEL: out_constant_42_vary:
493 ; CHECK-NEXT: mov w8, #42
494 ; CHECK-NEXT: and w8, w2, w8
495 ; CHECK-NEXT: bic w9, w1, w2
496 ; CHECK-NEXT: orr w0, w8, w9
498 %notmask = xor i32 %mask, -1
499 %mx = and i32 %mask, 42
500 %my = and i32 %notmask, %y
504 define i32 @in_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
505 ; CHECK-LABEL: in_constant_42_vary:
507 ; CHECK-NEXT: mov w9, #42
508 ; CHECK-NEXT: bic w8, w1, w2
509 ; CHECK-NEXT: and w9, w2, w9
510 ; CHECK-NEXT: orr w0, w9, w8
512 %n0 = xor i32 42, %y ; %x
513 %n1 = and i32 %n0, %mask
517 ; This is not a canonical form. Testing for completeness only.
518 define i32 @out_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
519 ; CHECK-LABEL: out_constant_42_vary_invmask:
521 ; CHECK-NEXT: mov w8, #42
522 ; CHECK-NEXT: bic w8, w8, w2
523 ; CHECK-NEXT: and w9, w2, w1
524 ; CHECK-NEXT: orr w0, w8, w9
526 %notmask = xor i32 %mask, -1
527 %mx = and i32 %notmask, 42
528 %my = and i32 %mask, %y
532 ; This is not a canonical form. Testing for completeness only.
533 define i32 @in_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
534 ; CHECK-LABEL: in_constant_42_vary_invmask:
536 ; CHECK-NEXT: mov w9, #42
537 ; CHECK-NEXT: and w8, w1, w2
538 ; CHECK-NEXT: bic w9, w9, w2
539 ; CHECK-NEXT: orr w0, w9, w8
541 %notmask = xor i32 %mask, -1
542 %n0 = xor i32 42, %y ; %x
543 %n1 = and i32 %n0, %notmask
547 ; ============================================================================ ;
548 ; Negative tests. Should not be folded.
549 ; ============================================================================ ;
551 declare void @use32(i32) nounwind
552 define i32 @in_multiuse_A(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
553 ; CHECK-LABEL: in_multiuse_A:
555 ; CHECK-NEXT: str x20, [sp, #-32]! // 8-byte Folded Spill
556 ; CHECK-NEXT: eor w8, w0, w1
557 ; CHECK-NEXT: and w20, w8, w3
558 ; CHECK-NEXT: mov w0, w20
559 ; CHECK-NEXT: stp x19, x30, [sp, #16] // 16-byte Folded Spill
560 ; CHECK-NEXT: mov w19, w1
561 ; CHECK-NEXT: bl use32
562 ; CHECK-NEXT: eor w0, w20, w19
563 ; CHECK-NEXT: ldp x19, x30, [sp, #16] // 16-byte Folded Reload
564 ; CHECK-NEXT: ldr x20, [sp], #32 // 8-byte Folded Reload
567 %n1 = and i32 %n0, %mask
568 call void @use32(i32 %n1)
572 define i32 @in_multiuse_B(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
573 ; CHECK-LABEL: in_multiuse_B:
575 ; CHECK-NEXT: str x20, [sp, #-32]! // 8-byte Folded Spill
576 ; CHECK-NEXT: eor w0, w0, w1
577 ; CHECK-NEXT: stp x19, x30, [sp, #16] // 16-byte Folded Spill
578 ; CHECK-NEXT: mov w19, w1
579 ; CHECK-NEXT: and w20, w0, w3
580 ; CHECK-NEXT: bl use32
581 ; CHECK-NEXT: eor w0, w20, w19
582 ; CHECK-NEXT: ldp x19, x30, [sp, #16] // 16-byte Folded Reload
583 ; CHECK-NEXT: ldr x20, [sp], #32 // 8-byte Folded Reload
586 %n1 = and i32 %n0, %mask
587 call void @use32(i32 %n0)
591 ; Various bad variants
592 define i32 @n0_badmask(i32 %x, i32 %y, i32 %mask, i32 %mask2) {
593 ; CHECK-LABEL: n0_badmask:
595 ; CHECK-NEXT: and w8, w0, w2
596 ; CHECK-NEXT: bic w9, w1, w3
597 ; CHECK-NEXT: orr w0, w8, w9
599 %mx = and i32 %x, %mask
600 %notmask = xor i32 %mask2, -1 ; %mask2 instead of %mask
601 %my = and i32 %y, %notmask
605 define i32 @n0_badxor(i32 %x, i32 %y, i32 %mask) {
606 ; CHECK-LABEL: n0_badxor:
608 ; CHECK-NEXT: eor w9, w2, #0x1
609 ; CHECK-NEXT: and w8, w0, w2
610 ; CHECK-NEXT: and w9, w1, w9
611 ; CHECK-NEXT: orr w0, w8, w9
613 %mx = and i32 %x, %mask
614 %notmask = xor i32 %mask, 1 ; instead of -1
615 %my = and i32 %y, %notmask
619 define i32 @n1_thirdvar(i32 %x, i32 %y, i32 %z, i32 %mask) {
620 ; CHECK-LABEL: n1_thirdvar:
622 ; CHECK-NEXT: eor w8, w0, w1
623 ; CHECK-NEXT: and w8, w8, w3
624 ; CHECK-NEXT: eor w0, w8, w2
627 %n1 = and i32 %n0, %mask
628 %r = xor i32 %n1, %z ; instead of %y