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: eor w8, w3, w4
272 ; CHECK-NEXT: and w9, w1, w2
273 ; CHECK-NEXT: bic w9, w9, w8
274 ; CHECK-NEXT: and w8, w0, w8
275 ; CHECK-NEXT: orr w0, w8, w9
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: eor w8, w3, w4
288 ; CHECK-NEXT: and w9, w1, w2
289 ; CHECK-NEXT: bic w9, w9, w8
290 ; CHECK-NEXT: and w8, w0, w8
291 ; CHECK-NEXT: orr w0, w8, w9
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: eor w8, w3, w4
304 ; CHECK-NEXT: and w9, w1, w2
305 ; CHECK-NEXT: bic w9, w9, w8
306 ; CHECK-NEXT: and w8, w0, w8
307 ; CHECK-NEXT: orr w0, w8, w9
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: eor w8, w3, w4
320 ; CHECK-NEXT: and w9, w1, w2
321 ; CHECK-NEXT: bic w9, w9, w8
322 ; CHECK-NEXT: and w8, w0, w8
323 ; CHECK-NEXT: orr w0, w8, w9
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 w8, #42 // =0x2a
388 ; CHECK-NEXT: and w9, w2, w0
389 ; CHECK-NEXT: bic w8, w8, w2
390 ; CHECK-NEXT: orr w0, w9, w8
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 // =0x2a
402 ; CHECK-NEXT: and w9, w0, w2
403 ; CHECK-NEXT: bic w8, w8, 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 w8, #42 // =0x2a
416 ; CHECK-NEXT: bic w9, w0, w2
417 ; CHECK-NEXT: and w8, w2, w8
418 ; CHECK-NEXT: orr w0, w9, w8
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 // =0x2a
431 ; CHECK-NEXT: bic w9, w0, w2
432 ; CHECK-NEXT: and w8, w2, w8
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: orr w0, w2, w1
457 %n0 = xor i32 -1, %y ; %x
458 %n1 = and i32 %n0, %mask
462 ; This is not a canonical form. Testing for completeness only.
463 define i32 @out_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
464 ; CHECK-LABEL: out_constant_mone_vary_invmask:
466 ; CHECK-NEXT: and w8, w2, w1
467 ; CHECK-NEXT: orn w0, w8, w2
469 %notmask = xor i32 %mask, -1
470 %mx = and i32 %notmask, -1
471 %my = and i32 %mask, %y
475 ; This is not a canonical form. Testing for completeness only.
476 define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
477 ; CHECK-LABEL: in_constant_mone_vary_invmask:
479 ; CHECK-NEXT: orn w0, w1, w2
481 %notmask = xor i32 %mask, -1
482 %n0 = xor i32 -1, %y ; %x
483 %n1 = and i32 %n0, %notmask
487 define i32 @out_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
488 ; CHECK-LABEL: out_constant_42_vary:
490 ; CHECK-NEXT: mov w8, #42 // =0x2a
491 ; CHECK-NEXT: bic w9, w1, w2
492 ; CHECK-NEXT: and w8, w2, w8
493 ; CHECK-NEXT: orr w0, w8, w9
495 %notmask = xor i32 %mask, -1
496 %mx = and i32 %mask, 42
497 %my = and i32 %notmask, %y
501 define i32 @in_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
502 ; CHECK-LABEL: in_constant_42_vary:
504 ; CHECK-NEXT: mov w8, #42 // =0x2a
505 ; CHECK-NEXT: bic w9, w1, w2
506 ; CHECK-NEXT: and w8, w2, w8
507 ; CHECK-NEXT: orr w0, w8, w9
509 %n0 = xor i32 42, %y ; %x
510 %n1 = and i32 %n0, %mask
514 ; This is not a canonical form. Testing for completeness only.
515 define i32 @out_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
516 ; CHECK-LABEL: out_constant_42_vary_invmask:
518 ; CHECK-NEXT: mov w8, #42 // =0x2a
519 ; CHECK-NEXT: and w9, w2, w1
520 ; CHECK-NEXT: bic w8, w8, w2
521 ; CHECK-NEXT: orr w0, w8, w9
523 %notmask = xor i32 %mask, -1
524 %mx = and i32 %notmask, 42
525 %my = and i32 %mask, %y
529 ; This is not a canonical form. Testing for completeness only.
530 define i32 @in_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
531 ; CHECK-LABEL: in_constant_42_vary_invmask:
533 ; CHECK-NEXT: mov w8, #42 // =0x2a
534 ; CHECK-NEXT: and w9, w1, w2
535 ; CHECK-NEXT: bic w8, w8, w2
536 ; CHECK-NEXT: orr w0, w8, w9
538 %notmask = xor i32 %mask, -1
539 %n0 = xor i32 42, %y ; %x
540 %n1 = and i32 %n0, %notmask
544 ; ============================================================================ ;
545 ; Negative tests. Should not be folded.
546 ; ============================================================================ ;
548 declare void @use32(i32) nounwind
549 define i32 @in_multiuse_A(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
550 ; CHECK-LABEL: in_multiuse_A:
552 ; CHECK-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill
553 ; CHECK-NEXT: eor w8, w0, w1
554 ; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill
555 ; CHECK-NEXT: mov w19, w1
556 ; CHECK-NEXT: and w20, w8, w3
557 ; CHECK-NEXT: mov w0, w20
558 ; CHECK-NEXT: bl use32
559 ; CHECK-NEXT: eor w0, w20, w19
560 ; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload
561 ; CHECK-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload
564 %n1 = and i32 %n0, %mask
565 call void @use32(i32 %n1)
569 define i32 @in_multiuse_B(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
570 ; CHECK-LABEL: in_multiuse_B:
572 ; CHECK-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill
573 ; CHECK-NEXT: eor w0, w0, w1
574 ; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill
575 ; CHECK-NEXT: mov w19, w1
576 ; CHECK-NEXT: and w20, w0, w3
577 ; CHECK-NEXT: bl use32
578 ; CHECK-NEXT: eor w0, w20, w19
579 ; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload
580 ; CHECK-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload
583 %n1 = and i32 %n0, %mask
584 call void @use32(i32 %n0)
588 ; Various bad variants
589 define i32 @n0_badmask(i32 %x, i32 %y, i32 %mask, i32 %mask2) {
590 ; CHECK-LABEL: n0_badmask:
592 ; CHECK-NEXT: bic w8, w1, w3
593 ; CHECK-NEXT: and w9, w0, w2
594 ; CHECK-NEXT: orr w0, w9, w8
596 %mx = and i32 %x, %mask
597 %notmask = xor i32 %mask2, -1 ; %mask2 instead of %mask
598 %my = and i32 %y, %notmask
602 define i32 @n0_badxor(i32 %x, i32 %y, i32 %mask) {
603 ; CHECK-LABEL: n0_badxor:
605 ; CHECK-NEXT: eor w8, w2, #0x1
606 ; CHECK-NEXT: and w9, w0, w2
607 ; CHECK-NEXT: and w8, w1, w8
608 ; CHECK-NEXT: orr w0, w9, w8
610 %mx = and i32 %x, %mask
611 %notmask = xor i32 %mask, 1 ; instead of -1
612 %my = and i32 %y, %notmask
616 define i32 @n1_thirdvar(i32 %x, i32 %y, i32 %z, i32 %mask) {
617 ; CHECK-LABEL: n1_thirdvar:
619 ; CHECK-NEXT: eor w8, w0, w1
620 ; CHECK-NEXT: and w8, w8, w3
621 ; CHECK-NEXT: eor w0, w8, w2
624 %n1 = and i32 %n0, %mask
625 %r = xor i32 %n1, %z ; instead of %y