1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
5 declare void @use32(i32)
7 ; There should be no 'and' instructions left in any test.
9 define i32 @test1(i32 %A) {
10 ; CHECK-LABEL: @test1(
11 ; CHECK-NEXT: ret i32 0
17 define i32 @test2(i32 %A) {
18 ; CHECK-LABEL: @test2(
19 ; CHECK-NEXT: ret i32 [[A:%.*]]
25 define i1 @test3(i1 %A) {
26 ; CHECK-LABEL: @test3(
27 ; CHECK-NEXT: ret i1 false
33 define i1 @test3_logical(i1 %A) {
34 ; CHECK-LABEL: @test3_logical(
35 ; CHECK-NEXT: ret i1 false
37 %B = select i1 %A, i1 false, i1 false
41 define i1 @test4(i1 %A) {
42 ; CHECK-LABEL: @test4(
43 ; CHECK-NEXT: ret i1 [[A:%.*]]
49 define i1 @test4_logical(i1 %A) {
50 ; CHECK-LABEL: @test4_logical(
51 ; CHECK-NEXT: ret i1 [[A:%.*]]
53 %B = select i1 %A, i1 true, i1 false
57 define i32 @test5(i32 %A) {
58 ; CHECK-LABEL: @test5(
59 ; CHECK-NEXT: ret i32 [[A:%.*]]
65 define i1 @test6(i1 %A) {
66 ; CHECK-LABEL: @test6(
67 ; CHECK-NEXT: ret i1 [[A:%.*]]
73 define i1 @test6_logical(i1 %A) {
74 ; CHECK-LABEL: @test6_logical(
75 ; CHECK-NEXT: ret i1 [[A:%.*]]
77 %B = select i1 %A, i1 %A, i1 false
82 define i32 @test7(i32 %A) {
83 ; CHECK-LABEL: @test7(
84 ; CHECK-NEXT: ret i32 0
86 %NotA = xor i32 %A, -1
87 %B = and i32 %A, %NotA
92 define i8 @test8(i8 %A) {
93 ; CHECK-LABEL: @test8(
94 ; CHECK-NEXT: ret i8 0
101 ; Test of sign bit, convert to setle %A, 0
102 define i1 @test9(i32 %A) {
103 ; CHECK-LABEL: @test9(
104 ; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A:%.*]], 0
105 ; CHECK-NEXT: ret i1 [[C]]
107 %B = and i32 %A, -2147483648
108 %C = icmp ne i32 %B, 0
112 ; Test of sign bit, convert to setle %A, 0
113 define i1 @test9a(i32 %A) {
114 ; CHECK-LABEL: @test9a(
115 ; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A:%.*]], 0
116 ; CHECK-NEXT: ret i1 [[C]]
118 %B = and i32 %A, -2147483648
119 %C = icmp ne i32 %B, 0
123 define i32 @test10(i32 %A) {
124 ; CHECK-LABEL: @test10(
125 ; CHECK-NEXT: ret i32 1
129 ; (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
134 define i32 @test11(i32 %A, i32* %P) {
135 ; CHECK-LABEL: @test11(
136 ; CHECK-NEXT: [[B:%.*]] = or i32 [[A:%.*]], 3
137 ; CHECK-NEXT: [[C:%.*]] = xor i32 [[B]], 12
138 ; CHECK-NEXT: store i32 [[C]], i32* [[P:%.*]], align 4
139 ; CHECK-NEXT: ret i32 3
143 ; additional use of C
144 store i32 %C, i32* %P
145 ; %C = and uint %B, 3 --> 3
150 define i1 @test12(i32 %A, i32 %B) {
151 ; CHECK-LABEL: @test12(
152 ; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
153 ; CHECK-NEXT: ret i1 [[C1]]
155 %C1 = icmp ult i32 %A, %B
156 %C2 = icmp ule i32 %A, %B
157 ; (A < B) & (A <= B) === (A < B)
162 define i1 @test12_logical(i32 %A, i32 %B) {
163 ; CHECK-LABEL: @test12_logical(
164 ; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]]
165 ; CHECK-NEXT: ret i1 [[C1]]
167 %C1 = icmp ult i32 %A, %B
168 %C2 = icmp ule i32 %A, %B
169 ; (A < B) & (A <= B) === (A < B)
170 %D = select i1 %C1, i1 %C2, i1 false
174 define i1 @test13(i32 %A, i32 %B) {
175 ; CHECK-LABEL: @test13(
176 ; CHECK-NEXT: ret i1 false
178 %C1 = icmp ult i32 %A, %B
179 %C2 = icmp ugt i32 %A, %B
180 ; (A < B) & (A > B) === false
185 define i1 @test13_logical(i32 %A, i32 %B) {
186 ; CHECK-LABEL: @test13_logical(
187 ; CHECK-NEXT: ret i1 false
189 %C1 = icmp ult i32 %A, %B
190 %C2 = icmp ugt i32 %A, %B
191 ; (A < B) & (A > B) === false
192 %D = select i1 %C1, i1 %C2, i1 false
196 define i1 @test14(i8 %A) {
197 ; CHECK-LABEL: @test14(
198 ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[A:%.*]], 0
199 ; CHECK-NEXT: ret i1 [[C]]
202 %C = icmp ne i8 %B, 0
206 define i8 @test15(i8 %A) {
207 ; CHECK-LABEL: @test15(
208 ; CHECK-NEXT: ret i8 0
216 define i8 @test16(i8 %A) {
217 ; CHECK-LABEL: @test16(
218 ; CHECK-NEXT: ret i8 0
225 define i1 @test18(i32 %A) {
226 ; CHECK-LABEL: @test18(
227 ; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A:%.*]], 127
228 ; CHECK-NEXT: ret i1 [[C]]
230 %B = and i32 %A, -128
232 %C = icmp ne i32 %B, 0
236 define <2 x i1> @test18_vec(<2 x i32> %A) {
237 ; CHECK-LABEL: @test18_vec(
238 ; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i32> [[A:%.*]], <i32 127, i32 127>
239 ; CHECK-NEXT: ret <2 x i1> [[C]]
241 %B = and <2 x i32> %A, <i32 -128, i32 -128>
242 %C = icmp ne <2 x i32> %B, zeroinitializer
246 define i1 @test18a(i8 %A) {
247 ; CHECK-LABEL: @test18a(
248 ; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[A:%.*]], 2
249 ; CHECK-NEXT: ret i1 [[C]]
252 %C = icmp eq i8 %B, 0
256 define <2 x i1> @test18a_vec(<2 x i8> %A) {
257 ; CHECK-LABEL: @test18a_vec(
258 ; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i8> [[A:%.*]], <i8 2, i8 2>
259 ; CHECK-NEXT: ret <2 x i1> [[C]]
261 %B = and <2 x i8> %A, <i8 -2, i8 -2>
262 %C = icmp eq <2 x i8> %B, zeroinitializer
266 define i32 @test19(i32 %A) {
267 ; CHECK-LABEL: @test19(
268 ; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 3
269 ; CHECK-NEXT: ret i32 [[B]]
272 ;; Clearing a zero bit
277 define i8 @test20(i8 %A) {
278 ; CHECK-LABEL: @test20(
279 ; CHECK-NEXT: [[C:%.*]] = lshr i8 [[A:%.*]], 7
280 ; CHECK-NEXT: ret i8 [[C]]
288 define i1 @test23(i32 %A) {
289 ; CHECK-LABEL: @test23(
290 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], 2
291 ; CHECK-NEXT: ret i1 [[TMP1]]
293 %B = icmp sgt i32 %A, 1
294 %C = icmp sle i32 %A, 2
299 define i1 @test23_logical(i32 %A) {
300 ; CHECK-LABEL: @test23_logical(
301 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], 2
302 ; CHECK-NEXT: ret i1 [[TMP1]]
304 %B = icmp sgt i32 %A, 1
305 %C = icmp sle i32 %A, 2
306 %D = select i1 %B, i1 %C, i1 false
310 define <2 x i1> @test23vec(<2 x i32> %A) {
311 ; CHECK-LABEL: @test23vec(
312 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[A:%.*]], <i32 2, i32 2>
313 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
315 %B = icmp sgt <2 x i32> %A, <i32 1, i32 1>
316 %C = icmp sle <2 x i32> %A, <i32 2, i32 2>
317 %D = and <2 x i1> %B, %C
321 define i1 @test24(i32 %A) {
322 ; CHECK-LABEL: @test24(
323 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], 2
324 ; CHECK-NEXT: ret i1 [[TMP1]]
326 %B = icmp sgt i32 %A, 1
327 %C = icmp ne i32 %A, 2
333 define i1 @test24_logical(i32 %A) {
334 ; CHECK-LABEL: @test24_logical(
335 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], 2
336 ; CHECK-NEXT: ret i1 [[TMP1]]
338 %B = icmp sgt i32 %A, 1
339 %C = icmp ne i32 %A, 2
341 %D = select i1 %B, i1 %C, i1 false
345 define i1 @test25(i32 %A) {
346 ; CHECK-LABEL: @test25(
347 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -50
348 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 50
349 ; CHECK-NEXT: ret i1 [[TMP2]]
351 %B = icmp sge i32 %A, 50
352 %C = icmp slt i32 %A, 100
357 define i1 @test25_logical(i32 %A) {
358 ; CHECK-LABEL: @test25_logical(
359 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[A:%.*]], -50
360 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[TMP1]], 50
361 ; CHECK-NEXT: ret i1 [[TMP2]]
363 %B = icmp sge i32 %A, 50
364 %C = icmp slt i32 %A, 100
365 %D = select i1 %B, i1 %C, i1 false
369 define <2 x i1> @test25vec(<2 x i32> %A) {
370 ; CHECK-LABEL: @test25vec(
371 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[A:%.*]], <i32 -50, i32 -50>
372 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 50, i32 50>
373 ; CHECK-NEXT: ret <2 x i1> [[TMP2]]
375 %B = icmp sge <2 x i32> %A, <i32 50, i32 50>
376 %C = icmp slt <2 x i32> %A, <i32 100, i32 100>
377 %D = and <2 x i1> %B, %C
381 define i8 @test27(i8 %A) {
382 ; CHECK-LABEL: @test27(
383 ; CHECK-NEXT: ret i8 0
393 ;; This is just a zero-extending shr.
394 define i32 @test28(i32 %X) {
395 ; CHECK-LABEL: @test28(
396 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 24
397 ; CHECK-NEXT: ret i32 [[TMP1]]
401 ;; Mask out sign bits
406 define i32 @test29(i8 %X) {
407 ; CHECK-LABEL: @test29(
408 ; CHECK-NEXT: [[Y:%.*]] = zext i8 [[X:%.*]] to i32
409 ; CHECK-NEXT: ret i32 [[Y]]
411 %Y = zext i8 %X to i32
412 ;; Zero extend makes this unneeded.
417 define i32 @test30(i1 %X) {
418 ; CHECK-LABEL: @test30(
419 ; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X:%.*]] to i32
420 ; CHECK-NEXT: ret i32 [[Y]]
422 %Y = zext i1 %X to i32
427 define i32 @test31(i1 %X) {
428 ; CHECK-LABEL: @test31(
429 ; CHECK-NEXT: [[Z:%.*]] = select i1 [[X:%.*]], i32 16, i32 0
430 ; CHECK-NEXT: ret i32 [[Z]]
432 %Y = zext i1 %X to i32
438 ; Demanded bit analysis allows us to eliminate the add.
440 define <2 x i32> @and_demanded_bits_splat_vec(<2 x i32> %x) {
441 ; CHECK-LABEL: @and_demanded_bits_splat_vec(
442 ; CHECK-NEXT: [[Z:%.*]] = and <2 x i32> [[X:%.*]], <i32 7, i32 7>
443 ; CHECK-NEXT: ret <2 x i32> [[Z]]
445 %y = add <2 x i32> %x, <i32 8, i32 8>
446 %z = and <2 x i32> %y, <i32 7, i32 7>
450 ; zext (x >> 8) has all zeros in the high 24-bits: 0x000000xx
451 ; (y | 255) has all ones in the low 8-bits: 0xyyyyyyff
452 ; 'and' of those is all known bits - it's just 'z'.
454 define i32 @and_zext_demanded(i16 %x, i32 %y) {
455 ; CHECK-LABEL: @and_zext_demanded(
456 ; CHECK-NEXT: [[S:%.*]] = lshr i16 [[X:%.*]], 8
457 ; CHECK-NEXT: [[Z:%.*]] = zext i16 [[S]] to i32
458 ; CHECK-NEXT: ret i32 [[Z]]
461 %z = zext i16 %s to i32
467 define i32 @test32(i32 %In) {
468 ; CHECK-LABEL: @test32(
469 ; CHECK-NEXT: ret i32 0
477 ;; Code corresponding to one-bit bitfield ^1.
478 define i32 @test33(i32 %b) {
479 ; CHECK-LABEL: @test33(
480 ; CHECK-NEXT: [[T13:%.*]] = xor i32 [[B:%.*]], 1
481 ; CHECK-NEXT: ret i32 [[T13]]
483 %t4.mask = and i32 %b, 1
484 %t10 = xor i32 %t4.mask, 1
485 %t12 = and i32 %b, -2
486 %t13 = or i32 %t12, %t10
490 define i32 @test33b(i32 %b) {
491 ; CHECK-LABEL: @test33b(
492 ; CHECK-NEXT: [[T13:%.*]] = xor i32 [[B:%.*]], 1
493 ; CHECK-NEXT: ret i32 [[T13]]
495 %t4.mask = and i32 %b, 1
496 %t10 = xor i32 %t4.mask, 1
497 %t12 = and i32 %b, -2
498 %t13 = or i32 %t10, %t12
502 define <2 x i32> @test33vec(<2 x i32> %b) {
503 ; CHECK-LABEL: @test33vec(
504 ; CHECK-NEXT: [[T13:%.*]] = xor <2 x i32> [[B:%.*]], <i32 1, i32 1>
505 ; CHECK-NEXT: ret <2 x i32> [[T13]]
507 %t4.mask = and <2 x i32> %b, <i32 1, i32 1>
508 %t10 = xor <2 x i32> %t4.mask, <i32 1, i32 1>
509 %t12 = and <2 x i32> %b, <i32 -2, i32 -2>
510 %t13 = or <2 x i32> %t12, %t10
514 define <2 x i32> @test33vecb(<2 x i32> %b) {
515 ; CHECK-LABEL: @test33vecb(
516 ; CHECK-NEXT: [[T13:%.*]] = xor <2 x i32> [[B:%.*]], <i32 1, i32 1>
517 ; CHECK-NEXT: ret <2 x i32> [[T13]]
519 %t4.mask = and <2 x i32> %b, <i32 1, i32 1>
520 %t10 = xor <2 x i32> %t4.mask, <i32 1, i32 1>
521 %t12 = and <2 x i32> %b, <i32 -2, i32 -2>
522 %t13 = or <2 x i32> %t10, %t12
526 define i32 @test34(i32 %A, i32 %B) {
527 ; CHECK-LABEL: @test34(
528 ; CHECK-NEXT: ret i32 [[B:%.*]]
531 %t4 = and i32 %t2, %B
535 ; FIXME: This test should only need -instsimplify (ValueTracking / computeKnownBits), not -instcombine.
537 define <2 x i32> @PR24942(<2 x i32> %x) {
538 ; CHECK-LABEL: @PR24942(
539 ; CHECK-NEXT: ret <2 x i32> zeroinitializer
541 %lshr = lshr <2 x i32> %x, <i32 31, i32 31>
542 %and = and <2 x i32> %lshr, <i32 2, i32 2>
546 define i64 @test35(i32 %X) {
547 ; CHECK-LABEL: @test35(
548 ; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]]
549 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 240
550 ; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP2]] to i64
551 ; CHECK-NEXT: ret i64 [[RES]]
553 %zext = zext i32 %X to i64
554 %zsub = sub i64 0, %zext
555 %res = and i64 %zsub, 240
559 define <2 x i64> @test35_uniform(<2 x i32> %X) {
560 ; CHECK-LABEL: @test35_uniform(
561 ; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
562 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 240, i32 240>
563 ; CHECK-NEXT: [[RES:%.*]] = zext <2 x i32> [[TMP2]] to <2 x i64>
564 ; CHECK-NEXT: ret <2 x i64> [[RES]]
566 %zext = zext <2 x i32> %X to <2 x i64>
567 %zsub = sub <2 x i64> zeroinitializer, %zext
568 %res = and <2 x i64> %zsub, <i64 240, i64 240>
572 define i64 @test36(i32 %X) {
573 ; CHECK-LABEL: @test36(
574 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 7
575 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 240
576 ; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP2]] to i64
577 ; CHECK-NEXT: ret i64 [[RES]]
579 %zext = zext i32 %X to i64
580 %zsub = add i64 %zext, 7
581 %res = and i64 %zsub, 240
585 define <2 x i64> @test36_uniform(<2 x i32> %X) {
586 ; CHECK-LABEL: @test36_uniform(
587 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], <i32 7, i32 7>
588 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 240, i32 240>
589 ; CHECK-NEXT: [[RES:%.*]] = zext <2 x i32> [[TMP2]] to <2 x i64>
590 ; CHECK-NEXT: ret <2 x i64> [[RES]]
592 %zext = zext <2 x i32> %X to <2 x i64>
593 %zsub = add <2 x i64> %zext, <i64 7, i64 7>
594 %res = and <2 x i64> %zsub, <i64 240, i64 240>
598 define <2 x i64> @test36_undef(<2 x i32> %X) {
599 ; CHECK-LABEL: @test36_undef(
600 ; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>
601 ; CHECK-NEXT: [[ZSUB:%.*]] = add <2 x i64> [[ZEXT]], <i64 7, i64 undef>
602 ; CHECK-NEXT: [[RES:%.*]] = and <2 x i64> [[ZSUB]], <i64 240, i64 undef>
603 ; CHECK-NEXT: ret <2 x i64> [[RES]]
605 %zext = zext <2 x i32> %X to <2 x i64>
606 %zsub = add <2 x i64> %zext, <i64 7, i64 undef>
607 %res = and <2 x i64> %zsub, <i64 240, i64 undef>
611 define i64 @test37(i32 %X) {
612 ; CHECK-LABEL: @test37(
613 ; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], 7
614 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 240
615 ; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP2]] to i64
616 ; CHECK-NEXT: ret i64 [[RES]]
618 %zext = zext i32 %X to i64
619 %zsub = mul i64 %zext, 7
620 %res = and i64 %zsub, 240
624 define <2 x i64> @test37_uniform(<2 x i32> %X) {
625 ; CHECK-LABEL: @test37_uniform(
626 ; CHECK-NEXT: [[TMP1:%.*]] = mul <2 x i32> [[X:%.*]], <i32 7, i32 7>
627 ; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], <i32 240, i32 240>
628 ; CHECK-NEXT: [[RES:%.*]] = zext <2 x i32> [[TMP2]] to <2 x i64>
629 ; CHECK-NEXT: ret <2 x i64> [[RES]]
631 %zext = zext <2 x i32> %X to <2 x i64>
632 %zsub = mul <2 x i64> %zext, <i64 7, i64 7>
633 %res = and <2 x i64> %zsub, <i64 240, i64 240>
637 define <2 x i64> @test37_nonuniform(<2 x i32> %X) {
638 ; CHECK-LABEL: @test37_nonuniform(
639 ; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>
640 ; CHECK-NEXT: [[ZSUB:%.*]] = mul nuw nsw <2 x i64> [[ZEXT]], <i64 7, i64 9>
641 ; CHECK-NEXT: [[RES:%.*]] = and <2 x i64> [[ZSUB]], <i64 240, i64 110>
642 ; CHECK-NEXT: ret <2 x i64> [[RES]]
644 %zext = zext <2 x i32> %X to <2 x i64>
645 %zsub = mul <2 x i64> %zext, <i64 7, i64 9>
646 %res = and <2 x i64> %zsub, <i64 240, i64 110>
650 define i64 @test38(i32 %X) {
651 ; CHECK-LABEL: @test38(
652 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240
653 ; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP1]] to i64
654 ; CHECK-NEXT: ret i64 [[RES]]
656 %zext = zext i32 %X to i64
657 %zsub = xor i64 %zext, 7
658 %res = and i64 %zsub, 240
662 define i64 @test39(i32 %X) {
663 ; CHECK-LABEL: @test39(
664 ; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240
665 ; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP1]] to i64
666 ; CHECK-NEXT: ret i64 [[RES]]
668 %zext = zext i32 %X to i64
669 %zsub = or i64 %zext, 7
670 %res = and i64 %zsub, 240
674 define i32 @test40(i1 %C) {
675 ; CHECK-LABEL: @test40(
676 ; CHECK-NEXT: [[A:%.*]] = select i1 [[C:%.*]], i32 104, i32 10
677 ; CHECK-NEXT: ret i32 [[A]]
679 %A = select i1 %C, i32 1000, i32 10
684 define <2 x i32> @test40vec(i1 %C) {
685 ; CHECK-LABEL: @test40vec(
686 ; CHECK-NEXT: [[A:%.*]] = select i1 [[C:%.*]], <2 x i32> <i32 104, i32 104>, <2 x i32> <i32 10, i32 10>
687 ; CHECK-NEXT: ret <2 x i32> [[A]]
689 %A = select i1 %C, <2 x i32> <i32 1000, i32 1000>, <2 x i32> <i32 10, i32 10>
690 %V = and <2 x i32> %A, <i32 123, i32 123>
694 define <2 x i32> @test40vec2(i1 %C) {
695 ; CHECK-LABEL: @test40vec2(
696 ; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], <2 x i32> <i32 104, i32 324>, <2 x i32> <i32 10, i32 12>
697 ; CHECK-NEXT: ret <2 x i32> [[V]]
699 %A = select i1 %C, <2 x i32> <i32 1000, i32 2500>, <2 x i32> <i32 10, i32 30>
700 %V = and <2 x i32> %A, <i32 123, i32 333>
704 define i32 @test41(i1 %which) {
705 ; CHECK-LABEL: @test41(
707 ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]
709 ; CHECK-NEXT: br label [[FINAL]]
711 ; CHECK-NEXT: [[A:%.*]] = phi i32 [ 104, [[ENTRY:%.*]] ], [ 10, [[DELAY]] ]
712 ; CHECK-NEXT: ret i32 [[A]]
715 br i1 %which, label %final, label %delay
721 %A = phi i32 [ 1000, %entry ], [ 10, %delay ]
722 %value = and i32 %A, 123
726 define <2 x i32> @test41vec(i1 %which) {
727 ; CHECK-LABEL: @test41vec(
729 ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]
731 ; CHECK-NEXT: br label [[FINAL]]
733 ; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ <i32 104, i32 104>, [[ENTRY:%.*]] ], [ <i32 10, i32 10>, [[DELAY]] ]
734 ; CHECK-NEXT: ret <2 x i32> [[A]]
737 br i1 %which, label %final, label %delay
743 %A = phi <2 x i32> [ <i32 1000, i32 1000>, %entry ], [ <i32 10, i32 10>, %delay ]
744 %value = and <2 x i32> %A, <i32 123, i32 123>
748 define <2 x i32> @test41vec2(i1 %which) {
749 ; CHECK-LABEL: @test41vec2(
751 ; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]
753 ; CHECK-NEXT: br label [[FINAL]]
755 ; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ <i32 104, i32 324>, [[ENTRY:%.*]] ], [ <i32 10, i32 12>, [[DELAY]] ]
756 ; CHECK-NEXT: ret <2 x i32> [[A]]
759 br i1 %which, label %final, label %delay
765 %A = phi <2 x i32> [ <i32 1000, i32 2500>, %entry ], [ <i32 10, i32 30>, %delay ]
766 %value = and <2 x i32> %A, <i32 123, i32 333>
770 define i32 @test42(i32 %a, i32 %c, i32 %d) {
771 ; CHECK-LABEL: @test42(
772 ; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[C:%.*]], [[D:%.*]]
773 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[FORCE]], [[A:%.*]]
774 ; CHECK-NEXT: ret i32 [[AND]]
776 %force = mul i32 %c, %d ; forces the complexity sorting
777 %or = or i32 %a, %force
778 %nota = xor i32 %a, -1
779 %xor = xor i32 %nota, %force
780 %and = and i32 %xor, %or
784 define i32 @test43(i32 %a, i32 %c, i32 %d) {
785 ; CHECK-LABEL: @test43(
786 ; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[C:%.*]], [[D:%.*]]
787 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[FORCE]], [[A:%.*]]
788 ; CHECK-NEXT: ret i32 [[AND]]
790 %force = mul i32 %c, %d ; forces the complexity sorting
791 %or = or i32 %a, %force
792 %nota = xor i32 %a, -1
793 %xor = xor i32 %nota, %force
794 %and = and i32 %or, %xor
798 ; (~y | x) & y -> x & y
799 define i32 @test44(i32 %x, i32 %y) nounwind {
800 ; CHECK-LABEL: @test44(
801 ; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
802 ; CHECK-NEXT: ret i32 [[A]]
810 ; (x | ~y) & y -> x & y
811 define i32 @test45(i32 %x, i32 %y) nounwind {
812 ; CHECK-LABEL: @test45(
813 ; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
814 ; CHECK-NEXT: ret i32 [[A]]
822 ; y & (~y | x) -> y | x
823 define i32 @test46(i32 %x, i32 %y) nounwind {
824 ; CHECK-LABEL: @test46(
825 ; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
826 ; CHECK-NEXT: ret i32 [[A]]
834 ; y & (x | ~y) -> y | x
835 define i32 @test47(i32 %x, i32 %y) nounwind {
836 ; CHECK-LABEL: @test47(
837 ; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
838 ; CHECK-NEXT: ret i32 [[A]]
846 ; In the next 4 tests, vary the types and predicates for extra coverage.
847 ; (X & (Y | ~X)) -> (X & Y), where 'not' is an inverted cmp
849 define i1 @and_orn_cmp_1(i32 %a, i32 %b, i32 %c) {
850 ; CHECK-LABEL: @and_orn_cmp_1(
851 ; CHECK-NEXT: [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
852 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42
853 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[X]], [[Y]]
854 ; CHECK-NEXT: ret i1 [[AND]]
856 %x = icmp sgt i32 %a, %b
857 %x_inv = icmp sle i32 %a, %b
858 %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering
859 %or = or i1 %y, %x_inv
860 %and = and i1 %x, %or
864 define i1 @and_orn_cmp_1_logical(i32 %a, i32 %b, i32 %c) {
865 ; CHECK-LABEL: @and_orn_cmp_1_logical(
866 ; CHECK-NEXT: [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]]
867 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42
868 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[X]], i1 [[Y]], i1 false
869 ; CHECK-NEXT: ret i1 [[AND]]
871 %x = icmp sgt i32 %a, %b
872 %x_inv = icmp sle i32 %a, %b
873 %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering
874 %or = select i1 %y, i1 true, i1 %x_inv
875 %and = select i1 %x, i1 %or, i1 false
880 ; ((Y | ~X) & X) -> (X & Y), where 'not' is an inverted cmp
882 define <2 x i1> @and_orn_cmp_2(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) {
883 ; CHECK-LABEL: @and_orn_cmp_2(
884 ; CHECK-NEXT: [[X:%.*]] = icmp sge <2 x i32> [[A:%.*]], [[B:%.*]]
885 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt <2 x i32> [[C:%.*]], <i32 42, i32 47>
886 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[Y]], [[X]]
887 ; CHECK-NEXT: ret <2 x i1> [[AND]]
889 %x = icmp sge <2 x i32> %a, %b
890 %x_inv = icmp slt <2 x i32> %a, %b
891 %y = icmp ugt <2 x i32> %c, <i32 42, i32 47> ; thwart complexity-based ordering
892 %or = or <2 x i1> %y, %x_inv
893 %and = and <2 x i1> %or, %x
898 ; (X & (~X | Y)) -> (X & Y), where 'not' is an inverted cmp
900 define i1 @and_orn_cmp_3(i72 %a, i72 %b, i72 %c) {
901 ; CHECK-LABEL: @and_orn_cmp_3(
902 ; CHECK-NEXT: [[X:%.*]] = icmp ugt i72 [[A:%.*]], [[B:%.*]]
903 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i72 [[C:%.*]], 42
904 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[X]], [[Y]]
905 ; CHECK-NEXT: ret i1 [[AND]]
907 %x = icmp ugt i72 %a, %b
908 %x_inv = icmp ule i72 %a, %b
909 %y = icmp ugt i72 %c, 42 ; thwart complexity-based ordering
910 %or = or i1 %x_inv, %y
911 %and = and i1 %x, %or
915 define i1 @and_orn_cmp_3_logical(i72 %a, i72 %b, i72 %c) {
916 ; CHECK-LABEL: @and_orn_cmp_3_logical(
917 ; CHECK-NEXT: [[X:%.*]] = icmp ugt i72 [[A:%.*]], [[B:%.*]]
918 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i72 [[C:%.*]], 42
919 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[X]], i1 [[Y]], i1 false
920 ; CHECK-NEXT: ret i1 [[AND]]
922 %x = icmp ugt i72 %a, %b
923 %x_inv = icmp ule i72 %a, %b
924 %y = icmp ugt i72 %c, 42 ; thwart complexity-based ordering
925 %or = select i1 %x_inv, i1 true, i1 %y
926 %and = select i1 %x, i1 %or, i1 false
931 ; ((~X | Y) & X) -> (X & Y), where 'not' is an inverted cmp
933 define <3 x i1> @or_andn_cmp_4(<3 x i32> %a, <3 x i32> %b, <3 x i32> %c) {
934 ; CHECK-LABEL: @or_andn_cmp_4(
935 ; CHECK-NEXT: [[X:%.*]] = icmp eq <3 x i32> [[A:%.*]], [[B:%.*]]
936 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt <3 x i32> [[C:%.*]], <i32 42, i32 43, i32 -1>
937 ; CHECK-NEXT: [[AND:%.*]] = and <3 x i1> [[Y]], [[X]]
938 ; CHECK-NEXT: ret <3 x i1> [[AND]]
940 %x = icmp eq <3 x i32> %a, %b
941 %x_inv = icmp ne <3 x i32> %a, %b
942 %y = icmp ugt <3 x i32> %c, <i32 42, i32 43, i32 -1> ; thwart complexity-based ordering
943 %or = or <3 x i1> %x_inv, %y
944 %and = and <3 x i1> %or, %x
948 ; In the next 4 tests, vary the types and predicates for extra coverage.
949 ; (~X & (Y | X)) -> (~X & Y), where 'not' is an inverted cmp
951 define i1 @andn_or_cmp_1(i37 %a, i37 %b, i37 %c) {
952 ; CHECK-LABEL: @andn_or_cmp_1(
953 ; CHECK-NEXT: [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]]
954 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i37 [[C:%.*]], 42
955 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[X_INV]], [[Y]]
956 ; CHECK-NEXT: ret i1 [[AND]]
958 %x = icmp sgt i37 %a, %b
959 %x_inv = icmp sle i37 %a, %b
960 %y = icmp ugt i37 %c, 42 ; thwart complexity-based ordering
962 %and = and i1 %x_inv, %or
966 define i1 @andn_or_cmp_1_logical(i37 %a, i37 %b, i37 %c) {
967 ; CHECK-LABEL: @andn_or_cmp_1_logical(
968 ; CHECK-NEXT: [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]]
969 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i37 [[C:%.*]], 42
970 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[X_INV]], i1 [[Y]], i1 false
971 ; CHECK-NEXT: ret i1 [[AND]]
973 %x = icmp sgt i37 %a, %b
974 %x_inv = icmp sle i37 %a, %b
975 %y = icmp ugt i37 %c, 42 ; thwart complexity-based ordering
976 %or = select i1 %y, i1 true, i1 %x
977 %and = select i1 %x_inv, i1 %or, i1 false
982 ; ((Y | X) & ~X) -> (~X & Y), where 'not' is an inverted cmp
984 define i1 @andn_or_cmp_2(i16 %a, i16 %b, i16 %c) {
985 ; CHECK-LABEL: @andn_or_cmp_2(
986 ; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
987 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i16 [[C:%.*]], 42
988 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[Y]], [[X_INV]]
989 ; CHECK-NEXT: ret i1 [[AND]]
991 %x = icmp sge i16 %a, %b
992 %x_inv = icmp slt i16 %a, %b
993 %y = icmp ugt i16 %c, 42 ; thwart complexity-based ordering
995 %and = and i1 %or, %x_inv
999 define i1 @andn_or_cmp_2_logical(i16 %a, i16 %b, i16 %c) {
1000 ; CHECK-LABEL: @andn_or_cmp_2_logical(
1001 ; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]]
1002 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i16 [[C:%.*]], 42
1003 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[Y]], i1 [[X_INV]], i1 false
1004 ; CHECK-NEXT: ret i1 [[AND]]
1006 %x = icmp sge i16 %a, %b
1007 %x_inv = icmp slt i16 %a, %b
1008 %y = icmp ugt i16 %c, 42 ; thwart complexity-based ordering
1009 %or = select i1 %y, i1 true, i1 %x
1010 %and = select i1 %or, i1 %x_inv, i1 false
1015 ; (~X & (X | Y)) -> (~X & Y), where 'not' is an inverted cmp
1017 define <4 x i1> @andn_or_cmp_3(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) {
1018 ; CHECK-LABEL: @andn_or_cmp_3(
1019 ; CHECK-NEXT: [[X_INV:%.*]] = icmp ule <4 x i32> [[A:%.*]], [[B:%.*]]
1020 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt <4 x i32> [[C:%.*]], <i32 42, i32 0, i32 1, i32 -1>
1021 ; CHECK-NEXT: [[AND:%.*]] = and <4 x i1> [[X_INV]], [[Y]]
1022 ; CHECK-NEXT: ret <4 x i1> [[AND]]
1024 %x = icmp ugt <4 x i32> %a, %b
1025 %x_inv = icmp ule <4 x i32> %a, %b
1026 %y = icmp ugt <4 x i32> %c, <i32 42, i32 0, i32 1, i32 -1> ; thwart complexity-based ordering
1027 %or = or <4 x i1> %x, %y
1028 %and = and <4 x i1> %x_inv, %or
1032 ; Commute the 'and':
1033 ; ((X | Y) & ~X) -> (~X & Y), where 'not' is an inverted cmp
1035 define i1 @andn_or_cmp_4(i32 %a, i32 %b, i32 %c) {
1036 ; CHECK-LABEL: @andn_or_cmp_4(
1037 ; CHECK-NEXT: [[X_INV:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
1038 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42
1039 ; CHECK-NEXT: [[AND:%.*]] = and i1 [[Y]], [[X_INV]]
1040 ; CHECK-NEXT: ret i1 [[AND]]
1042 %x = icmp eq i32 %a, %b
1043 %x_inv = icmp ne i32 %a, %b
1044 %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering
1046 %and = and i1 %or, %x_inv
1050 define i1 @andn_or_cmp_4_logical(i32 %a, i32 %b, i32 %c) {
1051 ; CHECK-LABEL: @andn_or_cmp_4_logical(
1052 ; CHECK-NEXT: [[X_INV:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]]
1053 ; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42
1054 ; CHECK-NEXT: [[AND:%.*]] = select i1 [[X_INV]], i1 [[Y]], i1 false
1055 ; CHECK-NEXT: ret i1 [[AND]]
1057 %x = icmp eq i32 %a, %b
1058 %x_inv = icmp ne i32 %a, %b
1059 %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering
1060 %or = select i1 %x, i1 true, i1 %y
1061 %and = select i1 %or, i1 %x_inv, i1 false
1065 define i32 @lowbitmask_casted_shift(i8 %x) {
1066 ; CHECK-LABEL: @lowbitmask_casted_shift(
1067 ; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32
1068 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[TMP1]], 1
1069 ; CHECK-NEXT: ret i32 [[R]]
1072 %s = sext i8 %a to i32
1073 %r = and i32 %s, 2147483647
1077 ; Negative test - mask constant is too big.
1079 define i32 @lowbitmask_casted_shift_wrong_mask1(i8 %x) {
1080 ; CHECK-LABEL: @lowbitmask_casted_shift_wrong_mask1(
1081 ; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 2
1082 ; CHECK-NEXT: [[S:%.*]] = sext i8 [[A]] to i32
1083 ; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 2147483647
1084 ; CHECK-NEXT: ret i32 [[R]]
1087 %s = sext i8 %a to i32
1088 %r = and i32 %s, 2147483647 ; 0x7fffffff
1092 ; Negative test - mask constant is too small.
1094 define i32 @lowbitmask_casted_shift_wrong_mask2(i8 %x) {
1095 ; CHECK-LABEL: @lowbitmask_casted_shift_wrong_mask2(
1096 ; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 2
1097 ; CHECK-NEXT: [[S:%.*]] = sext i8 [[A]] to i32
1098 ; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 536870911
1099 ; CHECK-NEXT: ret i32 [[R]]
1102 %s = sext i8 %a to i32
1103 %r = and i32 %s, 536870911 ; 0x1fffffff
1107 ; Extra use of shift is ok.
1109 define i32 @lowbitmask_casted_shift_use1(i8 %x) {
1110 ; CHECK-LABEL: @lowbitmask_casted_shift_use1(
1111 ; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 3
1112 ; CHECK-NEXT: call void @use8(i8 [[A]])
1113 ; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32
1114 ; CHECK-NEXT: [[R:%.*]] = lshr i32 [[TMP1]], 3
1115 ; CHECK-NEXT: ret i32 [[R]]
1118 call void @use8(i8 %a)
1119 %s = sext i8 %a to i32
1120 %r = and i32 %s, 536870911
1124 ; Negative test - extra use of sext requires more instructions.
1126 define i32 @lowbitmask_casted_shift_use2(i8 %x) {
1127 ; CHECK-LABEL: @lowbitmask_casted_shift_use2(
1128 ; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 3
1129 ; CHECK-NEXT: [[S:%.*]] = sext i8 [[A]] to i32
1130 ; CHECK-NEXT: call void @use32(i32 [[S]])
1131 ; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 536870911
1132 ; CHECK-NEXT: ret i32 [[R]]
1135 %s = sext i8 %a to i32
1136 call void @use32(i32 %s)
1137 %r = and i32 %s, 536870911
1141 ; Vectors/weird types are ok.
1143 define <2 x i59> @lowbitmask_casted_shift_vec_splat(<2 x i47> %x) {
1144 ; CHECK-LABEL: @lowbitmask_casted_shift_vec_splat(
1145 ; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i47> [[X:%.*]] to <2 x i59>
1146 ; CHECK-NEXT: [[R:%.*]] = lshr <2 x i59> [[TMP1]], <i59 5, i59 5>
1147 ; CHECK-NEXT: ret <2 x i59> [[R]]
1149 %a = ashr <2 x i47> %x, <i47 5, i47 5>
1150 %s = sext <2 x i47> %a to <2 x i59>
1151 %r = and <2 x i59> %s, <i59 18014398509481983, i59 18014398509481983> ; -1 u>> 5 == 0x3f_ffff_ffff_ffff
1155 define i32 @lowmask_sext_in_reg(i32 %x) {
1156 ; CHECK-LABEL: @lowmask_sext_in_reg(
1157 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 20
1158 ; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 20
1159 ; CHECK-NEXT: call void @use32(i32 [[R]])
1160 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 4095
1161 ; CHECK-NEXT: ret i32 [[AND]]
1164 %r = ashr i32 %l, 20
1165 call void @use32(i32 %r)
1166 %and = and i32 %r, 4095
1170 ; Negative test - mismatched shift amounts
1172 define i32 @lowmask_not_sext_in_reg(i32 %x) {
1173 ; CHECK-LABEL: @lowmask_not_sext_in_reg(
1174 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 19
1175 ; CHECK-NEXT: [[R:%.*]] = ashr i32 [[L]], 20
1176 ; CHECK-NEXT: call void @use32(i32 [[R]])
1177 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4095
1178 ; CHECK-NEXT: ret i32 [[AND]]
1181 %r = ashr i32 %l, 20
1182 call void @use32(i32 %r)
1183 %and = and i32 %r, 4095
1187 ; Negative test - too much shift for mask
1189 define i32 @not_lowmask_sext_in_reg(i32 %x) {
1190 ; CHECK-LABEL: @not_lowmask_sext_in_reg(
1191 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 20
1192 ; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 20
1193 ; CHECK-NEXT: call void @use32(i32 [[R]])
1194 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4096
1195 ; CHECK-NEXT: ret i32 [[AND]]
1198 %r = ashr i32 %l, 20
1199 call void @use32(i32 %r)
1200 %and = and i32 %r, 4096
1204 ; Negative test - too much shift for mask
1206 define i32 @not_lowmask_sext_in_reg2(i32 %x) {
1207 ; CHECK-LABEL: @not_lowmask_sext_in_reg2(
1208 ; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 21
1209 ; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 21
1210 ; CHECK-NEXT: call void @use32(i32 [[R]])
1211 ; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4095
1212 ; CHECK-NEXT: ret i32 [[AND]]
1215 %r = ashr i32 %l, 21
1216 call void @use32(i32 %r)
1217 %and = and i32 %r, 4095
1221 define <2 x i32> @lowmask_sext_in_reg_splat(<2 x i32> %x, <2 x i32>* %p) {
1222 ; CHECK-LABEL: @lowmask_sext_in_reg_splat(
1223 ; CHECK-NEXT: [[L:%.*]] = shl <2 x i32> [[X:%.*]], <i32 20, i32 20>
1224 ; CHECK-NEXT: [[R:%.*]] = ashr exact <2 x i32> [[L]], <i32 20, i32 20>
1225 ; CHECK-NEXT: store <2 x i32> [[R]], <2 x i32>* [[P:%.*]], align 8
1226 ; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X]], <i32 4095, i32 4095>
1227 ; CHECK-NEXT: ret <2 x i32> [[AND]]
1229 %l = shl <2 x i32> %x, <i32 20, i32 20>
1230 %r = ashr <2 x i32> %l, <i32 20, i32 20>
1231 store <2 x i32> %r, <2 x i32>* %p
1232 %and = and <2 x i32> %r, <i32 4095, i32 4095>
1236 define i8 @lowmask_add(i8 %x) {
1237 ; CHECK-LABEL: @lowmask_add(
1238 ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64
1239 ; CHECK-NEXT: call void @use8(i8 [[A]])
1240 ; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 32
1241 ; CHECK-NEXT: ret i8 [[R]]
1243 %a = add i8 %x, -64 ; 0xc0
1244 call void @use8(i8 %a)
1245 %r = and i8 %a, 32 ; 0x20
1249 define i8 @lowmask_add_2(i8 %x) {
1250 ; CHECK-LABEL: @lowmask_add_2(
1251 ; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], 63
1252 ; CHECK-NEXT: ret i8 [[R]]
1254 %a = add i8 %x, -64 ; 0xc0
1255 %r = and i8 %a, 63 ; 0x3f
1259 define i8 @lowmask_add_2_uses(i8 %x) {
1260 ; CHECK-LABEL: @lowmask_add_2_uses(
1261 ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64
1262 ; CHECK-NEXT: call void @use8(i8 [[A]])
1263 ; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 63
1264 ; CHECK-NEXT: ret i8 [[R]]
1266 %a = add i8 %x, -64 ; 0xc0
1267 call void @use8(i8 %a)
1268 %r = and i8 %a, 63 ; 0x3f
1272 define <2 x i8> @lowmask_add_2_splat(<2 x i8> %x, <2 x i8>* %p) {
1273 ; CHECK-LABEL: @lowmask_add_2_splat(
1274 ; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -64, i8 -64>
1275 ; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2
1276 ; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[X]], <i8 63, i8 63>
1277 ; CHECK-NEXT: ret <2 x i8> [[R]]
1279 %a = add <2 x i8> %x, <i8 -64, i8 -64> ; 0xc0
1280 store <2 x i8> %a, <2 x i8>* %p
1281 %r = and <2 x i8> %a, <i8 63, i8 63> ; 0x3f
1285 ; Negative test - mask overlaps low bit of add
1287 define i8 @not_lowmask_add(i8 %x) {
1288 ; CHECK-LABEL: @not_lowmask_add(
1289 ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64
1290 ; CHECK-NEXT: call void @use8(i8 [[A]])
1291 ; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], 64
1292 ; CHECK-NEXT: ret i8 [[R]]
1294 %a = add i8 %x, -64 ; 0xc0
1295 call void @use8(i8 %a)
1296 %r = and i8 %a, 64 ; 0x40
1300 ; Negative test - mask overlaps low bit of add
1302 define i8 @not_lowmask_add2(i8 %x) {
1303 ; CHECK-LABEL: @not_lowmask_add2(
1304 ; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -96
1305 ; CHECK-NEXT: call void @use8(i8 [[A]])
1306 ; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], 63
1307 ; CHECK-NEXT: ret i8 [[R]]
1309 %a = add i8 %x, -96 ; 0xe0
1310 call void @use8(i8 %a)
1311 %r = and i8 %a, 63 ; 0x3f
1315 define <2 x i8> @lowmask_add_splat(<2 x i8> %x, <2 x i8>* %p) {
1316 ; CHECK-LABEL: @lowmask_add_splat(
1317 ; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -64, i8 -64>
1318 ; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2
1319 ; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[X]], <i8 32, i8 32>
1320 ; CHECK-NEXT: ret <2 x i8> [[R]]
1322 %a = add <2 x i8> %x, <i8 -64, i8 -64> ; 0xc0
1323 store <2 x i8> %a, <2 x i8>* %p
1324 %r = and <2 x i8> %a, <i8 32, i8 32> ; 0x20
1328 define <2 x i8> @lowmask_add_splat_undef(<2 x i8> %x, <2 x i8>* %p) {
1329 ; CHECK-LABEL: @lowmask_add_splat_undef(
1330 ; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -64, i8 undef>
1331 ; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2
1332 ; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[A]], <i8 undef, i8 32>
1333 ; CHECK-NEXT: ret <2 x i8> [[R]]
1335 %a = add <2 x i8> %x, <i8 -64, i8 undef> ; 0xc0
1336 store <2 x i8> %a, <2 x i8>* %p
1337 %r = and <2 x i8> %a, <i8 undef, i8 32> ; 0x20
1341 define <2 x i8> @lowmask_add_vec(<2 x i8> %x, <2 x i8>* %p) {
1342 ; CHECK-LABEL: @lowmask_add_vec(
1343 ; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -96, i8 -64>
1344 ; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2
1345 ; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[A]], <i8 16, i8 32>
1346 ; CHECK-NEXT: ret <2 x i8> [[R]]
1348 %a = add <2 x i8> %x, <i8 -96, i8 -64> ; 0xe0, 0xc0
1349 store <2 x i8> %a, <2 x i8>* %p
1350 %r = and <2 x i8> %a, <i8 16, i8 32> ; 0x10, 0x20
1355 define i8 @flip_masked_bit(i8 %A) {
1356 ; CHECK-LABEL: @flip_masked_bit(
1357 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 16
1358 ; CHECK-NEXT: [[C:%.*]] = xor i8 [[TMP1]], 16
1359 ; CHECK-NEXT: ret i8 [[C]]
1366 define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
1367 ; CHECK-LABEL: @flip_masked_bit_uniform(
1368 ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[A:%.*]], <i8 16, i8 16>
1369 ; CHECK-NEXT: [[C:%.*]] = xor <2 x i8> [[TMP1]], <i8 16, i8 16>
1370 ; CHECK-NEXT: ret <2 x i8> [[C]]
1372 %B = add <2 x i8> %A, <i8 16, i8 16>
1373 %C = and <2 x i8> %B, <i8 16, i8 16>
1377 define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
1378 ; CHECK-LABEL: @flip_masked_bit_undef(
1379 ; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
1380 ; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
1381 ; CHECK-NEXT: ret <2 x i8> [[C]]
1383 %B = add <2 x i8> %A, <i8 16, i8 undef>
1384 %C = and <2 x i8> %B, <i8 16, i8 undef>
1388 define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
1389 ; CHECK-LABEL: @flip_masked_bit_nonuniform(
1390 ; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
1391 ; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
1392 ; CHECK-NEXT: ret <2 x i8> [[C]]
1394 %B = add <2 x i8> %A, <i8 16, i8 4>
1395 %C = and <2 x i8> %B, <i8 16, i8 4>
1399 define i8 @ashr_bitwidth_mask(i8 %x, i8 %y) {
1400 ; CHECK-LABEL: @ashr_bitwidth_mask(
1401 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i8 [[X:%.*]], 0
1402 ; CHECK-NEXT: [[NEG_OR_ZERO:%.*]] = select i1 [[ISNEG]], i8 [[Y:%.*]], i8 0
1403 ; CHECK-NEXT: ret i8 [[NEG_OR_ZERO]]
1405 %sign = ashr i8 %x, 7
1406 %neg_or_zero = and i8 %sign, %y
1410 define <2 x i8> @ashr_bitwidth_mask_vec_commute(<2 x i8> %x, <2 x i8> %py) {
1411 ; CHECK-LABEL: @ashr_bitwidth_mask_vec_commute(
1412 ; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], <i8 42, i8 2>
1413 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
1414 ; CHECK-NEXT: [[NEG_OR_ZERO:%.*]] = select <2 x i1> [[ISNEG]], <2 x i8> [[Y]], <2 x i8> zeroinitializer
1415 ; CHECK-NEXT: ret <2 x i8> [[NEG_OR_ZERO]]
1417 %y = mul <2 x i8> %py, <i8 42, i8 2> ; thwart complexity-based ordering
1418 %sign = ashr <2 x i8> %x, <i8 7, i8 7>
1419 %neg_or_zero = and <2 x i8> %y, %sign
1420 ret <2 x i8> %neg_or_zero
1423 ; negative test - extra use
1425 define i8 @ashr_bitwidth_mask_use(i8 %x, i8 %y) {
1426 ; CHECK-LABEL: @ashr_bitwidth_mask_use(
1427 ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7
1428 ; CHECK-NEXT: call void @use8(i8 [[SIGN]])
1429 ; CHECK-NEXT: [[R:%.*]] = and i8 [[SIGN]], [[Y:%.*]]
1430 ; CHECK-NEXT: ret i8 [[R]]
1432 %sign = ashr i8 %x, 7
1433 call void @use8(i8 %sign)
1434 %r = and i8 %sign, %y
1438 ; negative test - wrong shift amount
1440 define i8 @ashr_not_bitwidth_mask(i8 %x, i8 %y) {
1441 ; CHECK-LABEL: @ashr_not_bitwidth_mask(
1442 ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 6
1443 ; CHECK-NEXT: [[R:%.*]] = and i8 [[SIGN]], [[Y:%.*]]
1444 ; CHECK-NEXT: ret i8 [[R]]
1446 %sign = ashr i8 %x, 6
1447 %r = and i8 %sign, %y
1451 ; negative test - wrong shift opcode
1453 define i8 @lshr_bitwidth_mask(i8 %x, i8 %y) {
1454 ; CHECK-LABEL: @lshr_bitwidth_mask(
1455 ; CHECK-NEXT: [[SIGN:%.*]] = lshr i8 [[X:%.*]], 7
1456 ; CHECK-NEXT: [[R:%.*]] = and i8 [[SIGN]], [[Y:%.*]]
1457 ; CHECK-NEXT: ret i8 [[R]]
1459 %sign = lshr i8 %x, 7
1460 %r = and i8 %sign, %y
1464 define i8 @not_ashr_bitwidth_mask(i8 %x, i8 %y) {
1465 ; CHECK-LABEL: @not_ashr_bitwidth_mask(
1466 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i8 [[X:%.*]], 0
1467 ; CHECK-NEXT: [[POS_OR_ZERO:%.*]] = select i1 [[ISNEG]], i8 0, i8 [[Y:%.*]]
1468 ; CHECK-NEXT: ret i8 [[POS_OR_ZERO]]
1470 %sign = ashr i8 %x, 7
1471 %not = xor i8 %sign, -1
1472 %pos_or_zero = and i8 %not, %y
1476 define <2 x i8> @not_ashr_bitwidth_mask_vec_commute(<2 x i8> %x, <2 x i8> %py) {
1477 ; CHECK-LABEL: @not_ashr_bitwidth_mask_vec_commute(
1478 ; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[PY:%.*]], <i8 42, i8 2>
1479 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer
1480 ; CHECK-NEXT: [[POS_OR_ZERO:%.*]] = select <2 x i1> [[ISNEG]], <2 x i8> zeroinitializer, <2 x i8> [[Y]]
1481 ; CHECK-NEXT: ret <2 x i8> [[POS_OR_ZERO]]
1483 %y = mul <2 x i8> %py, <i8 42, i8 2> ; thwart complexity-based ordering
1484 %sign = ashr <2 x i8> %x, <i8 7, i8 7>
1485 %not = xor <2 x i8> %sign, <i8 -1, i8 -1>
1486 %pos_or_zero = and <2 x i8> %y, %not
1487 ret <2 x i8> %pos_or_zero
1490 ; extra use of shift is ok
1492 define i8 @not_ashr_bitwidth_mask_use1(i8 %x, i8 %y) {
1493 ; CHECK-LABEL: @not_ashr_bitwidth_mask_use1(
1494 ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7
1495 ; CHECK-NEXT: call void @use8(i8 [[SIGN]])
1496 ; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i8 [[X]], 0
1497 ; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNEG]], i8 0, i8 [[Y:%.*]]
1498 ; CHECK-NEXT: ret i8 [[R]]
1500 %sign = ashr i8 %x, 7
1501 call void @use8(i8 %sign)
1502 %not = xor i8 %sign, -1
1503 %r = and i8 %not, %y
1507 ; negative test - extra use
1509 define i8 @not_ashr_bitwidth_mask_use2(i8 %x, i8 %y) {
1510 ; CHECK-LABEL: @not_ashr_bitwidth_mask_use2(
1511 ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 7
1512 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SIGN]], -1
1513 ; CHECK-NEXT: call void @use8(i8 [[NOT]])
1514 ; CHECK-NEXT: [[R:%.*]] = and i8 [[NOT]], [[Y:%.*]]
1515 ; CHECK-NEXT: ret i8 [[R]]
1517 %sign = ashr i8 %x, 7
1518 %not = xor i8 %sign, -1
1519 call void @use8(i8 %not)
1520 %r = and i8 %not, %y
1524 ; negative test - wrong shift amount
1526 define i8 @not_ashr_not_bitwidth_mask(i8 %x, i8 %y) {
1527 ; CHECK-LABEL: @not_ashr_not_bitwidth_mask(
1528 ; CHECK-NEXT: [[SIGN:%.*]] = ashr i8 [[X:%.*]], 6
1529 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SIGN]], -1
1530 ; CHECK-NEXT: [[R:%.*]] = and i8 [[NOT]], [[Y:%.*]]
1531 ; CHECK-NEXT: ret i8 [[R]]
1533 %sign = ashr i8 %x, 6
1534 %not = xor i8 %sign, -1
1535 %r = and i8 %not, %y
1539 ; negative test - wrong shift opcode
1541 define i8 @not_lshr_bitwidth_mask(i8 %x, i8 %y) {
1542 ; CHECK-LABEL: @not_lshr_bitwidth_mask(
1543 ; CHECK-NEXT: [[SIGN:%.*]] = lshr i8 [[X:%.*]], 7
1544 ; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[SIGN]], -1
1545 ; CHECK-NEXT: [[R:%.*]] = and i8 [[NOT]], [[Y:%.*]]
1546 ; CHECK-NEXT: ret i8 [[R]]
1548 %sign = lshr i8 %x, 7
1549 %not = xor i8 %sign, -1
1550 %r = and i8 %not, %y