[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / test / CodeGen / AArch64 / mul_pow2.ll
blob7e26b877a42286b35ed1321c0594b6ec64b3fbfb
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) {
11 ; CHECK-LABEL: test2:
12 ; CHECK:       // %bb.0:
13 ; CHECK-NEXT:    lsl w0, w0, #1
14 ; CHECK-NEXT:    ret
16 ; GISEL-LABEL: test2:
17 ; GISEL:       // %bb.0:
18 ; GISEL-NEXT:    lsl w0, w0, #1
19 ; GISEL-NEXT:    ret
21   %mul = shl nsw i32 %x, 1
22   ret i32 %mul
25 define i32 @test3(i32 %x) {
26 ; CHECK-LABEL: test3:
27 ; CHECK:       // %bb.0:
28 ; CHECK-NEXT:    add w0, w0, w0, lsl #1
29 ; CHECK-NEXT:    ret
31 ; GISEL-LABEL: test3:
32 ; GISEL:       // %bb.0:
33 ; GISEL-NEXT:    add w0, w0, w0, lsl #1
34 ; GISEL-NEXT:    ret
36   %mul = mul nsw i32 %x, 3
37   ret i32 %mul
40 define i32 @test4(i32 %x) {
41 ; CHECK-LABEL: test4:
42 ; CHECK:       // %bb.0:
43 ; CHECK-NEXT:    lsl w0, w0, #2
44 ; CHECK-NEXT:    ret
46 ; GISEL-LABEL: test4:
47 ; GISEL:       // %bb.0:
48 ; GISEL-NEXT:    lsl w0, w0, #2
49 ; GISEL-NEXT:    ret
51   %mul = shl nsw i32 %x, 2
52   ret i32 %mul
55 define i32 @test5(i32 %x) {
56 ; CHECK-LABEL: test5:
57 ; CHECK:       // %bb.0:
58 ; CHECK-NEXT:    add w0, w0, w0, lsl #2
59 ; CHECK-NEXT:    ret
61 ; GISEL-LABEL: test5:
62 ; GISEL:       // %bb.0:
63 ; GISEL-NEXT:    add w0, w0, w0, lsl #2
64 ; GISEL-NEXT:    ret
67   %mul = mul nsw i32 %x, 5
68   ret i32 %mul
71 define i32 @test6_32b(i32 %x) {
72 ; CHECK-LABEL: test6_32b:
73 ; CHECK:       // %bb.0:
74 ; CHECK-NEXT:    add w8, w0, w0, lsl #1
75 ; CHECK-NEXT:    lsl w0, w8, #1
76 ; CHECK-NEXT:    ret
78 ; GISEL-LABEL: test6_32b:
79 ; GISEL:       // %bb.0:
80 ; GISEL-NEXT:    add w8, w0, w0, lsl #1
81 ; GISEL-NEXT:    lsl w0, w8, #1
82 ; GISEL-NEXT:    ret
84   %mul = mul nsw i32 %x, 6
85   ret i32 %mul
88 define i64 @test6_64b(i64 %x) {
89 ; CHECK-LABEL: test6_64b:
90 ; CHECK:       // %bb.0:
91 ; CHECK-NEXT:    add x8, x0, x0, lsl #1
92 ; CHECK-NEXT:    lsl x0, x8, #1
93 ; CHECK-NEXT:    ret
95 ; GISEL-LABEL: test6_64b:
96 ; GISEL:       // %bb.0:
97 ; GISEL-NEXT:    add x8, x0, x0, lsl #1
98 ; GISEL-NEXT:    lsl x0, x8, #1
99 ; GISEL-NEXT:    ret
101   %mul = mul nsw i64 %x, 6
102   ret i64 %mul
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:
109 ; CHECK:       // %bb.0:
110 ; CHECK-NEXT:    mov w8, #6 // =0x6
111 ; CHECK-NEXT:    umull x0, w0, w8
112 ; CHECK-NEXT:    ret
114 ; GISEL-LABEL: test6_umull:
115 ; GISEL:       // %bb.0:
116 ; GISEL-NEXT:    mov w8, #6 // =0x6
117 ; GISEL-NEXT:    umull x0, w0, w8
118 ; GISEL-NEXT:    ret
120   %ext = zext i32 %x to i64
121   %mul = mul nsw i64 %ext, 6
122   ret i64 %mul
125 define i64 @test6_smull(i32 %x) {
126 ; CHECK-LABEL: test6_smull:
127 ; CHECK:       // %bb.0:
128 ; CHECK-NEXT:    mov w8, #6 // =0x6
129 ; CHECK-NEXT:    smull x0, w0, w8
130 ; CHECK-NEXT:    ret
132 ; GISEL-LABEL: test6_smull:
133 ; GISEL:       // %bb.0:
134 ; GISEL-NEXT:    mov w8, #6 // =0x6
135 ; GISEL-NEXT:    smull x0, w0, w8
136 ; GISEL-NEXT:    ret
138   %ext = sext i32 %x to i64
139   %mul = mul nsw i64 %ext, 6
140   ret i64 %mul
143 define i32 @test6_madd(i32 %x, i32 %y) {
144 ; CHECK-LABEL: test6_madd:
145 ; CHECK:       // %bb.0:
146 ; CHECK-NEXT:    mov w8, #6 // =0x6
147 ; CHECK-NEXT:    madd w0, w0, w8, w1
148 ; CHECK-NEXT:    ret
150 ; GISEL-LABEL: test6_madd:
151 ; GISEL:       // %bb.0:
152 ; GISEL-NEXT:    mov w8, #6 // =0x6
153 ; GISEL-NEXT:    madd w0, w0, w8, w1
154 ; GISEL-NEXT:    ret
156   %mul = mul nsw i32 %x, 6
157   %add = add i32 %mul, %y
158   ret i32 %add
161 define i32 @test6_msub(i32 %x, i32 %y) {
162 ; CHECK-LABEL: test6_msub:
163 ; CHECK:       // %bb.0:
164 ; CHECK-NEXT:    mov w8, #6 // =0x6
165 ; CHECK-NEXT:    msub w0, w0, w8, w1
166 ; CHECK-NEXT:    ret
168 ; GISEL-LABEL: test6_msub:
169 ; GISEL:       // %bb.0:
170 ; GISEL-NEXT:    mov w8, #6 // =0x6
171 ; GISEL-NEXT:    msub w0, w0, w8, w1
172 ; GISEL-NEXT:    ret
174   %mul = mul nsw i32 %x, 6
175   %sub = sub i32 %y, %mul
176   ret i32 %sub
179 define i64 @test6_umaddl(i32 %x, i64 %y) {
180 ; CHECK-LABEL: test6_umaddl:
181 ; CHECK:       // %bb.0:
182 ; CHECK-NEXT:    mov w8, #6 // =0x6
183 ; CHECK-NEXT:    umaddl x0, w0, w8, x1
184 ; CHECK-NEXT:    ret
186 ; GISEL-LABEL: test6_umaddl:
187 ; GISEL:       // %bb.0:
188 ; GISEL-NEXT:    mov w8, #6 // =0x6
189 ; GISEL-NEXT:    umaddl x0, w0, w8, x1
190 ; GISEL-NEXT:    ret
192   %ext = zext i32 %x to i64
193   %mul = mul nsw i64 %ext, 6
194   %add = add i64 %mul, %y
195   ret i64 %add
198 define i64 @test6_smaddl(i32 %x, i64 %y) {
199 ; CHECK-LABEL: test6_smaddl:
200 ; CHECK:       // %bb.0:
201 ; CHECK-NEXT:    mov w8, #6 // =0x6
202 ; CHECK-NEXT:    smaddl x0, w0, w8, x1
203 ; CHECK-NEXT:    ret
205 ; GISEL-LABEL: test6_smaddl:
206 ; GISEL:       // %bb.0:
207 ; GISEL-NEXT:    mov w8, #6 // =0x6
208 ; GISEL-NEXT:    smaddl x0, w0, w8, x1
209 ; GISEL-NEXT:    ret
211   %ext = sext i32 %x to i64
212   %mul = mul nsw i64 %ext, 6
213   %add = add i64 %mul, %y
214   ret i64 %add
217 define i64 @test6_umsubl(i32 %x, i64 %y) {
218 ; CHECK-LABEL: test6_umsubl:
219 ; CHECK:       // %bb.0:
220 ; CHECK-NEXT:    mov w8, #6 // =0x6
221 ; CHECK-NEXT:    umsubl x0, w0, w8, x1
222 ; CHECK-NEXT:    ret
224 ; GISEL-LABEL: test6_umsubl:
225 ; GISEL:       // %bb.0:
226 ; GISEL-NEXT:    mov w8, #6 // =0x6
227 ; GISEL-NEXT:    umsubl x0, w0, w8, x1
228 ; GISEL-NEXT:    ret
230   %ext = zext i32 %x to i64
231   %mul = mul nsw i64 %ext, 6
232   %sub = sub i64 %y, %mul
233   ret i64 %sub
236 define i64 @test6_smsubl(i32 %x, i64 %y) {
237 ; CHECK-LABEL: test6_smsubl:
238 ; CHECK:       // %bb.0:
239 ; CHECK-NEXT:    mov w8, #6 // =0x6
240 ; CHECK-NEXT:    smsubl x0, w0, w8, x1
241 ; CHECK-NEXT:    ret
243 ; GISEL-LABEL: test6_smsubl:
244 ; GISEL:       // %bb.0:
245 ; GISEL-NEXT:    mov w8, #6 // =0x6
246 ; GISEL-NEXT:    smsubl x0, w0, w8, x1
247 ; GISEL-NEXT:    ret
249   %ext = sext i32 %x to i64
250   %mul = mul nsw i64 %ext, 6
251   %sub = sub i64 %y, %mul
252   ret i64 %sub
255 define i64 @test6_umnegl(i32 %x) {
256 ; CHECK-LABEL: test6_umnegl:
257 ; CHECK:       // %bb.0:
258 ; CHECK-NEXT:    mov w8, #6 // =0x6
259 ; CHECK-NEXT:    umnegl x0, w0, w8
260 ; CHECK-NEXT:    ret
262 ; GISEL-LABEL: test6_umnegl:
263 ; GISEL:       // %bb.0:
264 ; GISEL-NEXT:    mov w8, #6 // =0x6
265 ; GISEL-NEXT:    umnegl x0, w0, w8
266 ; GISEL-NEXT:    ret
268   %ext = zext i32 %x to i64
269   %mul = mul nsw i64 %ext, 6
270   %sub = sub i64 0, %mul
271   ret i64 %sub
274 define i64 @test6_smnegl(i32 %x) {
275 ; CHECK-LABEL: test6_smnegl:
276 ; CHECK:       // %bb.0:
277 ; CHECK-NEXT:    mov w8, #6 // =0x6
278 ; CHECK-NEXT:    smnegl x0, w0, w8
279 ; CHECK-NEXT:    ret
281 ; GISEL-LABEL: test6_smnegl:
282 ; GISEL:       // %bb.0:
283 ; GISEL-NEXT:    mov w8, #6 // =0x6
284 ; GISEL-NEXT:    smnegl x0, w0, w8
285 ; GISEL-NEXT:    ret
287   %ext = sext i32 %x to i64
288   %mul = mul nsw i64 %ext, 6
289   %sub = sub i64 0, %mul
290   ret i64 %sub
293 ; We may hoist the "mov" instructions out of a loop
294 define i32 @mull6_sub(i32 %x) {
295 ; CHECK-LABEL: mull6_sub:
296 ; CHECK:       // %bb.0:
297 ; CHECK-NEXT:    mov w8, #6 // =0x6
298 ; CHECK-NEXT:    mov w9, #-1 // =0xffffffff
299 ; CHECK-NEXT:    madd w0, w0, w8, w9
300 ; CHECK-NEXT:    ret
302 ; GISEL-LABEL: mull6_sub:
303 ; GISEL:       // %bb.0:
304 ; GISEL-NEXT:    mov w8, #6 // =0x6
305 ; GISEL-NEXT:    mov w9, #-1 // =0xffffffff
306 ; GISEL-NEXT:    madd w0, w0, w8, w9
307 ; GISEL-NEXT:    ret
308   %mul = mul nsw i32 %x, 6
309   %sub = add nsw i32 %mul, -1
310   ret i32 %sub
313 define i64 @mull6_sub_orr(i64 %x) {
314 ; CHECK-LABEL: mull6_sub_orr:
315 ; CHECK:       // %bb.0:
316 ; CHECK-NEXT:    mov w8, #6 // =0x6
317 ; CHECK-NEXT:    mov x9, #16773120 // =0xfff000
318 ; CHECK-NEXT:    madd x0, x0, x8, x9
319 ; CHECK-NEXT:    ret
321 ; GISEL-LABEL: mull6_sub_orr:
322 ; GISEL:       // %bb.0:
323 ; GISEL-NEXT:    mov w8, #6 // =0x6
324 ; GISEL-NEXT:    mov x9, #16773120 // =0xfff000
325 ; GISEL-NEXT:    madd x0, x0, x8, x9
326 ; GISEL-NEXT:    ret
327   %mul = mul nsw i64 %x, 6
328   %sub = add nsw i64 %mul, 16773120
329   ret i64 %sub
332 define i32 @test7(i32 %x) {
333 ; CHECK-LABEL: test7:
334 ; CHECK:       // %bb.0:
335 ; CHECK-NEXT:    lsl w8, w0, #3
336 ; CHECK-NEXT:    sub w0, w8, w0
337 ; CHECK-NEXT:    ret
339 ; GISEL-LABEL: test7:
340 ; GISEL:       // %bb.0:
341 ; GISEL-NEXT:    lsl w8, w0, #3
342 ; GISEL-NEXT:    sub w0, w8, w0
343 ; GISEL-NEXT:    ret
345   %mul = mul nsw i32 %x, 7
346   ret i32 %mul
349 define i32 @test8(i32 %x) {
350 ; CHECK-LABEL: test8:
351 ; CHECK:       // %bb.0:
352 ; CHECK-NEXT:    lsl w0, w0, #3
353 ; CHECK-NEXT:    ret
355 ; GISEL-LABEL: test8:
356 ; GISEL:       // %bb.0:
357 ; GISEL-NEXT:    lsl w0, w0, #3
358 ; GISEL-NEXT:    ret
360   %mul = shl nsw i32 %x, 3
361   ret i32 %mul
364 define i32 @test9(i32 %x) {
365 ; CHECK-LABEL: test9:
366 ; CHECK:       // %bb.0:
367 ; CHECK-NEXT:    add w0, w0, w0, lsl #3
368 ; CHECK-NEXT:    ret
370 ; GISEL-LABEL: test9:
371 ; GISEL:       // %bb.0:
372 ; GISEL-NEXT:    add w0, w0, w0, lsl #3
373 ; GISEL-NEXT:    ret
375   %mul = mul nsw i32 %x, 9
376   ret i32 %mul
379 define i32 @test10(i32 %x) {
380 ; CHECK-LABEL: test10:
381 ; CHECK:       // %bb.0:
382 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
383 ; CHECK-NEXT:    lsl w0, w8, #1
384 ; CHECK-NEXT:    ret
386 ; GISEL-LABEL: test10:
387 ; GISEL:       // %bb.0:
388 ; GISEL-NEXT:    add w8, w0, w0, lsl #2
389 ; GISEL-NEXT:    lsl w0, w8, #1
390 ; GISEL-NEXT:    ret
392   %mul = mul nsw i32 %x, 10
393   ret i32 %mul
396 define i32 @test11(i32 %x) {
397 ; CHECK-LABEL: test11:
398 ; CHECK:       // %bb.0:
399 ; CHECK-NEXT:    mov w8, #11 // =0xb
400 ; CHECK-NEXT:    mul w0, w0, w8
401 ; CHECK-NEXT:    ret
403 ; GISEL-LABEL: test11:
404 ; GISEL:       // %bb.0:
405 ; GISEL-NEXT:    mov w8, #11 // =0xb
406 ; GISEL-NEXT:    mul w0, w0, w8
407 ; GISEL-NEXT:    ret
409   %mul = mul nsw i32 %x, 11
410   ret i32 %mul
413 define i32 @test11_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
414 ; CHECK-LABEL: test11_fast_shift:
415 ; CHECK:       // %bb.0:
416 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
417 ; CHECK-NEXT:    add w0, w0, w8, lsl #1
418 ; CHECK-NEXT:    ret
420 ; GISEL-LABEL: test11_fast_shift:
421 ; GISEL:       // %bb.0:
422 ; GISEL-NEXT:    mov w8, #11 // =0xb
423 ; GISEL-NEXT:    mul w0, w0, w8
424 ; GISEL-NEXT:    ret
426   %mul = mul nsw i32 %x, 11 ; 11 = (((1<<2) + 1) << 1) + 1
427   ret i32 %mul
430 define i32 @test12(i32 %x) {
431 ; CHECK-LABEL: test12:
432 ; CHECK:       // %bb.0:
433 ; CHECK-NEXT:    add w8, w0, w0, lsl #1
434 ; CHECK-NEXT:    lsl w0, w8, #2
435 ; CHECK-NEXT:    ret
437 ; GISEL-LABEL: test12:
438 ; GISEL:       // %bb.0:
439 ; GISEL-NEXT:    add w8, w0, w0, lsl #1
440 ; GISEL-NEXT:    lsl w0, w8, #2
441 ; GISEL-NEXT:    ret
443   %mul = mul nsw i32 %x, 12
444   ret i32 %mul
447 define i32 @test13(i32 %x) {
448 ; CHECK-LABEL: test13:
449 ; CHECK:       // %bb.0:
450 ; CHECK-NEXT:    mov w8, #13 // =0xd
451 ; CHECK-NEXT:    mul w0, w0, w8
452 ; CHECK-NEXT:    ret
454 ; GISEL-LABEL: test13:
455 ; GISEL:       // %bb.0:
456 ; GISEL-NEXT:    mov w8, #13 // =0xd
457 ; GISEL-NEXT:    mul w0, w0, w8
458 ; GISEL-NEXT:    ret
460   %mul = mul nsw i32 %x, 13
461   ret i32 %mul
464 define i32 @test14(i32 %x) {
465 ; CHECK-LABEL: test14:
466 ; CHECK:       // %bb.0:
467 ; CHECK-NEXT:    lsl w8, w0, #4
468 ; CHECK-NEXT:    sub w0, w8, w0, lsl #1
469 ; CHECK-NEXT:    ret
471 ; GISEL-LABEL: test14:
472 ; GISEL:       // %bb.0:
473 ; GISEL-NEXT:    mov w8, #14 // =0xe
474 ; GISEL-NEXT:    mul w0, w0, w8
475 ; GISEL-NEXT:    ret
477   %mul = mul nsw i32 %x, 14
478   ret i32 %mul
481 define i32 @test15(i32 %x) {
482 ; CHECK-LABEL: test15:
483 ; CHECK:       // %bb.0:
484 ; CHECK-NEXT:    lsl w8, w0, #4
485 ; CHECK-NEXT:    sub w0, w8, w0
486 ; CHECK-NEXT:    ret
488 ; GISEL-LABEL: test15:
489 ; GISEL:       // %bb.0:
490 ; GISEL-NEXT:    lsl w8, w0, #4
491 ; GISEL-NEXT:    sub w0, w8, w0
492 ; GISEL-NEXT:    ret
494   %mul = mul nsw i32 %x, 15
495   ret i32 %mul
498 define i32 @test16(i32 %x) {
499 ; CHECK-LABEL: test16:
500 ; CHECK:       // %bb.0:
501 ; CHECK-NEXT:    lsl w0, w0, #4
502 ; CHECK-NEXT:    ret
504 ; GISEL-LABEL: test16:
505 ; GISEL:       // %bb.0:
506 ; GISEL-NEXT:    lsl w0, w0, #4
507 ; GISEL-NEXT:    ret
509   %mul = mul nsw i32 %x, 16
510   ret i32 %mul
513 define i32 @test25_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
514 ; CHECK-LABEL: test25_fast_shift:
515 ; CHECK:       // %bb.0:
516 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
517 ; CHECK-NEXT:    add w0, w8, w8, lsl #2
518 ; CHECK-NEXT:    ret
520 ; GISEL-LABEL: test25_fast_shift:
521 ; GISEL:       // %bb.0:
522 ; GISEL-NEXT:    mov w8, #25 // =0x19
523 ; GISEL-NEXT:    mul w0, w0, w8
524 ; GISEL-NEXT:    ret
526   %mul = mul nsw i32 %x, 25 ; 25 = (1+4)*(1+4)
527   ret i32 %mul
530 define i32 @test29_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
531 ; CHECK-LABEL: test29_fast_shift:
532 ; CHECK:       // %bb.0:
533 ; CHECK-NEXT:    sub w8, w0, w0, lsl #3
534 ; CHECK-NEXT:    sub w0, w0, w8, lsl #2
535 ; CHECK-NEXT:    ret
537 ; GISEL-LABEL: test29_fast_shift:
538 ; GISEL:       // %bb.0:
539 ; GISEL-NEXT:    mov w8, #29 // =0x1d
540 ; GISEL-NEXT:    mul w0, w0, w8
541 ; GISEL-NEXT:    ret
543   %mul = mul nsw i32 %x, 29 ; 29 = 1 - (1-8) * 4
544   ret i32 %mul
547 define i32 @test45_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
548 ; CHECK-LABEL: test45_fast_shift:
549 ; CHECK:       // %bb.0:
550 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
551 ; CHECK-NEXT:    add w0, w8, w8, lsl #3
552 ; CHECK-NEXT:    ret
554 ; GISEL-LABEL: test45_fast_shift:
555 ; GISEL:       // %bb.0:
556 ; GISEL-NEXT:    mov w8, #45 // =0x2d
557 ; GISEL-NEXT:    mul w0, w0, w8
558 ; GISEL-NEXT:    ret
560   %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)
561   ret i32 %mul
564 ; Negative test: Keep MUL as don't have the feature LSLFast
565 define i32 @test45(i32 %x) {
566 ; CHECK-LABEL: test45:
567 ; CHECK:       // %bb.0:
568 ; CHECK-NEXT:    mov w8, #45 // =0x2d
569 ; CHECK-NEXT:    mul w0, w0, w8
570 ; CHECK-NEXT:    ret
572 ; GISEL-LABEL: test45:
573 ; GISEL:       // %bb.0:
574 ; GISEL-NEXT:    mov w8, #45 // =0x2d
575 ; GISEL-NEXT:    mul w0, w0, w8
576 ; GISEL-NEXT:    ret
578   %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)
579   ret i32 %mul
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:
585 ; CHECK:       // %bb.0:
586 ; CHECK-NEXT:    mov w8, #67 // =0x43
587 ; CHECK-NEXT:    mul w0, w0, w8
588 ; CHECK-NEXT:    ret
590 ; GISEL-LABEL: test67_fast_shift:
591 ; GISEL:       // %bb.0:
592 ; GISEL-NEXT:    mov w8, #67 // =0x43
593 ; GISEL-NEXT:    mul w0, w0, w8
594 ; GISEL-NEXT:    ret
596   %mul = mul nsw i32 %x, 67 ; 67 = (((1<<5) + 1) << 1) + 1
597   ret i32 %mul
600 define i32 @test85_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
601 ; CHECK-LABEL: test85_fast_shift:
602 ; CHECK:       // %bb.0:
603 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
604 ; CHECK-NEXT:    add w0, w8, w8, lsl #4
605 ; CHECK-NEXT:    ret
607 ; GISEL-LABEL: test85_fast_shift:
608 ; GISEL:       // %bb.0:
609 ; GISEL-NEXT:    mov w8, #85 // =0x55
610 ; GISEL-NEXT:    mul w0, w0, w8
611 ; GISEL-NEXT:    ret
613   %mul = mul nsw i32 %x, 85 ; 85 = (1+4)*(1+16)
614   ret i32 %mul
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:
620 ; CHECK:       // %bb.0:
621 ; CHECK-NEXT:    mov w8, #97 // =0x61
622 ; CHECK-NEXT:    mul w0, w0, w8
623 ; CHECK-NEXT:    ret
625 ; GISEL-LABEL: test97_fast_shift:
626 ; GISEL:       // %bb.0:
627 ; GISEL-NEXT:    mov w8, #97 // =0x61
628 ; GISEL-NEXT:    mul w0, w0, w8
629 ; GISEL-NEXT:    ret
631   %mul = mul nsw i32 %x, 97 ; 97 = ((2 + 1) << 5) + 1
632   ret i32 %mul
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:
638 ; CHECK:       // %bb.0:
639 ; CHECK-NEXT:    mov w8, #125 // =0x7d
640 ; CHECK-NEXT:    mul w0, w0, w8
641 ; CHECK-NEXT:    ret
643 ; GISEL-LABEL: test125_fast_shift:
644 ; GISEL:       // %bb.0:
645 ; GISEL-NEXT:    mov w8, #125 // =0x7d
646 ; GISEL-NEXT:    mul w0, w0, w8
647 ; GISEL-NEXT:    ret
649   %mul = mul nsw i32 %x, 125 ; 125 = 1 - ((1-32) << 2)
650   ret i32 %mul
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:
656 ; CHECK:       // %bb.0:
657 ; CHECK-NEXT:    mov w8, #225 // =0xe1
658 ; CHECK-NEXT:    mul w0, w0, w8
659 ; CHECK-NEXT:    ret
661 ; GISEL-LABEL: test225_fast_shift:
662 ; GISEL:       // %bb.0:
663 ; GISEL-NEXT:    mov w8, #225 // =0xe1
664 ; GISEL-NEXT:    mul w0, w0, w8
665 ; GISEL-NEXT:    ret
667   %mul = mul nsw i32 %x, 225 ; 225 = (1-16)*(1-16)
668   ret i32 %mul
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:
674 ; CHECK:       // %bb.0:
675 ; CHECK-NEXT:    mov w8, #297 // =0x129
676 ; CHECK-NEXT:    mul w0, w0, w8
677 ; CHECK-NEXT:    ret
679 ; GISEL-LABEL: test297_fast_shift:
680 ; GISEL:       // %bb.0:
681 ; GISEL-NEXT:    mov w8, #297 // =0x129
682 ; GISEL-NEXT:    mul w0, w0, w8
683 ; GISEL-NEXT:    ret
685   %mul = mul nsw i32 %x, 297 ; 297 = (1+8)*(1+32)
686   ret i32 %mul
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:
692 ; CHECK:       // %bb.0:
693 ; CHECK-NEXT:    mov w8, #481 // =0x1e1
694 ; CHECK-NEXT:    mul w0, w0, w8
695 ; CHECK-NEXT:    ret
697 ; GISEL-LABEL: test481_fast_shift:
698 ; GISEL:       // %bb.0:
699 ; GISEL-NEXT:    mov w8, #481 // =0x1e1
700 ; GISEL-NEXT:    mul w0, w0, w8
701 ; GISEL-NEXT:    ret
703   %mul = mul nsw i32 %x, 481 ; 481 = 1 - ((1-16) << 5)
704   ret i32 %mul
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:
713 ; CHECK:       // %bb.0:
714 ; CHECK-NEXT:    neg w0, w0, lsl #1
715 ; CHECK-NEXT:    ret
717 ; GISEL-LABEL: ntest2:
718 ; GISEL:       // %bb.0:
719 ; GISEL-NEXT:    mov w8, #-2 // =0xfffffffe
720 ; GISEL-NEXT:    mul w0, w0, w8
721 ; GISEL-NEXT:    ret
723   %mul = mul nsw i32 %x, -2
724   ret i32 %mul
727 define i32 @ntest3(i32 %x) {
728 ; CHECK-LABEL: ntest3:
729 ; CHECK:       // %bb.0:
730 ; CHECK-NEXT:    sub w0, w0, w0, lsl #2
731 ; CHECK-NEXT:    ret
733 ; GISEL-LABEL: ntest3:
734 ; GISEL:       // %bb.0:
735 ; GISEL-NEXT:    sub w0, w0, w0, lsl #2
736 ; GISEL-NEXT:    ret
738   %mul = mul nsw i32 %x, -3
739   ret i32 %mul
742 define i32 @ntest4(i32 %x) {
743 ; CHECK-LABEL: ntest4:
744 ; CHECK:       // %bb.0:
745 ; CHECK-NEXT:    neg w0, w0, lsl #2
746 ; CHECK-NEXT:    ret
748 ; GISEL-LABEL: ntest4:
749 ; GISEL:       // %bb.0:
750 ; GISEL-NEXT:    mov w8, #-4 // =0xfffffffc
751 ; GISEL-NEXT:    mul w0, w0, w8
752 ; GISEL-NEXT:    ret
754   %mul = mul nsw i32 %x, -4
755   ret i32 %mul
758 define i32 @ntest5(i32 %x) {
759 ; CHECK-LABEL: ntest5:
760 ; CHECK:       // %bb.0:
761 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
762 ; CHECK-NEXT:    neg w0, w8
763 ; CHECK-NEXT:    ret
765 ; GISEL-LABEL: ntest5:
766 ; GISEL:       // %bb.0:
767 ; GISEL-NEXT:    add w8, w0, w0, lsl #2
768 ; GISEL-NEXT:    neg w0, w8
769 ; GISEL-NEXT:    ret
770   %mul = mul nsw i32 %x, -5
771   ret i32 %mul
774 define i32 @ntest6(i32 %x) {
775 ; CHECK-LABEL: ntest6:
776 ; CHECK:       // %bb.0:
777 ; CHECK-NEXT:    lsl w8, w0, #1
778 ; CHECK-NEXT:    sub w0, w8, w0, lsl #3
779 ; CHECK-NEXT:    ret
781 ; GISEL-LABEL: ntest6:
782 ; GISEL:       // %bb.0:
783 ; GISEL-NEXT:    mov w8, #-6 // =0xfffffffa
784 ; GISEL-NEXT:    mul w0, w0, w8
785 ; GISEL-NEXT:    ret
787   %mul = mul nsw i32 %x, -6
788   ret i32 %mul
791 define i32 @ntest7(i32 %x) {
792 ; CHECK-LABEL: ntest7:
793 ; CHECK:       // %bb.0:
794 ; CHECK-NEXT:    sub w0, w0, w0, lsl #3
795 ; CHECK-NEXT:    ret
797 ; GISEL-LABEL: ntest7:
798 ; GISEL:       // %bb.0:
799 ; GISEL-NEXT:    sub w0, w0, w0, lsl #3
800 ; GISEL-NEXT:    ret
802   %mul = mul nsw i32 %x, -7
803   ret i32 %mul
806 define i32 @ntest8(i32 %x) {
807 ; CHECK-LABEL: ntest8:
808 ; CHECK:       // %bb.0:
809 ; CHECK-NEXT:    neg w0, w0, lsl #3
810 ; CHECK-NEXT:    ret
812 ; GISEL-LABEL: ntest8:
813 ; GISEL:       // %bb.0:
814 ; GISEL-NEXT:    mov w8, #-8 // =0xfffffff8
815 ; GISEL-NEXT:    mul w0, w0, w8
816 ; GISEL-NEXT:    ret
818   %mul = mul nsw i32 %x, -8
819   ret i32 %mul
822 define i32 @ntest9(i32 %x) {
823 ; CHECK-LABEL: ntest9:
824 ; CHECK:       // %bb.0:
825 ; CHECK-NEXT:    add w8, w0, w0, lsl #3
826 ; CHECK-NEXT:    neg w0, w8
827 ; CHECK-NEXT:    ret
829 ; GISEL-LABEL: ntest9:
830 ; GISEL:       // %bb.0:
831 ; GISEL-NEXT:    add w8, w0, w0, lsl #3
832 ; GISEL-NEXT:    neg w0, w8
833 ; GISEL-NEXT:    ret
835   %mul = mul nsw i32 %x, -9
836   ret i32 %mul
839 define i32 @ntest10(i32 %x) {
840 ; CHECK-LABEL: ntest10:
841 ; CHECK:       // %bb.0:
842 ; CHECK-NEXT:    mov w8, #-10 // =0xfffffff6
843 ; CHECK-NEXT:    mul w0, w0, w8
844 ; CHECK-NEXT:    ret
846 ; GISEL-LABEL: ntest10:
847 ; GISEL:       // %bb.0:
848 ; GISEL-NEXT:    mov w8, #-10 // =0xfffffff6
849 ; GISEL-NEXT:    mul w0, w0, w8
850 ; GISEL-NEXT:    ret
852   %mul = mul nsw i32 %x, -10
853   ret i32 %mul
856 define i32 @ntest11(i32 %x) {
857 ; CHECK-LABEL: ntest11:
858 ; CHECK:       // %bb.0:
859 ; CHECK-NEXT:    mov w8, #-11 // =0xfffffff5
860 ; CHECK-NEXT:    mul w0, w0, w8
861 ; CHECK-NEXT:    ret
863 ; GISEL-LABEL: ntest11:
864 ; GISEL:       // %bb.0:
865 ; GISEL-NEXT:    mov w8, #-11 // =0xfffffff5
866 ; GISEL-NEXT:    mul w0, w0, w8
867 ; GISEL-NEXT:    ret
869   %mul = mul nsw i32 %x, -11
870   ret i32 %mul
873 define i32 @ntest12(i32 %x) {
874 ; CHECK-LABEL: ntest12:
875 ; CHECK:       // %bb.0:
876 ; CHECK-NEXT:    lsl w8, w0, #2
877 ; CHECK-NEXT:    sub w0, w8, w0, lsl #4
878 ; CHECK-NEXT:    ret
880 ; GISEL-LABEL: ntest12:
881 ; GISEL:       // %bb.0:
882 ; GISEL-NEXT:    mov w8, #-12 // =0xfffffff4
883 ; GISEL-NEXT:    mul w0, w0, w8
884 ; GISEL-NEXT:    ret
886   %mul = mul nsw i32 %x, -12
887   ret i32 %mul
890 define i32 @ntest13(i32 %x) {
891 ; CHECK-LABEL: ntest13:
892 ; CHECK:       // %bb.0:
893 ; CHECK-NEXT:    mov w8, #-13 // =0xfffffff3
894 ; CHECK-NEXT:    mul w0, w0, w8
895 ; CHECK-NEXT:    ret
897 ; GISEL-LABEL: ntest13:
898 ; GISEL:       // %bb.0:
899 ; GISEL-NEXT:    mov w8, #-13 // =0xfffffff3
900 ; GISEL-NEXT:    mul w0, w0, w8
901 ; GISEL-NEXT:    ret
902   %mul = mul nsw i32 %x, -13
903   ret i32 %mul
906 define i32 @ntest14(i32 %x) {
907 ; CHECK-LABEL: ntest14:
908 ; CHECK:       // %bb.0:
909 ; CHECK-NEXT:    lsl w8, w0, #1
910 ; CHECK-NEXT:    sub w0, w8, w0, lsl #4
911 ; CHECK-NEXT:    ret
913 ; GISEL-LABEL: ntest14:
914 ; GISEL:       // %bb.0:
915 ; GISEL-NEXT:    mov w8, #-14 // =0xfffffff2
916 ; GISEL-NEXT:    mul w0, w0, w8
917 ; GISEL-NEXT:    ret
919   %mul = mul nsw i32 %x, -14
920   ret i32 %mul
923 define i32 @ntest15(i32 %x) {
924 ; CHECK-LABEL: ntest15:
925 ; CHECK:       // %bb.0:
926 ; CHECK-NEXT:    sub w0, w0, w0, lsl #4
927 ; CHECK-NEXT:    ret
929 ; GISEL-LABEL: ntest15:
930 ; GISEL:       // %bb.0:
931 ; GISEL-NEXT:    sub w0, w0, w0, lsl #4
932 ; GISEL-NEXT:    ret
934   %mul = mul nsw i32 %x, -15
935   ret i32 %mul
938 define i32 @ntest16(i32 %x) {
939 ; CHECK-LABEL: ntest16:
940 ; CHECK:       // %bb.0:
941 ; CHECK-NEXT:    neg w0, w0, lsl #4
942 ; CHECK-NEXT:    ret
944 ; GISEL-LABEL: ntest16:
945 ; GISEL:       // %bb.0:
946 ; GISEL-NEXT:    mov w8, #-16 // =0xfffffff0
947 ; GISEL-NEXT:    mul w0, w0, w8
948 ; GISEL-NEXT:    ret
950   %mul = mul nsw i32 %x, -16
951   ret i32 %mul
954 define i32 @muladd_demand(i32 %x, i32 %y) {
955 ; CHECK-LABEL: muladd_demand:
956 ; CHECK:       // %bb.0:
957 ; CHECK-NEXT:    sub w8, w1, w0, lsl #6
958 ; CHECK-NEXT:    and w0, w8, #0x1ffc0
959 ; CHECK-NEXT:    ret
961 ; GISEL-LABEL: muladd_demand:
962 ; GISEL:       // %bb.0:
963 ; GISEL-NEXT:    mov w8, #131008 // =0x1ffc0
964 ; GISEL-NEXT:    madd w8, w0, w8, w1
965 ; GISEL-NEXT:    and w0, w8, #0x1ffc0
966 ; GISEL-NEXT:    ret
967   %m = mul i32 %x, 131008 ; 0x0001ffc0
968   %a = add i32 %y, %m
969   %r = and i32 %a, 131008
970   ret i32 %r
973 define <4 x i32> @muladd_demand_commute(<4 x i32> %x, <4 x i32> %y) {
974 ; CHECK-LABEL: muladd_demand_commute:
975 ; CHECK:       // %bb.0:
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
980 ; CHECK-NEXT:    ret
982 ; GISEL-LABEL: muladd_demand_commute:
983 ; GISEL:       // %bb.0:
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
989 ; GISEL-NEXT:    ret
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>
993   ret <4 x i32> %r
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:
1000 ; CHECK:       // %bb.0:
1001 ; CHECK-NEXT:    mov w8, #-2147483648 // =0x80000000
1002 ; CHECK-NEXT:    mul w0, w0, w8
1003 ; CHECK-NEXT:    ret
1005 ; GISEL-LABEL: shift_overflow:
1006 ; GISEL:       // %bb.0:
1007 ; GISEL-NEXT:    mov w8, #-2147483648 // =0x80000000
1008 ; GISEL-NEXT:    mul w0, w0, w8
1009 ; GISEL-NEXT:    ret
1010   %const = bitcast i32 2147483648 to i32
1011   %r = mul i32 %x, %const
1012   ret i32 %r
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:
1019 ; CHECK:       // %bb.0:
1020 ; CHECK-NEXT:    lsl w8, w0, #31
1021 ; CHECK-NEXT:    sub w0, w8, w0, lsl #30
1022 ; CHECK-NEXT:    ret
1024 ; GISEL-LABEL: shift_no_overflow:
1025 ; GISEL:       // %bb.0:
1026 ; GISEL-NEXT:    mov w8, #1073741824 // =0x40000000
1027 ; GISEL-NEXT:    mul w0, w0, w8
1028 ; GISEL-NEXT:    ret
1029   %const = bitcast i32 1073741824 to i32
1030   %r = mul i32 %x, %const
1031   ret i32 %r