Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / test / CodeGen / AArch64 / mul_pow2.ll
blobe16ee40c8dcb0d65dc76a020c7e6949f235e7aa2
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=aarch64-eabi | FileCheck %s
3 ; RUN: llc < %s -mtriple=aarch64-eabi -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 @test12(i32 %x) {
414 ; CHECK-LABEL: test12:
415 ; CHECK:       // %bb.0:
416 ; CHECK-NEXT:    add w8, w0, w0, lsl #1
417 ; CHECK-NEXT:    lsl w0, w8, #2
418 ; CHECK-NEXT:    ret
420 ; GISEL-LABEL: test12:
421 ; GISEL:       // %bb.0:
422 ; GISEL-NEXT:    add w8, w0, w0, lsl #1
423 ; GISEL-NEXT:    lsl w0, w8, #2
424 ; GISEL-NEXT:    ret
426   %mul = mul nsw i32 %x, 12
427   ret i32 %mul
430 define i32 @test13(i32 %x) {
431 ; CHECK-LABEL: test13:
432 ; CHECK:       // %bb.0:
433 ; CHECK-NEXT:    mov w8, #13 // =0xd
434 ; CHECK-NEXT:    mul w0, w0, w8
435 ; CHECK-NEXT:    ret
437 ; GISEL-LABEL: test13:
438 ; GISEL:       // %bb.0:
439 ; GISEL-NEXT:    mov w8, #13 // =0xd
440 ; GISEL-NEXT:    mul w0, w0, w8
441 ; GISEL-NEXT:    ret
443   %mul = mul nsw i32 %x, 13
444   ret i32 %mul
447 define i32 @test14(i32 %x) {
448 ; CHECK-LABEL: test14:
449 ; CHECK:       // %bb.0:
450 ; CHECK-NEXT:    lsl w8, w0, #4
451 ; CHECK-NEXT:    sub w0, w8, w0, lsl #1
452 ; CHECK-NEXT:    ret
454 ; GISEL-LABEL: test14:
455 ; GISEL:       // %bb.0:
456 ; GISEL-NEXT:    mov w8, #14 // =0xe
457 ; GISEL-NEXT:    mul w0, w0, w8
458 ; GISEL-NEXT:    ret
460   %mul = mul nsw i32 %x, 14
461   ret i32 %mul
464 define i32 @test15(i32 %x) {
465 ; CHECK-LABEL: test15:
466 ; CHECK:       // %bb.0:
467 ; CHECK-NEXT:    lsl w8, w0, #4
468 ; CHECK-NEXT:    sub w0, w8, w0
469 ; CHECK-NEXT:    ret
471 ; GISEL-LABEL: test15:
472 ; GISEL:       // %bb.0:
473 ; GISEL-NEXT:    lsl w8, w0, #4
474 ; GISEL-NEXT:    sub w0, w8, w0
475 ; GISEL-NEXT:    ret
477   %mul = mul nsw i32 %x, 15
478   ret i32 %mul
481 define i32 @test16(i32 %x) {
482 ; CHECK-LABEL: test16:
483 ; CHECK:       // %bb.0:
484 ; CHECK-NEXT:    lsl w0, w0, #4
485 ; CHECK-NEXT:    ret
487 ; GISEL-LABEL: test16:
488 ; GISEL:       // %bb.0:
489 ; GISEL-NEXT:    lsl w0, w0, #4
490 ; GISEL-NEXT:    ret
492   %mul = mul nsw i32 %x, 16
493   ret i32 %mul
496 define i32 @test25_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
497 ; CHECK-LABEL: test25_fast_shift:
498 ; CHECK:       // %bb.0:
499 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
500 ; CHECK-NEXT:    add w0, w8, w8, lsl #2
501 ; CHECK-NEXT:    ret
503 ; GISEL-LABEL: test25_fast_shift:
504 ; GISEL:       // %bb.0:
505 ; GISEL-NEXT:    mov w8, #25 // =0x19
506 ; GISEL-NEXT:    mul w0, w0, w8
507 ; GISEL-NEXT:    ret
509   %mul = mul nsw i32 %x, 25 ; 25 = (1+4)*(1+4)
510   ret i32 %mul
513 define i32 @test45_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
514 ; CHECK-LABEL: test45_fast_shift:
515 ; CHECK:       // %bb.0:
516 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
517 ; CHECK-NEXT:    add w0, w8, w8, lsl #3
518 ; CHECK-NEXT:    ret
520 ; GISEL-LABEL: test45_fast_shift:
521 ; GISEL:       // %bb.0:
522 ; GISEL-NEXT:    mov w8, #45 // =0x2d
523 ; GISEL-NEXT:    mul w0, w0, w8
524 ; GISEL-NEXT:    ret
526   %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)
527   ret i32 %mul
530 ; Negative test: Keep MUL as don't have the feature LSLFast
531 define i32 @test45(i32 %x) {
532 ; CHECK-LABEL: test45:
533 ; CHECK:       // %bb.0:
534 ; CHECK-NEXT:    mov w8, #45 // =0x2d
535 ; CHECK-NEXT:    mul w0, w0, w8
536 ; CHECK-NEXT:    ret
538 ; GISEL-LABEL: test45:
539 ; GISEL:       // %bb.0:
540 ; GISEL-NEXT:    mov w8, #45 // =0x2d
541 ; GISEL-NEXT:    mul w0, w0, w8
542 ; GISEL-NEXT:    ret
544   %mul = mul nsw i32 %x, 45 ; 45 = (1+4)*(1+8)
545   ret i32 %mul
548 ; Negative test: The shift amount 4 larger than 3
549 define i32 @test85_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
550 ; CHECK-LABEL: test85_fast_shift:
551 ; CHECK:       // %bb.0:
552 ; CHECK-NEXT:    mov w8, #85 // =0x55
553 ; CHECK-NEXT:    mul w0, w0, w8
554 ; CHECK-NEXT:    ret
556 ; GISEL-LABEL: test85_fast_shift:
557 ; GISEL:       // %bb.0:
558 ; GISEL-NEXT:    mov w8, #85 // =0x55
559 ; GISEL-NEXT:    mul w0, w0, w8
560 ; GISEL-NEXT:    ret
562   %mul = mul nsw i32 %x, 85 ; 85 = (1+4)*(1+16)
563   ret i32 %mul
566 ; Negative test: The shift amount 5 larger than 3
567 define i32 @test297_fast_shift(i32 %x) "target-features"="+alu-lsl-fast" {
568 ; CHECK-LABEL: test297_fast_shift:
569 ; CHECK:       // %bb.0:
570 ; CHECK-NEXT:    mov w8, #297 // =0x129
571 ; CHECK-NEXT:    mul w0, w0, w8
572 ; CHECK-NEXT:    ret
574 ; GISEL-LABEL: test297_fast_shift:
575 ; GISEL:       // %bb.0:
576 ; GISEL-NEXT:    mov w8, #297 // =0x129
577 ; GISEL-NEXT:    mul w0, w0, w8
578 ; GISEL-NEXT:    ret
580   %mul = mul nsw i32 %x, 297 ; 297 = (1+8)*(1+32)
581   ret i32 %mul
584 ; Convert mul x, -pow2 to shift.
585 ; Convert mul x, -(pow2 +/- 1) to shift + add/sub.
586 ; Lowering other negative constants are not supported yet.
588 define i32 @ntest2(i32 %x) {
589 ; CHECK-LABEL: ntest2:
590 ; CHECK:       // %bb.0:
591 ; CHECK-NEXT:    neg w0, w0, lsl #1
592 ; CHECK-NEXT:    ret
594 ; GISEL-LABEL: ntest2:
595 ; GISEL:       // %bb.0:
596 ; GISEL-NEXT:    mov w8, #-2 // =0xfffffffe
597 ; GISEL-NEXT:    mul w0, w0, w8
598 ; GISEL-NEXT:    ret
600   %mul = mul nsw i32 %x, -2
601   ret i32 %mul
604 define i32 @ntest3(i32 %x) {
605 ; CHECK-LABEL: ntest3:
606 ; CHECK:       // %bb.0:
607 ; CHECK-NEXT:    sub w0, w0, w0, lsl #2
608 ; CHECK-NEXT:    ret
610 ; GISEL-LABEL: ntest3:
611 ; GISEL:       // %bb.0:
612 ; GISEL-NEXT:    sub w0, w0, w0, lsl #2
613 ; GISEL-NEXT:    ret
615   %mul = mul nsw i32 %x, -3
616   ret i32 %mul
619 define i32 @ntest4(i32 %x) {
620 ; CHECK-LABEL: ntest4:
621 ; CHECK:       // %bb.0:
622 ; CHECK-NEXT:    neg w0, w0, lsl #2
623 ; CHECK-NEXT:    ret
625 ; GISEL-LABEL: ntest4:
626 ; GISEL:       // %bb.0:
627 ; GISEL-NEXT:    mov w8, #-4 // =0xfffffffc
628 ; GISEL-NEXT:    mul w0, w0, w8
629 ; GISEL-NEXT:    ret
631   %mul = mul nsw i32 %x, -4
632   ret i32 %mul
635 define i32 @ntest5(i32 %x) {
636 ; CHECK-LABEL: ntest5:
637 ; CHECK:       // %bb.0:
638 ; CHECK-NEXT:    add w8, w0, w0, lsl #2
639 ; CHECK-NEXT:    neg w0, w8
640 ; CHECK-NEXT:    ret
642 ; GISEL-LABEL: ntest5:
643 ; GISEL:       // %bb.0:
644 ; GISEL-NEXT:    add w8, w0, w0, lsl #2
645 ; GISEL-NEXT:    neg w0, w8
646 ; GISEL-NEXT:    ret
647   %mul = mul nsw i32 %x, -5
648   ret i32 %mul
651 define i32 @ntest6(i32 %x) {
652 ; CHECK-LABEL: ntest6:
653 ; CHECK:       // %bb.0:
654 ; CHECK-NEXT:    lsl w8, w0, #1
655 ; CHECK-NEXT:    sub w0, w8, w0, lsl #3
656 ; CHECK-NEXT:    ret
658 ; GISEL-LABEL: ntest6:
659 ; GISEL:       // %bb.0:
660 ; GISEL-NEXT:    mov w8, #-6 // =0xfffffffa
661 ; GISEL-NEXT:    mul w0, w0, w8
662 ; GISEL-NEXT:    ret
664   %mul = mul nsw i32 %x, -6
665   ret i32 %mul
668 define i32 @ntest7(i32 %x) {
669 ; CHECK-LABEL: ntest7:
670 ; CHECK:       // %bb.0:
671 ; CHECK-NEXT:    sub w0, w0, w0, lsl #3
672 ; CHECK-NEXT:    ret
674 ; GISEL-LABEL: ntest7:
675 ; GISEL:       // %bb.0:
676 ; GISEL-NEXT:    sub w0, w0, w0, lsl #3
677 ; GISEL-NEXT:    ret
679   %mul = mul nsw i32 %x, -7
680   ret i32 %mul
683 define i32 @ntest8(i32 %x) {
684 ; CHECK-LABEL: ntest8:
685 ; CHECK:       // %bb.0:
686 ; CHECK-NEXT:    neg w0, w0, lsl #3
687 ; CHECK-NEXT:    ret
689 ; GISEL-LABEL: ntest8:
690 ; GISEL:       // %bb.0:
691 ; GISEL-NEXT:    mov w8, #-8 // =0xfffffff8
692 ; GISEL-NEXT:    mul w0, w0, w8
693 ; GISEL-NEXT:    ret
695   %mul = mul nsw i32 %x, -8
696   ret i32 %mul
699 define i32 @ntest9(i32 %x) {
700 ; CHECK-LABEL: ntest9:
701 ; CHECK:       // %bb.0:
702 ; CHECK-NEXT:    add w8, w0, w0, lsl #3
703 ; CHECK-NEXT:    neg w0, w8
704 ; CHECK-NEXT:    ret
706 ; GISEL-LABEL: ntest9:
707 ; GISEL:       // %bb.0:
708 ; GISEL-NEXT:    add w8, w0, w0, lsl #3
709 ; GISEL-NEXT:    neg w0, w8
710 ; GISEL-NEXT:    ret
712   %mul = mul nsw i32 %x, -9
713   ret i32 %mul
716 define i32 @ntest10(i32 %x) {
717 ; CHECK-LABEL: ntest10:
718 ; CHECK:       // %bb.0:
719 ; CHECK-NEXT:    mov w8, #-10 // =0xfffffff6
720 ; CHECK-NEXT:    mul w0, w0, w8
721 ; CHECK-NEXT:    ret
723 ; GISEL-LABEL: ntest10:
724 ; GISEL:       // %bb.0:
725 ; GISEL-NEXT:    mov w8, #-10 // =0xfffffff6
726 ; GISEL-NEXT:    mul w0, w0, w8
727 ; GISEL-NEXT:    ret
729   %mul = mul nsw i32 %x, -10
730   ret i32 %mul
733 define i32 @ntest11(i32 %x) {
734 ; CHECK-LABEL: ntest11:
735 ; CHECK:       // %bb.0:
736 ; CHECK-NEXT:    mov w8, #-11 // =0xfffffff5
737 ; CHECK-NEXT:    mul w0, w0, w8
738 ; CHECK-NEXT:    ret
740 ; GISEL-LABEL: ntest11:
741 ; GISEL:       // %bb.0:
742 ; GISEL-NEXT:    mov w8, #-11 // =0xfffffff5
743 ; GISEL-NEXT:    mul w0, w0, w8
744 ; GISEL-NEXT:    ret
746   %mul = mul nsw i32 %x, -11
747   ret i32 %mul
750 define i32 @ntest12(i32 %x) {
751 ; CHECK-LABEL: ntest12:
752 ; CHECK:       // %bb.0:
753 ; CHECK-NEXT:    lsl w8, w0, #2
754 ; CHECK-NEXT:    sub w0, w8, w0, lsl #4
755 ; CHECK-NEXT:    ret
757 ; GISEL-LABEL: ntest12:
758 ; GISEL:       // %bb.0:
759 ; GISEL-NEXT:    mov w8, #-12 // =0xfffffff4
760 ; GISEL-NEXT:    mul w0, w0, w8
761 ; GISEL-NEXT:    ret
763   %mul = mul nsw i32 %x, -12
764   ret i32 %mul
767 define i32 @ntest13(i32 %x) {
768 ; CHECK-LABEL: ntest13:
769 ; CHECK:       // %bb.0:
770 ; CHECK-NEXT:    mov w8, #-13 // =0xfffffff3
771 ; CHECK-NEXT:    mul w0, w0, w8
772 ; CHECK-NEXT:    ret
774 ; GISEL-LABEL: ntest13:
775 ; GISEL:       // %bb.0:
776 ; GISEL-NEXT:    mov w8, #-13 // =0xfffffff3
777 ; GISEL-NEXT:    mul w0, w0, w8
778 ; GISEL-NEXT:    ret
779   %mul = mul nsw i32 %x, -13
780   ret i32 %mul
783 define i32 @ntest14(i32 %x) {
784 ; CHECK-LABEL: ntest14:
785 ; CHECK:       // %bb.0:
786 ; CHECK-NEXT:    lsl w8, w0, #1
787 ; CHECK-NEXT:    sub w0, w8, w0, lsl #4
788 ; CHECK-NEXT:    ret
790 ; GISEL-LABEL: ntest14:
791 ; GISEL:       // %bb.0:
792 ; GISEL-NEXT:    mov w8, #-14 // =0xfffffff2
793 ; GISEL-NEXT:    mul w0, w0, w8
794 ; GISEL-NEXT:    ret
796   %mul = mul nsw i32 %x, -14
797   ret i32 %mul
800 define i32 @ntest15(i32 %x) {
801 ; CHECK-LABEL: ntest15:
802 ; CHECK:       // %bb.0:
803 ; CHECK-NEXT:    sub w0, w0, w0, lsl #4
804 ; CHECK-NEXT:    ret
806 ; GISEL-LABEL: ntest15:
807 ; GISEL:       // %bb.0:
808 ; GISEL-NEXT:    sub w0, w0, w0, lsl #4
809 ; GISEL-NEXT:    ret
811   %mul = mul nsw i32 %x, -15
812   ret i32 %mul
815 define i32 @ntest16(i32 %x) {
816 ; CHECK-LABEL: ntest16:
817 ; CHECK:       // %bb.0:
818 ; CHECK-NEXT:    neg w0, w0, lsl #4
819 ; CHECK-NEXT:    ret
821 ; GISEL-LABEL: ntest16:
822 ; GISEL:       // %bb.0:
823 ; GISEL-NEXT:    mov w8, #-16 // =0xfffffff0
824 ; GISEL-NEXT:    mul w0, w0, w8
825 ; GISEL-NEXT:    ret
827   %mul = mul nsw i32 %x, -16
828   ret i32 %mul
831 define i32 @muladd_demand(i32 %x, i32 %y) {
832 ; CHECK-LABEL: muladd_demand:
833 ; CHECK:       // %bb.0:
834 ; CHECK-NEXT:    sub w8, w1, w0, lsl #6
835 ; CHECK-NEXT:    and w0, w8, #0x1ffc0
836 ; CHECK-NEXT:    ret
838 ; GISEL-LABEL: muladd_demand:
839 ; GISEL:       // %bb.0:
840 ; GISEL-NEXT:    mov w8, #131008 // =0x1ffc0
841 ; GISEL-NEXT:    madd w8, w0, w8, w1
842 ; GISEL-NEXT:    and w0, w8, #0x1ffc0
843 ; GISEL-NEXT:    ret
844   %m = mul i32 %x, 131008 ; 0x0001ffc0
845   %a = add i32 %y, %m
846   %r = and i32 %a, 131008
847   ret i32 %r
850 define <4 x i32> @muladd_demand_commute(<4 x i32> %x, <4 x i32> %y) {
851 ; CHECK-LABEL: muladd_demand_commute:
852 ; CHECK:       // %bb.0:
853 ; CHECK-NEXT:    shl v0.4s, v0.4s, #6
854 ; CHECK-NEXT:    movi v2.4s, #1, msl #16
855 ; CHECK-NEXT:    sub v0.4s, v1.4s, v0.4s
856 ; CHECK-NEXT:    and v0.16b, v0.16b, v2.16b
857 ; CHECK-NEXT:    ret
859 ; GISEL-LABEL: muladd_demand_commute:
860 ; GISEL:       // %bb.0:
861 ; GISEL-NEXT:    adrp x8, .LCPI49_0
862 ; GISEL-NEXT:    movi v3.4s, #1, msl #16
863 ; GISEL-NEXT:    ldr q2, [x8, :lo12:.LCPI49_0]
864 ; GISEL-NEXT:    mla v1.4s, v0.4s, v2.4s
865 ; GISEL-NEXT:    and v0.16b, v1.16b, v3.16b
866 ; GISEL-NEXT:    ret
867   %m = mul <4 x i32> %x, <i32 131008, i32 131008, i32 131008, i32 131008>
868   %a = add <4 x i32> %m, %y
869   %r = and <4 x i32> %a, <i32 131071, i32 131071, i32 131071, i32 131071>
870   ret <4 x i32> %r