1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=riscv32 < %s \
3 ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-I,RV32,RV32I
4 ; RUN: llc -mtriple=riscv64 < %s \
5 ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-I,RV64,RV64I
6 ; RUN: llc -mtriple=riscv32 -mattr=+zbb < %s \
7 ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ZBB,RV32,RV32ZBB
8 ; RUN: llc -mtriple=riscv64 -mattr=+zbb < %s \
9 ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-ZBB,RV64,RV64ZBB
11 ; TODO: Should we convert these to X ^ ((X ^ Y) & M) form when Zbb isn't
14 define i8 @out8(i8 %x, i8 %y, i8 %mask) {
15 ; CHECK-I-LABEL: out8:
17 ; CHECK-I-NEXT: and a0, a0, a2
18 ; CHECK-I-NEXT: not a2, a2
19 ; CHECK-I-NEXT: and a1, a1, a2
20 ; CHECK-I-NEXT: or a0, a0, a1
23 ; CHECK-ZBB-LABEL: out8:
25 ; CHECK-ZBB-NEXT: and a0, a0, a2
26 ; CHECK-ZBB-NEXT: andn a1, a1, a2
27 ; CHECK-ZBB-NEXT: or a0, a0, a1
29 %mx = and i8 %x, %mask
30 %notmask = xor i8 %mask, -1
31 %my = and i8 %y, %notmask
36 define i16 @out16(i16 %x, i16 %y, i16 %mask) {
37 ; CHECK-I-LABEL: out16:
39 ; CHECK-I-NEXT: and a0, a0, a2
40 ; CHECK-I-NEXT: not a2, a2
41 ; CHECK-I-NEXT: and a1, a1, a2
42 ; CHECK-I-NEXT: or a0, a0, a1
45 ; CHECK-ZBB-LABEL: out16:
47 ; CHECK-ZBB-NEXT: and a0, a0, a2
48 ; CHECK-ZBB-NEXT: andn a1, a1, a2
49 ; CHECK-ZBB-NEXT: or a0, a0, a1
51 %mx = and i16 %x, %mask
52 %notmask = xor i16 %mask, -1
53 %my = and i16 %y, %notmask
58 define i32 @out32(i32 %x, i32 %y, i32 %mask) {
59 ; CHECK-I-LABEL: out32:
61 ; CHECK-I-NEXT: and a0, a0, a2
62 ; CHECK-I-NEXT: not a2, a2
63 ; CHECK-I-NEXT: and a1, a1, a2
64 ; CHECK-I-NEXT: or a0, a0, a1
67 ; CHECK-ZBB-LABEL: out32:
69 ; CHECK-ZBB-NEXT: and a0, a0, a2
70 ; CHECK-ZBB-NEXT: andn a1, a1, a2
71 ; CHECK-ZBB-NEXT: or a0, a0, a1
73 %mx = and i32 %x, %mask
74 %notmask = xor i32 %mask, -1
75 %my = and i32 %y, %notmask
80 define i64 @out64(i64 %x, i64 %y, i64 %mask) {
83 ; RV32I-NEXT: and a1, a1, a5
84 ; RV32I-NEXT: and a0, a0, a4
85 ; RV32I-NEXT: not a4, a4
86 ; RV32I-NEXT: not a5, a5
87 ; RV32I-NEXT: and a3, a3, a5
88 ; RV32I-NEXT: and a2, a2, a4
89 ; RV32I-NEXT: or a0, a0, a2
90 ; RV32I-NEXT: or a1, a1, a3
95 ; RV64I-NEXT: and a0, a0, a2
96 ; RV64I-NEXT: not a2, a2
97 ; RV64I-NEXT: and a1, a1, a2
98 ; RV64I-NEXT: or a0, a0, a1
101 ; RV32ZBB-LABEL: out64:
103 ; RV32ZBB-NEXT: and a1, a1, a5
104 ; RV32ZBB-NEXT: and a0, a0, a4
105 ; RV32ZBB-NEXT: andn a3, a3, a5
106 ; RV32ZBB-NEXT: andn a2, a2, a4
107 ; RV32ZBB-NEXT: or a0, a0, a2
108 ; RV32ZBB-NEXT: or a1, a1, a3
111 ; RV64ZBB-LABEL: out64:
113 ; RV64ZBB-NEXT: and a0, a0, a2
114 ; RV64ZBB-NEXT: andn a1, a1, a2
115 ; RV64ZBB-NEXT: or a0, a0, a1
117 %mx = and i64 %x, %mask
118 %notmask = xor i64 %mask, -1
119 %my = and i64 %y, %notmask
124 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
125 ; These tests should produce the same output as the corresponding out* test
126 ; when the Zbb extension is enabled.
127 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
129 define i8 @in8(i8 %x, i8 %y, i8 %mask) {
130 ; CHECK-I-LABEL: in8:
132 ; CHECK-I-NEXT: xor a0, a0, a1
133 ; CHECK-I-NEXT: and a0, a0, a2
134 ; CHECK-I-NEXT: xor a0, a0, a1
137 ; CHECK-ZBB-LABEL: in8:
138 ; CHECK-ZBB: # %bb.0:
139 ; CHECK-ZBB-NEXT: andn a1, a1, a2
140 ; CHECK-ZBB-NEXT: and a0, a0, a2
141 ; CHECK-ZBB-NEXT: or a0, a0, a1
142 ; CHECK-ZBB-NEXT: ret
144 %n1 = and i8 %n0, %mask
149 define i16 @in16(i16 %x, i16 %y, i16 %mask) {
150 ; CHECK-I-LABEL: in16:
152 ; CHECK-I-NEXT: xor a0, a0, a1
153 ; CHECK-I-NEXT: and a0, a0, a2
154 ; CHECK-I-NEXT: xor a0, a0, a1
157 ; CHECK-ZBB-LABEL: in16:
158 ; CHECK-ZBB: # %bb.0:
159 ; CHECK-ZBB-NEXT: andn a1, a1, a2
160 ; CHECK-ZBB-NEXT: and a0, a0, a2
161 ; CHECK-ZBB-NEXT: or a0, a0, a1
162 ; CHECK-ZBB-NEXT: ret
164 %n1 = and i16 %n0, %mask
169 define i32 @in32(i32 %x, i32 %y, i32 %mask) {
170 ; CHECK-I-LABEL: in32:
172 ; CHECK-I-NEXT: xor a0, a0, a1
173 ; CHECK-I-NEXT: and a0, a0, a2
174 ; CHECK-I-NEXT: xor a0, a0, a1
177 ; CHECK-ZBB-LABEL: in32:
178 ; CHECK-ZBB: # %bb.0:
179 ; CHECK-ZBB-NEXT: andn a1, a1, a2
180 ; CHECK-ZBB-NEXT: and a0, a0, a2
181 ; CHECK-ZBB-NEXT: or a0, a0, a1
182 ; CHECK-ZBB-NEXT: ret
184 %n1 = and i32 %n0, %mask
189 define i64 @in64(i64 %x, i64 %y, i64 %mask) {
192 ; RV32I-NEXT: xor a0, a0, a2
193 ; RV32I-NEXT: xor a1, a1, a3
194 ; RV32I-NEXT: and a1, a1, a5
195 ; RV32I-NEXT: and a0, a0, a4
196 ; RV32I-NEXT: xor a0, a0, a2
197 ; RV32I-NEXT: xor a1, a1, a3
202 ; RV64I-NEXT: xor a0, a0, a1
203 ; RV64I-NEXT: and a0, a0, a2
204 ; RV64I-NEXT: xor a0, a0, a1
207 ; RV32ZBB-LABEL: in64:
209 ; RV32ZBB-NEXT: andn a2, a2, a4
210 ; RV32ZBB-NEXT: and a0, a0, a4
211 ; RV32ZBB-NEXT: or a0, a0, a2
212 ; RV32ZBB-NEXT: andn a2, a3, a5
213 ; RV32ZBB-NEXT: and a1, a1, a5
214 ; RV32ZBB-NEXT: or a1, a1, a2
217 ; RV64ZBB-LABEL: in64:
219 ; RV64ZBB-NEXT: andn a1, a1, a2
220 ; RV64ZBB-NEXT: and a0, a0, a2
221 ; RV64ZBB-NEXT: or a0, a0, a1
224 %n1 = and i64 %n0, %mask
229 ; ============================================================================ ;
230 ; Commutativity tests.
231 ; ============================================================================ ;
233 define i32 @in_commutativity_0_0_1(i32 %x, i32 %y, i32 %mask) {
234 ; CHECK-I-LABEL: in_commutativity_0_0_1:
236 ; CHECK-I-NEXT: xor a0, a0, a1
237 ; CHECK-I-NEXT: and a0, a2, a0
238 ; CHECK-I-NEXT: xor a0, a0, a1
241 ; CHECK-ZBB-LABEL: in_commutativity_0_0_1:
242 ; CHECK-ZBB: # %bb.0:
243 ; CHECK-ZBB-NEXT: andn a1, a1, a2
244 ; CHECK-ZBB-NEXT: and a0, a0, a2
245 ; CHECK-ZBB-NEXT: or a0, a0, a1
246 ; CHECK-ZBB-NEXT: ret
248 %n1 = and i32 %mask, %n0 ; swapped
253 define i32 @in_commutativity_0_1_0(i32 %x, i32 %y, i32 %mask) {
254 ; CHECK-I-LABEL: in_commutativity_0_1_0:
256 ; CHECK-I-NEXT: xor a0, a0, a1
257 ; CHECK-I-NEXT: and a0, a0, a2
258 ; CHECK-I-NEXT: xor a0, a1, a0
261 ; CHECK-ZBB-LABEL: in_commutativity_0_1_0:
262 ; CHECK-ZBB: # %bb.0:
263 ; CHECK-ZBB-NEXT: andn a1, a1, a2
264 ; CHECK-ZBB-NEXT: and a0, a0, a2
265 ; CHECK-ZBB-NEXT: or a0, a0, a1
266 ; CHECK-ZBB-NEXT: ret
268 %n1 = and i32 %n0, %mask
269 %r = xor i32 %y, %n1 ; swapped
273 define i32 @in_commutativity_0_1_1(i32 %x, i32 %y, i32 %mask) {
274 ; CHECK-I-LABEL: in_commutativity_0_1_1:
276 ; CHECK-I-NEXT: xor a0, a0, a1
277 ; CHECK-I-NEXT: and a0, a2, a0
278 ; CHECK-I-NEXT: xor a0, a1, a0
281 ; CHECK-ZBB-LABEL: in_commutativity_0_1_1:
282 ; CHECK-ZBB: # %bb.0:
283 ; CHECK-ZBB-NEXT: andn a1, a1, a2
284 ; CHECK-ZBB-NEXT: and a0, a0, a2
285 ; CHECK-ZBB-NEXT: or a0, a0, a1
286 ; CHECK-ZBB-NEXT: ret
288 %n1 = and i32 %mask, %n0 ; swapped
289 %r = xor i32 %y, %n1 ; swapped
293 define i32 @in_commutativity_1_0_0(i32 %x, i32 %y, i32 %mask) {
294 ; CHECK-I-LABEL: in_commutativity_1_0_0:
296 ; CHECK-I-NEXT: xor a1, a0, a1
297 ; CHECK-I-NEXT: and a1, a1, a2
298 ; CHECK-I-NEXT: xor a0, a1, a0
301 ; CHECK-ZBB-LABEL: in_commutativity_1_0_0:
302 ; CHECK-ZBB: # %bb.0:
303 ; CHECK-ZBB-NEXT: andn a0, a0, a2
304 ; CHECK-ZBB-NEXT: and a1, a1, a2
305 ; CHECK-ZBB-NEXT: or a0, a1, a0
306 ; CHECK-ZBB-NEXT: ret
308 %n1 = and i32 %n0, %mask
309 %r = xor i32 %n1, %x ; %x instead of %y
313 define i32 @in_commutativity_1_0_1(i32 %x, i32 %y, i32 %mask) {
314 ; CHECK-I-LABEL: in_commutativity_1_0_1:
316 ; CHECK-I-NEXT: xor a1, a0, a1
317 ; CHECK-I-NEXT: and a1, a2, a1
318 ; CHECK-I-NEXT: xor a0, a1, a0
321 ; CHECK-ZBB-LABEL: in_commutativity_1_0_1:
322 ; CHECK-ZBB: # %bb.0:
323 ; CHECK-ZBB-NEXT: andn a0, a0, a2
324 ; CHECK-ZBB-NEXT: and a1, a1, a2
325 ; CHECK-ZBB-NEXT: or a0, a1, a0
326 ; CHECK-ZBB-NEXT: ret
328 %n1 = and i32 %mask, %n0 ; swapped
329 %r = xor i32 %n1, %x ; %x instead of %y
333 define i32 @in_commutativity_1_1_0(i32 %x, i32 %y, i32 %mask) {
334 ; CHECK-I-LABEL: in_commutativity_1_1_0:
336 ; CHECK-I-NEXT: xor a1, a0, a1
337 ; CHECK-I-NEXT: and a1, a1, a2
338 ; CHECK-I-NEXT: xor a0, a0, a1
341 ; CHECK-ZBB-LABEL: in_commutativity_1_1_0:
342 ; CHECK-ZBB: # %bb.0:
343 ; CHECK-ZBB-NEXT: andn a0, a0, a2
344 ; CHECK-ZBB-NEXT: and a1, a1, a2
345 ; CHECK-ZBB-NEXT: or a0, a1, a0
346 ; CHECK-ZBB-NEXT: ret
348 %n1 = and i32 %n0, %mask
349 %r = xor i32 %x, %n1 ; swapped, %x instead of %y
353 define i32 @in_commutativity_1_1_1(i32 %x, i32 %y, i32 %mask) {
354 ; CHECK-I-LABEL: in_commutativity_1_1_1:
356 ; CHECK-I-NEXT: xor a1, a0, a1
357 ; CHECK-I-NEXT: and a1, a2, a1
358 ; CHECK-I-NEXT: xor a0, a0, a1
361 ; CHECK-ZBB-LABEL: in_commutativity_1_1_1:
362 ; CHECK-ZBB: # %bb.0:
363 ; CHECK-ZBB-NEXT: andn a0, a0, a2
364 ; CHECK-ZBB-NEXT: and a1, a1, a2
365 ; CHECK-ZBB-NEXT: or a0, a1, a0
366 ; CHECK-ZBB-NEXT: ret
368 %n1 = and i32 %mask, %n0 ; swapped
369 %r = xor i32 %x, %n1 ; swapped, %x instead of %y
373 ; ============================================================================ ;
375 ; ============================================================================ ;
377 define i32 @in_complex_y0(i32 %x, i32 %y_hi, i32 %y_low, i32 %mask) {
378 ; CHECK-I-LABEL: in_complex_y0:
380 ; CHECK-I-NEXT: and a1, a1, a2
381 ; CHECK-I-NEXT: xor a0, a0, a1
382 ; CHECK-I-NEXT: and a0, a0, a3
383 ; CHECK-I-NEXT: xor a0, a0, a1
386 ; CHECK-ZBB-LABEL: in_complex_y0:
387 ; CHECK-ZBB: # %bb.0:
388 ; CHECK-ZBB-NEXT: and a1, a1, a2
389 ; CHECK-ZBB-NEXT: and a0, a0, a3
390 ; CHECK-ZBB-NEXT: andn a1, a1, a3
391 ; CHECK-ZBB-NEXT: or a0, a0, a1
392 ; CHECK-ZBB-NEXT: ret
393 %y = and i32 %y_hi, %y_low
395 %n1 = and i32 %n0, %mask
400 define i32 @in_complex_y1(i32 %x, i32 %y_hi, i32 %y_low, i32 %mask) {
401 ; CHECK-I-LABEL: in_complex_y1:
403 ; CHECK-I-NEXT: and a1, a1, a2
404 ; CHECK-I-NEXT: xor a0, a0, a1
405 ; CHECK-I-NEXT: and a0, a0, a3
406 ; CHECK-I-NEXT: xor a0, a1, a0
409 ; CHECK-ZBB-LABEL: in_complex_y1:
410 ; CHECK-ZBB: # %bb.0:
411 ; CHECK-ZBB-NEXT: and a1, a1, a2
412 ; CHECK-ZBB-NEXT: and a0, a0, a3
413 ; CHECK-ZBB-NEXT: andn a1, a1, a3
414 ; CHECK-ZBB-NEXT: or a0, a0, a1
415 ; CHECK-ZBB-NEXT: ret
416 %y = and i32 %y_hi, %y_low
418 %n1 = and i32 %n0, %mask
423 ; ============================================================================ ;
425 ; ============================================================================ ;
427 define i32 @in_complex_m0(i32 %x, i32 %y, i32 %m_a, i32 %m_b) {
428 ; CHECK-I-LABEL: in_complex_m0:
430 ; CHECK-I-NEXT: xor a2, a2, a3
431 ; CHECK-I-NEXT: xor a0, a0, a1
432 ; CHECK-I-NEXT: and a0, a0, a2
433 ; CHECK-I-NEXT: xor a0, a0, a1
436 ; CHECK-ZBB-LABEL: in_complex_m0:
437 ; CHECK-ZBB: # %bb.0:
438 ; CHECK-ZBB-NEXT: xor a2, a2, a3
439 ; CHECK-ZBB-NEXT: andn a1, a1, a2
440 ; CHECK-ZBB-NEXT: and a0, a0, a2
441 ; CHECK-ZBB-NEXT: or a0, a0, a1
442 ; CHECK-ZBB-NEXT: ret
443 %mask = xor i32 %m_a, %m_b
445 %n1 = and i32 %n0, %mask
450 define i32 @in_complex_m1(i32 %x, i32 %y, i32 %m_a, i32 %m_b) {
451 ; CHECK-I-LABEL: in_complex_m1:
453 ; CHECK-I-NEXT: xor a2, a2, a3
454 ; CHECK-I-NEXT: xor a0, a0, a1
455 ; CHECK-I-NEXT: and a0, a2, a0
456 ; CHECK-I-NEXT: xor a0, a0, a1
459 ; CHECK-ZBB-LABEL: in_complex_m1:
460 ; CHECK-ZBB: # %bb.0:
461 ; CHECK-ZBB-NEXT: xor a2, a2, a3
462 ; CHECK-ZBB-NEXT: andn a1, a1, a2
463 ; CHECK-ZBB-NEXT: and a0, a0, a2
464 ; CHECK-ZBB-NEXT: or a0, a0, a1
465 ; CHECK-ZBB-NEXT: ret
466 %mask = xor i32 %m_a, %m_b
468 %n1 = and i32 %mask, %n0
473 ; ============================================================================ ;
474 ; Both Y and M are complex.
475 ; ============================================================================ ;
477 define i32 @in_complex_y0_m0(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
478 ; CHECK-I-LABEL: in_complex_y0_m0:
480 ; CHECK-I-NEXT: and a1, a1, a2
481 ; CHECK-I-NEXT: xor a3, a3, a4
482 ; CHECK-I-NEXT: xor a0, a0, a1
483 ; CHECK-I-NEXT: and a0, a0, a3
484 ; CHECK-I-NEXT: xor a0, a0, a1
487 ; CHECK-ZBB-LABEL: in_complex_y0_m0:
488 ; CHECK-ZBB: # %bb.0:
489 ; CHECK-ZBB-NEXT: and a1, a1, a2
490 ; CHECK-ZBB-NEXT: xor a3, a3, a4
491 ; CHECK-ZBB-NEXT: andn a1, a1, a3
492 ; CHECK-ZBB-NEXT: and a0, a0, a3
493 ; CHECK-ZBB-NEXT: or a0, a0, a1
494 ; CHECK-ZBB-NEXT: ret
495 %y = and i32 %y_hi, %y_low
496 %mask = xor i32 %m_a, %m_b
498 %n1 = and i32 %n0, %mask
503 define i32 @in_complex_y1_m0(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
504 ; CHECK-I-LABEL: in_complex_y1_m0:
506 ; CHECK-I-NEXT: and a1, a1, a2
507 ; CHECK-I-NEXT: xor a3, a3, a4
508 ; CHECK-I-NEXT: xor a0, a0, a1
509 ; CHECK-I-NEXT: and a0, a0, a3
510 ; CHECK-I-NEXT: xor a0, a1, a0
513 ; CHECK-ZBB-LABEL: in_complex_y1_m0:
514 ; CHECK-ZBB: # %bb.0:
515 ; CHECK-ZBB-NEXT: and a1, a1, a2
516 ; CHECK-ZBB-NEXT: xor a3, a3, a4
517 ; CHECK-ZBB-NEXT: andn a1, a1, a3
518 ; CHECK-ZBB-NEXT: and a0, a0, a3
519 ; CHECK-ZBB-NEXT: or a0, a0, a1
520 ; CHECK-ZBB-NEXT: ret
521 %y = and i32 %y_hi, %y_low
522 %mask = xor i32 %m_a, %m_b
524 %n1 = and i32 %n0, %mask
529 define i32 @in_complex_y0_m1(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
530 ; CHECK-I-LABEL: in_complex_y0_m1:
532 ; CHECK-I-NEXT: and a1, a1, a2
533 ; CHECK-I-NEXT: xor a3, a3, a4
534 ; CHECK-I-NEXT: xor a0, a0, a1
535 ; CHECK-I-NEXT: and a0, a3, a0
536 ; CHECK-I-NEXT: xor a0, a0, a1
539 ; CHECK-ZBB-LABEL: in_complex_y0_m1:
540 ; CHECK-ZBB: # %bb.0:
541 ; CHECK-ZBB-NEXT: and a1, a1, a2
542 ; CHECK-ZBB-NEXT: xor a3, a3, a4
543 ; CHECK-ZBB-NEXT: andn a1, a1, a3
544 ; CHECK-ZBB-NEXT: and a0, a0, a3
545 ; CHECK-ZBB-NEXT: or a0, a0, a1
546 ; CHECK-ZBB-NEXT: ret
547 %y = and i32 %y_hi, %y_low
548 %mask = xor i32 %m_a, %m_b
550 %n1 = and i32 %mask, %n0
555 define i32 @in_complex_y1_m1(i32 %x, i32 %y_hi, i32 %y_low, i32 %m_a, i32 %m_b) {
556 ; CHECK-I-LABEL: in_complex_y1_m1:
558 ; CHECK-I-NEXT: and a1, a1, a2
559 ; CHECK-I-NEXT: xor a3, a3, a4
560 ; CHECK-I-NEXT: xor a0, a0, a1
561 ; CHECK-I-NEXT: and a0, a3, a0
562 ; CHECK-I-NEXT: xor a0, a1, a0
565 ; CHECK-ZBB-LABEL: in_complex_y1_m1:
566 ; CHECK-ZBB: # %bb.0:
567 ; CHECK-ZBB-NEXT: and a1, a1, a2
568 ; CHECK-ZBB-NEXT: xor a3, a3, a4
569 ; CHECK-ZBB-NEXT: andn a1, a1, a3
570 ; CHECK-ZBB-NEXT: and a0, a0, a3
571 ; CHECK-ZBB-NEXT: or a0, a0, a1
572 ; CHECK-ZBB-NEXT: ret
573 %y = and i32 %y_hi, %y_low
574 %mask = xor i32 %m_a, %m_b
576 %n1 = and i32 %mask, %n0
581 ; ============================================================================ ;
582 ; Various cases with %x and/or %y being a constant
583 ; ============================================================================ ;
585 define i32 @out_constant_varx_mone(i32 %x, i32 %y, i32 %mask) {
586 ; CHECK-I-LABEL: out_constant_varx_mone:
588 ; CHECK-I-NEXT: not a1, a2
589 ; CHECK-I-NEXT: and a0, a2, a0
590 ; CHECK-I-NEXT: or a0, a0, a1
593 ; CHECK-ZBB-LABEL: out_constant_varx_mone:
594 ; CHECK-ZBB: # %bb.0:
595 ; CHECK-ZBB-NEXT: and a0, a2, a0
596 ; CHECK-ZBB-NEXT: orn a0, a0, a2
597 ; CHECK-ZBB-NEXT: ret
598 %notmask = xor i32 %mask, -1
599 %mx = and i32 %mask, %x
600 %my = and i32 %notmask, -1
605 define i32 @in_constant_varx_mone(i32 %x, i32 %y, i32 %mask) {
606 ; CHECK-I-LABEL: in_constant_varx_mone:
608 ; CHECK-I-NEXT: not a0, a0
609 ; CHECK-I-NEXT: and a0, a0, a2
610 ; CHECK-I-NEXT: not a0, a0
613 ; CHECK-ZBB-LABEL: in_constant_varx_mone:
614 ; CHECK-ZBB: # %bb.0:
615 ; CHECK-ZBB-NEXT: andn a0, a2, a0
616 ; CHECK-ZBB-NEXT: not a0, a0
617 ; CHECK-ZBB-NEXT: ret
618 %n0 = xor i32 %x, -1 ; %x
619 %n1 = and i32 %n0, %mask
624 ; This is not a canonical form. Testing for completeness only.
625 define i32 @out_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
626 ; CHECK-LABEL: out_constant_varx_mone_invmask:
628 ; CHECK-NEXT: or a0, a0, a2
630 %notmask = xor i32 %mask, -1
631 %mx = and i32 %notmask, %x
632 %my = and i32 %mask, -1
637 ; This is not a canonical form. Testing for completeness only.
638 define i32 @in_constant_varx_mone_invmask(i32 %x, i32 %y, i32 %mask) {
639 ; CHECK-I-LABEL: in_constant_varx_mone_invmask:
641 ; CHECK-I-NEXT: not a1, a2
642 ; CHECK-I-NEXT: not a0, a0
643 ; CHECK-I-NEXT: and a0, a0, a1
644 ; CHECK-I-NEXT: not a0, a0
647 ; CHECK-ZBB-LABEL: in_constant_varx_mone_invmask:
648 ; CHECK-ZBB: # %bb.0:
649 ; CHECK-ZBB-NEXT: not a0, a0
650 ; CHECK-ZBB-NEXT: andn a0, a0, a2
651 ; CHECK-ZBB-NEXT: not a0, a0
652 ; CHECK-ZBB-NEXT: ret
653 %notmask = xor i32 %mask, -1
654 %n0 = xor i32 %x, -1 ; %x
655 %n1 = and i32 %n0, %notmask
660 define i32 @out_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
661 ; CHECK-I-LABEL: out_constant_varx_42:
663 ; CHECK-I-NEXT: not a1, a2
664 ; CHECK-I-NEXT: and a0, a2, a0
665 ; CHECK-I-NEXT: andi a1, a1, 42
666 ; CHECK-I-NEXT: or a0, a0, a1
669 ; CHECK-ZBB-LABEL: out_constant_varx_42:
670 ; CHECK-ZBB: # %bb.0:
671 ; CHECK-ZBB-NEXT: and a0, a2, a0
672 ; CHECK-ZBB-NEXT: li a1, 42
673 ; CHECK-ZBB-NEXT: andn a1, a1, a2
674 ; CHECK-ZBB-NEXT: or a0, a0, a1
675 ; CHECK-ZBB-NEXT: ret
676 %notmask = xor i32 %mask, -1
677 %mx = and i32 %mask, %x
678 %my = and i32 %notmask, 42
683 define i32 @in_constant_varx_42(i32 %x, i32 %y, i32 %mask) {
684 ; CHECK-I-LABEL: in_constant_varx_42:
686 ; CHECK-I-NEXT: xori a0, a0, 42
687 ; CHECK-I-NEXT: and a0, a0, a2
688 ; CHECK-I-NEXT: xori a0, a0, 42
691 ; CHECK-ZBB-LABEL: in_constant_varx_42:
692 ; CHECK-ZBB: # %bb.0:
693 ; CHECK-ZBB-NEXT: andn a0, a2, a0
694 ; CHECK-ZBB-NEXT: ori a1, a2, 42
695 ; CHECK-ZBB-NEXT: andn a0, a1, a0
696 ; CHECK-ZBB-NEXT: ret
697 %n0 = xor i32 %x, 42 ; %x
698 %n1 = and i32 %n0, %mask
703 ; This is not a canonical form. Testing for completeness only.
704 define i32 @out_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
705 ; CHECK-I-LABEL: out_constant_varx_42_invmask:
707 ; CHECK-I-NEXT: not a1, a2
708 ; CHECK-I-NEXT: and a0, a1, a0
709 ; CHECK-I-NEXT: andi a1, a2, 42
710 ; CHECK-I-NEXT: or a0, a0, a1
713 ; CHECK-ZBB-LABEL: out_constant_varx_42_invmask:
714 ; CHECK-ZBB: # %bb.0:
715 ; CHECK-ZBB-NEXT: andn a0, a0, a2
716 ; CHECK-ZBB-NEXT: andi a1, a2, 42
717 ; CHECK-ZBB-NEXT: or a0, a0, a1
718 ; CHECK-ZBB-NEXT: ret
719 %notmask = xor i32 %mask, -1
720 %mx = and i32 %notmask, %x
721 %my = and i32 %mask, 42
726 ; This is not a canonical form. Testing for completeness only.
727 define i32 @in_constant_varx_42_invmask(i32 %x, i32 %y, i32 %mask) {
728 ; CHECK-I-LABEL: in_constant_varx_42_invmask:
730 ; CHECK-I-NEXT: not a1, a2
731 ; CHECK-I-NEXT: xori a0, a0, 42
732 ; CHECK-I-NEXT: and a0, a0, a1
733 ; CHECK-I-NEXT: xori a0, a0, 42
736 ; CHECK-ZBB-LABEL: in_constant_varx_42_invmask:
737 ; CHECK-ZBB: # %bb.0:
738 ; CHECK-ZBB-NEXT: andn a0, a0, a2
739 ; CHECK-ZBB-NEXT: andi a1, a2, 42
740 ; CHECK-ZBB-NEXT: or a0, a0, a1
741 ; CHECK-ZBB-NEXT: ret
742 %notmask = xor i32 %mask, -1
743 %n0 = xor i32 %x, 42 ; %x
744 %n1 = and i32 %n0, %notmask
749 define i32 @out_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
750 ; CHECK-LABEL: out_constant_mone_vary:
752 ; CHECK-NEXT: or a0, a1, a2
754 %notmask = xor i32 %mask, -1
755 %mx = and i32 %mask, -1
756 %my = and i32 %notmask, %y
761 define i32 @in_constant_mone_vary(i32 %x, i32 %y, i32 %mask) {
762 ; CHECK-LABEL: in_constant_mone_vary:
764 ; CHECK-NEXT: or a0, a2, a1
766 %n0 = xor i32 -1, %y ; %x
767 %n1 = and i32 %n0, %mask
772 ; This is not a canonical form. Testing for completeness only.
773 define i32 @out_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
774 ; CHECK-I-LABEL: out_constant_mone_vary_invmask:
776 ; CHECK-I-NEXT: not a0, a2
777 ; CHECK-I-NEXT: and a1, a2, a1
778 ; CHECK-I-NEXT: or a0, a0, a1
781 ; CHECK-ZBB-LABEL: out_constant_mone_vary_invmask:
782 ; CHECK-ZBB: # %bb.0:
783 ; CHECK-ZBB-NEXT: and a1, a2, a1
784 ; CHECK-ZBB-NEXT: orn a0, a1, a2
785 ; CHECK-ZBB-NEXT: ret
786 %notmask = xor i32 %mask, -1
787 %mx = and i32 %notmask, -1
788 %my = and i32 %mask, %y
793 ; This is not a canonical form. Testing for completeness only.
794 define i32 @in_constant_mone_vary_invmask(i32 %x, i32 %y, i32 %mask) {
795 ; CHECK-I-LABEL: in_constant_mone_vary_invmask:
797 ; CHECK-I-NEXT: not a0, a2
798 ; CHECK-I-NEXT: or a0, a0, a1
801 ; CHECK-ZBB-LABEL: in_constant_mone_vary_invmask:
802 ; CHECK-ZBB: # %bb.0:
803 ; CHECK-ZBB-NEXT: orn a0, a1, a2
804 ; CHECK-ZBB-NEXT: ret
805 %notmask = xor i32 %mask, -1
806 %n0 = xor i32 -1, %y ; %x
807 %n1 = and i32 %n0, %notmask
812 define i32 @out_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
813 ; CHECK-I-LABEL: out_constant_42_vary:
815 ; CHECK-I-NEXT: not a0, a2
816 ; CHECK-I-NEXT: andi a2, a2, 42
817 ; CHECK-I-NEXT: and a0, a0, a1
818 ; CHECK-I-NEXT: or a0, a2, a0
821 ; CHECK-ZBB-LABEL: out_constant_42_vary:
822 ; CHECK-ZBB: # %bb.0:
823 ; CHECK-ZBB-NEXT: andi a0, a2, 42
824 ; CHECK-ZBB-NEXT: andn a1, a1, a2
825 ; CHECK-ZBB-NEXT: or a0, a0, a1
826 ; CHECK-ZBB-NEXT: ret
827 %notmask = xor i32 %mask, -1
828 %mx = and i32 %mask, 42
829 %my = and i32 %notmask, %y
834 define i32 @in_constant_42_vary(i32 %x, i32 %y, i32 %mask) {
835 ; CHECK-I-LABEL: in_constant_42_vary:
837 ; CHECK-I-NEXT: xori a0, a1, 42
838 ; CHECK-I-NEXT: and a0, a0, a2
839 ; CHECK-I-NEXT: xor a0, a0, a1
842 ; CHECK-ZBB-LABEL: in_constant_42_vary:
843 ; CHECK-ZBB: # %bb.0:
844 ; CHECK-ZBB-NEXT: andn a0, a1, a2
845 ; CHECK-ZBB-NEXT: andi a1, a2, 42
846 ; CHECK-ZBB-NEXT: or a0, a1, a0
847 ; CHECK-ZBB-NEXT: ret
848 %n0 = xor i32 42, %y ; %x
849 %n1 = and i32 %n0, %mask
854 ; This is not a canonical form. Testing for completeness only.
855 define i32 @out_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
856 ; CHECK-I-LABEL: out_constant_42_vary_invmask:
858 ; CHECK-I-NEXT: not a0, a2
859 ; CHECK-I-NEXT: andi a0, a0, 42
860 ; CHECK-I-NEXT: and a1, a2, a1
861 ; CHECK-I-NEXT: or a0, a0, a1
864 ; CHECK-ZBB-LABEL: out_constant_42_vary_invmask:
865 ; CHECK-ZBB: # %bb.0:
866 ; CHECK-ZBB-NEXT: li a0, 42
867 ; CHECK-ZBB-NEXT: andn a0, a0, a2
868 ; CHECK-ZBB-NEXT: and a1, a2, a1
869 ; CHECK-ZBB-NEXT: or a0, a0, a1
870 ; CHECK-ZBB-NEXT: ret
871 %notmask = xor i32 %mask, -1
872 %mx = and i32 %notmask, 42
873 %my = and i32 %mask, %y
878 ; This is not a canonical form. Testing for completeness only.
879 define i32 @in_constant_42_vary_invmask(i32 %x, i32 %y, i32 %mask) {
880 ; CHECK-I-LABEL: in_constant_42_vary_invmask:
882 ; CHECK-I-NEXT: not a0, a2
883 ; CHECK-I-NEXT: xori a2, a1, 42
884 ; CHECK-I-NEXT: and a0, a2, a0
885 ; CHECK-I-NEXT: xor a0, a0, a1
888 ; CHECK-ZBB-LABEL: in_constant_42_vary_invmask:
889 ; CHECK-ZBB: # %bb.0:
890 ; CHECK-ZBB-NEXT: andn a0, a2, a1
891 ; CHECK-ZBB-NEXT: ori a1, a2, 42
892 ; CHECK-ZBB-NEXT: andn a0, a1, a0
893 ; CHECK-ZBB-NEXT: ret
894 %notmask = xor i32 %mask, -1
895 %n0 = xor i32 42, %y ; %x
896 %n1 = and i32 %n0, %notmask
901 ; ============================================================================ ;
902 ; Negative tests. Should not be folded.
903 ; ============================================================================ ;
906 declare void @use32(i32) nounwind
907 define i32 @in_multiuse_A(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
908 ; RV32-LABEL: in_multiuse_A:
910 ; RV32-NEXT: addi sp, sp, -16
911 ; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
912 ; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
913 ; RV32-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
914 ; RV32-NEXT: mv s0, a1
915 ; RV32-NEXT: xor a0, a0, a1
916 ; RV32-NEXT: and s1, a0, a3
917 ; RV32-NEXT: mv a0, s1
918 ; RV32-NEXT: call use32
919 ; RV32-NEXT: xor a0, s1, s0
920 ; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
921 ; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
922 ; RV32-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
923 ; RV32-NEXT: addi sp, sp, 16
926 ; RV64-LABEL: in_multiuse_A:
928 ; RV64-NEXT: addi sp, sp, -32
929 ; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
930 ; RV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
931 ; RV64-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
932 ; RV64-NEXT: mv s0, a1
933 ; RV64-NEXT: xor a0, a0, a1
934 ; RV64-NEXT: and s1, a0, a3
935 ; RV64-NEXT: mv a0, s1
936 ; RV64-NEXT: call use32
937 ; RV64-NEXT: xor a0, s1, s0
938 ; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
939 ; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
940 ; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
941 ; RV64-NEXT: addi sp, sp, 32
944 %n1 = and i32 %n0, %mask
945 call void @use32(i32 %n1)
950 define i32 @in_multiuse_B(i32 %x, i32 %y, i32 %z, i32 %mask) nounwind {
951 ; RV32-LABEL: in_multiuse_B:
953 ; RV32-NEXT: addi sp, sp, -16
954 ; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
955 ; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
956 ; RV32-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
957 ; RV32-NEXT: mv s0, a1
958 ; RV32-NEXT: xor a0, a0, a1
959 ; RV32-NEXT: and s1, a0, a3
960 ; RV32-NEXT: call use32
961 ; RV32-NEXT: xor a0, s1, s0
962 ; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
963 ; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
964 ; RV32-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
965 ; RV32-NEXT: addi sp, sp, 16
968 ; RV64-LABEL: in_multiuse_B:
970 ; RV64-NEXT: addi sp, sp, -32
971 ; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
972 ; RV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
973 ; RV64-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
974 ; RV64-NEXT: mv s0, a1
975 ; RV64-NEXT: xor a0, a0, a1
976 ; RV64-NEXT: and s1, a0, a3
977 ; RV64-NEXT: call use32
978 ; RV64-NEXT: xor a0, s1, s0
979 ; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
980 ; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
981 ; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
982 ; RV64-NEXT: addi sp, sp, 32
985 %n1 = and i32 %n0, %mask
986 call void @use32(i32 %n0)
991 ; Various bad variants
992 define i32 @n0_badmask(i32 %x, i32 %y, i32 %mask, i32 %mask2) {
993 ; CHECK-I-LABEL: n0_badmask:
995 ; CHECK-I-NEXT: and a0, a0, a2
996 ; CHECK-I-NEXT: not a2, a3
997 ; CHECK-I-NEXT: and a1, a1, a2
998 ; CHECK-I-NEXT: or a0, a0, a1
1001 ; CHECK-ZBB-LABEL: n0_badmask:
1002 ; CHECK-ZBB: # %bb.0:
1003 ; CHECK-ZBB-NEXT: and a0, a0, a2
1004 ; CHECK-ZBB-NEXT: andn a1, a1, a3
1005 ; CHECK-ZBB-NEXT: or a0, a0, a1
1006 ; CHECK-ZBB-NEXT: ret
1007 %mx = and i32 %x, %mask
1008 %notmask = xor i32 %mask2, -1 ; %mask2 instead of %mask
1009 %my = and i32 %y, %notmask
1010 %r = or i32 %mx, %my
1014 define i32 @n0_badxor(i32 %x, i32 %y, i32 %mask) {
1015 ; CHECK-LABEL: n0_badxor:
1017 ; CHECK-NEXT: and a0, a0, a2
1018 ; CHECK-NEXT: xori a2, a2, 1
1019 ; CHECK-NEXT: and a1, a1, a2
1020 ; CHECK-NEXT: or a0, a0, a1
1022 %mx = and i32 %x, %mask
1023 %notmask = xor i32 %mask, 1 ; instead of -1
1024 %my = and i32 %y, %notmask
1025 %r = or i32 %mx, %my
1029 define i32 @n1_thirdvar(i32 %x, i32 %y, i32 %z, i32 %mask) {
1030 ; CHECK-LABEL: n1_thirdvar:
1032 ; CHECK-NEXT: xor a0, a0, a1
1033 ; CHECK-NEXT: and a0, a0, a3
1034 ; CHECK-NEXT: xor a0, a0, a2
1036 %n0 = xor i32 %x, %y
1037 %n1 = and i32 %n0, %mask
1038 %r = xor i32 %n1, %z ; instead of %y