1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64 | FileCheck %s
3 ; RUN: llc < %s -mtriple=aarch64 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefix=GISEL
5 ; Convert mul x, pow2 to shift.
6 ; Convert mul x, pow2 +/- 1 to shift + add/sub.
7 ; Convert mul x, (pow2 + 1) * pow2 to shift + add + shift.
8 ; Lowering other positive constants are not supported yet.
10 define i32 @test2(i32 %x) {
13 ; CHECK-NEXT: lsl w0, w0, #1
18 ; GISEL-NEXT: lsl w0, w0, #1
21 %mul = shl nsw i32 %x, 1
25 define i32 @test3(i32 %x) {
28 ; CHECK-NEXT: add w0, w0, w0, lsl #1
33 ; GISEL-NEXT: add w0, w0, w0, lsl #1
36 %mul = mul nsw i32 %x, 3
40 define i32 @test4(i32 %x) {
43 ; CHECK-NEXT: lsl w0, w0, #2
48 ; GISEL-NEXT: lsl w0, w0, #2
51 %mul = shl nsw i32 %x, 2
55 define i32 @test5(i32 %x) {
58 ; CHECK-NEXT: add w0, w0, w0, lsl #2
63 ; GISEL-NEXT: add w0, w0, w0, lsl #2
67 %mul = mul nsw i32 %x, 5
71 define i32 @test6_32b(i32 %x) {
72 ; CHECK-LABEL: test6_32b:
74 ; CHECK-NEXT: add w8, w0, w0, lsl #1
75 ; CHECK-NEXT: lsl w0, w8, #1
78 ; GISEL-LABEL: test6_32b:
80 ; GISEL-NEXT: add w8, w0, w0, lsl #1
81 ; GISEL-NEXT: lsl w0, w8, #1
84 %mul = mul nsw i32 %x, 6
88 define i64 @test6_64b(i64 %x) {
89 ; CHECK-LABEL: test6_64b:
91 ; CHECK-NEXT: add x8, x0, x0, lsl #1
92 ; CHECK-NEXT: lsl x0, x8, #1
95 ; GISEL-LABEL: test6_64b:
97 ; GISEL-NEXT: add x8, x0, x0, lsl #1
98 ; GISEL-NEXT: lsl x0, x8, #1
101 %mul = mul nsw i64 %x, 6
105 ; mul that appears together with add, sub, s(z)ext is not supported to be
106 ; converted to the combination of lsl, add/sub yet.
107 define i64 @test6_umull(i32 %x) {
108 ; CHECK-LABEL: test6_umull:
110 ; CHECK-NEXT: mov w8, #6 // =0x6
111 ; CHECK-NEXT: umull x0, w0, w8
114 ; GISEL-LABEL: test6_umull:
116 ; GISEL-NEXT: mov w8, #6 // =0x6
117 ; GISEL-NEXT: umull x0, w0, w8
120 %ext = zext i32 %x to i64
121 %mul = mul nsw i64 %ext, 6
125 define i64 @test6_smull(i32 %x) {
126 ; CHECK-LABEL: test6_smull:
128 ; CHECK-NEXT: mov w8, #6 // =0x6
129 ; CHECK-NEXT: smull x0, w0, w8
132 ; GISEL-LABEL: test6_smull:
134 ; GISEL-NEXT: mov w8, #6 // =0x6
135 ; GISEL-NEXT: smull x0, w0, w8
138 %ext = sext i32 %x to i64
139 %mul = mul nsw i64 %ext, 6
143 define i32 @test6_madd(i32 %x, i32 %y) {
144 ; CHECK-LABEL: test6_madd:
146 ; CHECK-NEXT: mov w8, #6 // =0x6
147 ; CHECK-NEXT: madd w0, w0, w8, w1
150 ; GISEL-LABEL: test6_madd:
152 ; GISEL-NEXT: mov w8, #6 // =0x6
153 ; GISEL-NEXT: madd w0, w0, w8, w1
156 %mul = mul nsw i32 %x, 6
157 %add = add i32 %mul, %y
161 define i32 @test6_msub(i32 %x, i32 %y) {
162 ; CHECK-LABEL: test6_msub:
164 ; CHECK-NEXT: mov w8, #6 // =0x6
165 ; CHECK-NEXT: msub w0, w0, w8, w1
168 ; GISEL-LABEL: test6_msub:
170 ; GISEL-NEXT: mov w8, #6 // =0x6
171 ; GISEL-NEXT: msub w0, w0, w8, w1
174 %mul = mul nsw i32 %x, 6
175 %sub = sub i32 %y, %mul
179 define i64 @test6_umaddl(i32 %x, i64 %y) {
180 ; CHECK-LABEL: test6_umaddl:
182 ; CHECK-NEXT: mov w8, #6 // =0x6
183 ; CHECK-NEXT: umaddl x0, w0, w8, x1
186 ; GISEL-LABEL: test6_umaddl:
188 ; GISEL-NEXT: mov w8, #6 // =0x6
189 ; GISEL-NEXT: umaddl x0, w0, w8, x1
192 %ext = zext i32 %x to i64
193 %mul = mul nsw i64 %ext, 6
194 %add = add i64 %mul, %y
198 define i64 @test6_smaddl(i32 %x, i64 %y) {
199 ; CHECK-LABEL: test6_smaddl:
201 ; CHECK-NEXT: mov w8, #6 // =0x6
202 ; CHECK-NEXT: smaddl x0, w0, w8, x1
205 ; GISEL-LABEL: test6_smaddl:
207 ; GISEL-NEXT: mov w8, #6 // =0x6
208 ; GISEL-NEXT: smaddl x0, w0, w8, x1
211 %ext = sext i32 %x to i64
212 %mul = mul nsw i64 %ext, 6
213 %add = add i64 %mul, %y
217 define i64 @test6_umsubl(i32 %x, i64 %y) {
218 ; CHECK-LABEL: test6_umsubl:
220 ; CHECK-NEXT: mov w8, #6 // =0x6
221 ; CHECK-NEXT: umsubl x0, w0, w8, x1
224 ; GISEL-LABEL: test6_umsubl:
226 ; GISEL-NEXT: mov w8, #6 // =0x6
227 ; GISEL-NEXT: umsubl x0, w0, w8, x1
230 %ext = zext i32 %x to i64
231 %mul = mul nsw i64 %ext, 6
232 %sub = sub i64 %y, %mul
236 define i64 @test6_smsubl(i32 %x, i64 %y) {
237 ; CHECK-LABEL: test6_smsubl:
239 ; CHECK-NEXT: mov w8, #6 // =0x6
240 ; CHECK-NEXT: smsubl x0, w0, w8, x1
243 ; GISEL-LABEL: test6_smsubl:
245 ; GISEL-NEXT: mov w8, #6 // =0x6
246 ; GISEL-NEXT: smsubl x0, w0, w8, x1
249 %ext = sext i32 %x to i64
250 %mul = mul nsw i64 %ext, 6
251 %sub = sub i64 %y, %mul
255 define i64 @test6_umnegl(i32 %x) {
256 ; CHECK-LABEL: test6_umnegl:
258 ; CHECK-NEXT: mov w8, #6 // =0x6
259 ; CHECK-NEXT: umnegl x0, w0, w8
262 ; GISEL-LABEL: test6_umnegl:
264 ; GISEL-NEXT: mov w8, #6 // =0x6
265 ; GISEL-NEXT: umnegl x0, w0, w8
268 %ext = zext i32 %x to i64
269 %mul = mul nsw i64 %ext, 6
270 %sub = sub i64 0, %mul
274 define i64 @test6_smnegl(i32 %x) {
275 ; CHECK-LABEL: test6_smnegl:
277 ; CHECK-NEXT: mov w8, #6 // =0x6
278 ; CHECK-NEXT: smnegl x0, w0, w8
281 ; GISEL-LABEL: test6_smnegl:
283 ; GISEL-NEXT: mov w8, #6 // =0x6
284 ; GISEL-NEXT: smnegl x0, w0, w8
287 %ext = sext i32 %x to i64
288 %mul = mul nsw i64 %ext, 6
289 %sub = sub i64 0, %mul
293 ; We may hoist the "mov" instructions out of a loop
294 define i32 @mull6_sub(i32 %x) {
295 ; CHECK-LABEL: mull6_sub:
297 ; CHECK-NEXT: mov w8, #6 // =0x6
298 ; CHECK-NEXT: mov w9, #-1 // =0xffffffff
299 ; CHECK-NEXT: madd w0, w0, w8, w9
302 ; GISEL-LABEL: mull6_sub:
304 ; GISEL-NEXT: mov w8, #6 // =0x6
305 ; GISEL-NEXT: mov w9, #-1 // =0xffffffff
306 ; GISEL-NEXT: madd w0, w0, w8, w9
308 %mul = mul nsw i32 %x, 6
309 %sub = add nsw i32 %mul, -1
313 define i64 @mull6_sub_orr(i64 %x) {
314 ; CHECK-LABEL: mull6_sub_orr:
316 ; CHECK-NEXT: mov w8, #6 // =0x6
317 ; CHECK-NEXT: mov x9, #16773120 // =0xfff000
318 ; CHECK-NEXT: madd x0, x0, x8, x9
321 ; GISEL-LABEL: mull6_sub_orr:
323 ; GISEL-NEXT: mov w8, #6 // =0x6
324 ; GISEL-NEXT: mov x9, #16773120 // =0xfff000
325 ; GISEL-NEXT: madd x0, x0, x8, x9
327 %mul = mul nsw i64 %x, 6
328 %sub = add nsw i64 %mul, 16773120
332 define i32 @test7(i32 %x) {
333 ; CHECK-LABEL: test7:
335 ; CHECK-NEXT: lsl w8, w0, #3
336 ; CHECK-NEXT: sub w0, w8, w0
339 ; GISEL-LABEL: test7:
341 ; GISEL-NEXT: lsl w8, w0, #3
342 ; GISEL-NEXT: sub w0, w8, w0
345 %mul = mul nsw i32 %x, 7
349 define i32 @test8(i32 %x) {
350 ; CHECK-LABEL: test8:
352 ; CHECK-NEXT: lsl w0, w0, #3
355 ; GISEL-LABEL: test8:
357 ; GISEL-NEXT: lsl w0, w0, #3
360 %mul = shl nsw i32 %x, 3
364 define i32 @test9(i32 %x) {
365 ; CHECK-LABEL: test9:
367 ; CHECK-NEXT: add w0, w0, w0, lsl #3
370 ; GISEL-LABEL: test9:
372 ; GISEL-NEXT: add w0, w0, w0, lsl #3
375 %mul = mul nsw i32 %x, 9
379 define i32 @test10(i32 %x) {
380 ; CHECK-LABEL: test10:
382 ; CHECK-NEXT: add w8, w0, w0, lsl #2
383 ; CHECK-NEXT: lsl w0, w8, #1
386 ; GISEL-LABEL: test10:
388 ; GISEL-NEXT: add w8, w0, w0, lsl #2
389 ; GISEL-NEXT: lsl w0, w8, #1
392 %mul = mul nsw i32 %x, 10
396 define i32 @test11(i32 %x) {
397 ; CHECK-LABEL: test11:
399 ; CHECK-NEXT: mov w8, #11 // =0xb
400 ; CHECK-NEXT: mul w0, w0, w8
403 ; GISEL-LABEL: test11:
405 ; GISEL-NEXT: mov w8, #11 // =0xb
406 ; GISEL-NEXT: mul w0, w0, w8
409 %mul = mul nsw i32 %x, 11
413 define i32 @test11_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
414 ; CHECK-LABEL: test11_fast_shift:
416 ; CHECK-NEXT: add w8, w0, w0, lsl #2
417 ; CHECK-NEXT: add w0, w0, w8, lsl #1
420 ; GISEL-LABEL: test11_fast_shift:
422 ; GISEL-NEXT: mov w8, #11 // =0xb
423 ; GISEL-NEXT: mul w0, w0, w8
426 %mul = mul nsw i32 %x, 11 ; 11 = (((1<<2) + 1) << 1) + 1
430 define i32 @test12(i32 %x) {
431 ; CHECK-LABEL: test12:
433 ; CHECK-NEXT: add w8, w0, w0, lsl #1
434 ; CHECK-NEXT: lsl w0, w8, #2
437 ; GISEL-LABEL: test12:
439 ; GISEL-NEXT: add w8, w0, w0, lsl #1
440 ; GISEL-NEXT: lsl w0, w8, #2
443 %mul = mul nsw i32 %x, 12
447 define i32 @test13(i32 %x) {
448 ; CHECK-LABEL: test13:
450 ; CHECK-NEXT: mov w8, #13 // =0xd
451 ; CHECK-NEXT: mul w0, w0, w8
454 ; GISEL-LABEL: test13:
456 ; GISEL-NEXT: mov w8, #13 // =0xd
457 ; GISEL-NEXT: mul w0, w0, w8
460 %mul = mul nsw i32 %x, 13
464 define i32 @test14(i32 %x) {
465 ; CHECK-LABEL: test14:
467 ; CHECK-NEXT: lsl w8, w0, #4
468 ; CHECK-NEXT: sub w0, w8, w0, lsl #1
471 ; GISEL-LABEL: test14:
473 ; GISEL-NEXT: mov w8, #14 // =0xe
474 ; GISEL-NEXT: mul w0, w0, w8
477 %mul = mul nsw i32 %x, 14
481 define i32 @test15(i32 %x) {
482 ; CHECK-LABEL: test15:
484 ; CHECK-NEXT: lsl w8, w0, #4
485 ; CHECK-NEXT: sub w0, w8, w0
488 ; GISEL-LABEL: test15:
490 ; GISEL-NEXT: lsl w8, w0, #4
491 ; GISEL-NEXT: sub w0, w8, w0
494 %mul = mul nsw i32 %x, 15
498 define i32 @test16(i32 %x) {
499 ; CHECK-LABEL: test16:
501 ; CHECK-NEXT: lsl w0, w0, #4
504 ; GISEL-LABEL: test16:
506 ; GISEL-NEXT: lsl w0, w0, #4
509 %mul = mul nsw i32 %x, 16
513 define i32 @test25_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
514 ; CHECK-LABEL: test25_fast_shift:
516 ; CHECK-NEXT: add w8, w0, w0, lsl #2
517 ; CHECK-NEXT: add w0, w8, w8, lsl #2
520 ; GISEL-LABEL: test25_fast_shift:
522 ; GISEL-NEXT: mov w8, #25 // =0x19
523 ; GISEL-NEXT: mul w0, w0, w8
526 %mul = mul nsw i32 %x, 25 ; 25 = (1+4)*(1+4)
530 define i32 @test29_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
531 ; CHECK-LABEL: test29_fast_shift:
533 ; CHECK-NEXT: sub w8, w0, w0, lsl #3
534 ; CHECK-NEXT: sub w0, w0, w8, lsl #2
537 ; GISEL-LABEL: test29_fast_shift:
539 ; GISEL-NEXT: mov w8, #29 // =0x1d
540 ; GISEL-NEXT: mul w0, w0, w8
543 %mul = mul nsw i32 %x, 29 ; 29 = 1 - (1-8) * 4
547 define i32 @test45_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
548 ; CHECK-LABEL: test45_fast_shift:
550 ; CHECK-NEXT: add w8, w0, w0, lsl #2
551 ; CHECK-NEXT: add w0, w8, w8, lsl #3
554 ; GISEL-LABEL: test45_fast_shift:
556 ; GISEL-NEXT: mov w8, #45 // =0x2d
557 ; GISEL-NEXT: mul w0, w0, w8
560 %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)
564 ; Negative test: Keep MUL as don't have the feature LSLFast
565 define i32 @test45(i32 %x) {
566 ; CHECK-LABEL: test45:
568 ; CHECK-NEXT: mov w8, #45 // =0x2d
569 ; CHECK-NEXT: mul w0, w0, w8
572 ; GISEL-LABEL: test45:
574 ; GISEL-NEXT: mov w8, #45 // =0x2d
575 ; GISEL-NEXT: mul w0, w0, w8
578 %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)
582 ; Negative test: The shift number 5 is out of bound
583 define i32 @test67_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
584 ; CHECK-LABEL: test67_fast_shift:
586 ; CHECK-NEXT: mov w8, #67 // =0x43
587 ; CHECK-NEXT: mul w0, w0, w8
590 ; GISEL-LABEL: test67_fast_shift:
592 ; GISEL-NEXT: mov w8, #67 // =0x43
593 ; GISEL-NEXT: mul w0, w0, w8
596 %mul = mul nsw i32 %x, 67 ; 67 = (((1<<5) + 1) << 1) + 1
600 define i32 @test85_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
601 ; CHECK-LABEL: test85_fast_shift:
603 ; CHECK-NEXT: add w8, w0, w0, lsl #2
604 ; CHECK-NEXT: add w0, w8, w8, lsl #4
607 ; GISEL-LABEL: test85_fast_shift:
609 ; GISEL-NEXT: mov w8, #85 // =0x55
610 ; GISEL-NEXT: mul w0, w0, w8
613 %mul = mul nsw i32 %x, 85 ; 85 = (1+4)*(1+16)
617 ; Negative test: The shift number 5 is out of bound
618 define i32 @test97_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
619 ; CHECK-LABEL: test97_fast_shift:
621 ; CHECK-NEXT: mov w8, #97 // =0x61
622 ; CHECK-NEXT: mul w0, w0, w8
625 ; GISEL-LABEL: test97_fast_shift:
627 ; GISEL-NEXT: mov w8, #97 // =0x61
628 ; GISEL-NEXT: mul w0, w0, w8
631 %mul = mul nsw i32 %x, 97 ; 97 = ((2 + 1) << 5) + 1
635 ; Negative test: The shift number 5 is out of bound
636 define i32 @test125_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
637 ; CHECK-LABEL: test125_fast_shift:
639 ; CHECK-NEXT: mov w8, #125 // =0x7d
640 ; CHECK-NEXT: mul w0, w0, w8
643 ; GISEL-LABEL: test125_fast_shift:
645 ; GISEL-NEXT: mov w8, #125 // =0x7d
646 ; GISEL-NEXT: mul w0, w0, w8
649 %mul = mul nsw i32 %x, 125 ; 125 = 1 - ((1-32) << 2)
653 ; TODO: (1 - 2^M) * (1 - 2^N)
654 define i32 @test225_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
655 ; CHECK-LABEL: test225_fast_shift:
657 ; CHECK-NEXT: mov w8, #225 // =0xe1
658 ; CHECK-NEXT: mul w0, w0, w8
661 ; GISEL-LABEL: test225_fast_shift:
663 ; GISEL-NEXT: mov w8, #225 // =0xe1
664 ; GISEL-NEXT: mul w0, w0, w8
667 %mul = mul nsw i32 %x, 225 ; 225 = (1-16)*(1-16)
671 ; Negative test: The shift amount 5 larger than 4
672 define i32 @test297_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
673 ; CHECK-LABEL: test297_fast_shift:
675 ; CHECK-NEXT: mov w8, #297 // =0x129
676 ; CHECK-NEXT: mul w0, w0, w8
679 ; GISEL-LABEL: test297_fast_shift:
681 ; GISEL-NEXT: mov w8, #297 // =0x129
682 ; GISEL-NEXT: mul w0, w0, w8
685 %mul = mul nsw i32 %x, 297 ; 297 = (1+8)*(1+32)
689 ; Negative test: The shift number 5 is out of bound
690 define i32 @test481_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
691 ; CHECK-LABEL: test481_fast_shift:
693 ; CHECK-NEXT: mov w8, #481 // =0x1e1
694 ; CHECK-NEXT: mul w0, w0, w8
697 ; GISEL-LABEL: test481_fast_shift:
699 ; GISEL-NEXT: mov w8, #481 // =0x1e1
700 ; GISEL-NEXT: mul w0, w0, w8
703 %mul = mul nsw i32 %x, 481 ; 481 = 1 - ((1-16) << 5)
707 ; Convert mul x, -pow2 to shift.
708 ; Convert mul x, -(pow2 +/- 1) to shift + add/sub.
709 ; Lowering other negative constants are not supported yet.
711 define i32 @ntest2(i32 %x) {
712 ; CHECK-LABEL: ntest2:
714 ; CHECK-NEXT: neg w0, w0, lsl #1
717 ; GISEL-LABEL: ntest2:
719 ; GISEL-NEXT: mov w8, #-2 // =0xfffffffe
720 ; GISEL-NEXT: mul w0, w0, w8
723 %mul = mul nsw i32 %x, -2
727 define i32 @ntest3(i32 %x) {
728 ; CHECK-LABEL: ntest3:
730 ; CHECK-NEXT: sub w0, w0, w0, lsl #2
733 ; GISEL-LABEL: ntest3:
735 ; GISEL-NEXT: sub w0, w0, w0, lsl #2
738 %mul = mul nsw i32 %x, -3
742 define i32 @ntest4(i32 %x) {
743 ; CHECK-LABEL: ntest4:
745 ; CHECK-NEXT: neg w0, w0, lsl #2
748 ; GISEL-LABEL: ntest4:
750 ; GISEL-NEXT: mov w8, #-4 // =0xfffffffc
751 ; GISEL-NEXT: mul w0, w0, w8
754 %mul = mul nsw i32 %x, -4
758 define i32 @ntest5(i32 %x) {
759 ; CHECK-LABEL: ntest5:
761 ; CHECK-NEXT: add w8, w0, w0, lsl #2
762 ; CHECK-NEXT: neg w0, w8
765 ; GISEL-LABEL: ntest5:
767 ; GISEL-NEXT: add w8, w0, w0, lsl #2
768 ; GISEL-NEXT: neg w0, w8
770 %mul = mul nsw i32 %x, -5
774 define i32 @ntest6(i32 %x) {
775 ; CHECK-LABEL: ntest6:
777 ; CHECK-NEXT: lsl w8, w0, #1
778 ; CHECK-NEXT: sub w0, w8, w0, lsl #3
781 ; GISEL-LABEL: ntest6:
783 ; GISEL-NEXT: mov w8, #-6 // =0xfffffffa
784 ; GISEL-NEXT: mul w0, w0, w8
787 %mul = mul nsw i32 %x, -6
791 define i32 @ntest7(i32 %x) {
792 ; CHECK-LABEL: ntest7:
794 ; CHECK-NEXT: sub w0, w0, w0, lsl #3
797 ; GISEL-LABEL: ntest7:
799 ; GISEL-NEXT: sub w0, w0, w0, lsl #3
802 %mul = mul nsw i32 %x, -7
806 define i32 @ntest8(i32 %x) {
807 ; CHECK-LABEL: ntest8:
809 ; CHECK-NEXT: neg w0, w0, lsl #3
812 ; GISEL-LABEL: ntest8:
814 ; GISEL-NEXT: mov w8, #-8 // =0xfffffff8
815 ; GISEL-NEXT: mul w0, w0, w8
818 %mul = mul nsw i32 %x, -8
822 define i32 @ntest9(i32 %x) {
823 ; CHECK-LABEL: ntest9:
825 ; CHECK-NEXT: add w8, w0, w0, lsl #3
826 ; CHECK-NEXT: neg w0, w8
829 ; GISEL-LABEL: ntest9:
831 ; GISEL-NEXT: add w8, w0, w0, lsl #3
832 ; GISEL-NEXT: neg w0, w8
835 %mul = mul nsw i32 %x, -9
839 define i32 @ntest10(i32 %x) {
840 ; CHECK-LABEL: ntest10:
842 ; CHECK-NEXT: mov w8, #-10 // =0xfffffff6
843 ; CHECK-NEXT: mul w0, w0, w8
846 ; GISEL-LABEL: ntest10:
848 ; GISEL-NEXT: mov w8, #-10 // =0xfffffff6
849 ; GISEL-NEXT: mul w0, w0, w8
852 %mul = mul nsw i32 %x, -10
856 define i32 @ntest11(i32 %x) {
857 ; CHECK-LABEL: ntest11:
859 ; CHECK-NEXT: mov w8, #-11 // =0xfffffff5
860 ; CHECK-NEXT: mul w0, w0, w8
863 ; GISEL-LABEL: ntest11:
865 ; GISEL-NEXT: mov w8, #-11 // =0xfffffff5
866 ; GISEL-NEXT: mul w0, w0, w8
869 %mul = mul nsw i32 %x, -11
873 define i32 @ntest12(i32 %x) {
874 ; CHECK-LABEL: ntest12:
876 ; CHECK-NEXT: lsl w8, w0, #2
877 ; CHECK-NEXT: sub w0, w8, w0, lsl #4
880 ; GISEL-LABEL: ntest12:
882 ; GISEL-NEXT: mov w8, #-12 // =0xfffffff4
883 ; GISEL-NEXT: mul w0, w0, w8
886 %mul = mul nsw i32 %x, -12
890 define i32 @ntest13(i32 %x) {
891 ; CHECK-LABEL: ntest13:
893 ; CHECK-NEXT: mov w8, #-13 // =0xfffffff3
894 ; CHECK-NEXT: mul w0, w0, w8
897 ; GISEL-LABEL: ntest13:
899 ; GISEL-NEXT: mov w8, #-13 // =0xfffffff3
900 ; GISEL-NEXT: mul w0, w0, w8
902 %mul = mul nsw i32 %x, -13
906 define i32 @ntest14(i32 %x) {
907 ; CHECK-LABEL: ntest14:
909 ; CHECK-NEXT: lsl w8, w0, #1
910 ; CHECK-NEXT: sub w0, w8, w0, lsl #4
913 ; GISEL-LABEL: ntest14:
915 ; GISEL-NEXT: mov w8, #-14 // =0xfffffff2
916 ; GISEL-NEXT: mul w0, w0, w8
919 %mul = mul nsw i32 %x, -14
923 define i32 @ntest15(i32 %x) {
924 ; CHECK-LABEL: ntest15:
926 ; CHECK-NEXT: sub w0, w0, w0, lsl #4
929 ; GISEL-LABEL: ntest15:
931 ; GISEL-NEXT: sub w0, w0, w0, lsl #4
934 %mul = mul nsw i32 %x, -15
938 define i32 @ntest16(i32 %x) {
939 ; CHECK-LABEL: ntest16:
941 ; CHECK-NEXT: neg w0, w0, lsl #4
944 ; GISEL-LABEL: ntest16:
946 ; GISEL-NEXT: mov w8, #-16 // =0xfffffff0
947 ; GISEL-NEXT: mul w0, w0, w8
950 %mul = mul nsw i32 %x, -16
954 define i32 @muladd_demand(i32 %x, i32 %y) {
955 ; CHECK-LABEL: muladd_demand:
957 ; CHECK-NEXT: sub w8, w1, w0, lsl #6
958 ; CHECK-NEXT: and w0, w8, #0x1ffc0
961 ; GISEL-LABEL: muladd_demand:
963 ; GISEL-NEXT: mov w8, #131008 // =0x1ffc0
964 ; GISEL-NEXT: madd w8, w0, w8, w1
965 ; GISEL-NEXT: and w0, w8, #0x1ffc0
967 %m = mul i32 %x, 131008 ; 0x0001ffc0
969 %r = and i32 %a, 131008
973 define <4 x i32> @muladd_demand_commute(<4 x i32> %x, <4 x i32> %y) {
974 ; CHECK-LABEL: muladd_demand_commute:
976 ; CHECK-NEXT: shl v0.4s, v0.4s, #6
977 ; CHECK-NEXT: movi v2.4s, #1, msl #16
978 ; CHECK-NEXT: sub v0.4s, v1.4s, v0.4s
979 ; CHECK-NEXT: and v0.16b, v0.16b, v2.16b
982 ; GISEL-LABEL: muladd_demand_commute:
984 ; GISEL-NEXT: adrp x8, .LCPI56_0
985 ; GISEL-NEXT: movi v3.4s, #1, msl #16
986 ; GISEL-NEXT: ldr q2, [x8, :lo12:.LCPI56_0]
987 ; GISEL-NEXT: mla v1.4s, v0.4s, v2.4s
988 ; GISEL-NEXT: and v0.16b, v1.16b, v3.16b
990 %m = mul <4 x i32> %x, <i32 131008, i32 131008, i32 131008, i32 131008>
991 %a = add <4 x i32> %m, %y
992 %r = and <4 x i32> %a, <i32 131071, i32 131071, i32 131071, i32 131071>
996 ; Transforming `(mul x, -(2^(N-M) - 1) * 2^M)` to `(sub (shl x, M), (shl x, N))`
997 ; will cause overflow when N is 32 and M is 31.
998 define i32 @shift_overflow(i32 %x) {
999 ; CHECK-LABEL: shift_overflow:
1001 ; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000
1002 ; CHECK-NEXT: mul w0, w0, w8
1005 ; GISEL-LABEL: shift_overflow:
1007 ; GISEL-NEXT: mov w8, #-2147483648 // =0x80000000
1008 ; GISEL-NEXT: mul w0, w0, w8
1010 %const = bitcast i32 2147483648 to i32
1011 %r = mul i32 %x, %const
1015 ; Transforming `(mul x, -(2^(N-M) - 1) * 2^M)` to `(sub (shl x, M), (shl x, N))`
1016 ; will not cause overflow when N is 31 and M is 30.
1017 define i32 @shift_no_overflow(i32 %x) {
1018 ; CHECK-LABEL: shift_no_overflow:
1020 ; CHECK-NEXT: lsl w8, w0, #31
1021 ; CHECK-NEXT: sub w0, w8, w0, lsl #30
1024 ; GISEL-LABEL: shift_no_overflow:
1026 ; GISEL-NEXT: mov w8, #1073741824 // =0x40000000
1027 ; GISEL-NEXT: mul w0, w0, w8
1029 %const = bitcast i32 1073741824 to i32
1030 %r = mul i32 %x, %const