1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -debugify-and-strip-all-safe -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
3 ; RUN: llc -debugify-and-strip-all-safe -global-isel -enable-machine-outliner=never -verify-machineinstrs %s -o - -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
5 define i32 @add_z_i8i32(i8 %v, i32 %lhs) minsize {
6 ; CHECK-LABEL: add_z_i8i32:
8 ; CHECK-NEXT: add w0, w1, w0, uxtb
10 %vz = zext i8 %v to i32
11 %r = add i32 %lhs, %vz
15 define i32 @add_z_shli8i32(i8 %v, i32 %lhs) minsize {
16 ; CHECK-LABEL: add_z_shli8i32:
18 ; CHECK-NEXT: add w0, w1, w0, uxtb #3
20 %vz = zext i8 %v to i32
26 define i64 @add_z_i8i64(i8 %v, i64 %lhs) minsize {
27 ; CHECK-LABEL: add_z_i8i64:
29 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
30 ; CHECK-NEXT: add x0, x1, w0, uxtb
32 %vz = zext i8 %v to i64
33 %r = add i64 %lhs, %vz
37 define i64 @add_z_shli8i64(i8 %v, i64 %lhs) minsize {
38 ; CHECK-LABEL: add_z_shli8i64:
40 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
41 ; CHECK-NEXT: add x0, x1, w0, uxtb #3
43 %vz = zext i8 %v to i64
49 define i32 @add_s_i8i32(i8 %v, i32 %lhs) minsize {
50 ; CHECK-LABEL: add_s_i8i32:
52 ; CHECK-NEXT: add w0, w1, w0, sxtb
54 %vz = sext i8 %v to i32
55 %r = add i32 %lhs, %vz
59 define i32 @add_s_shli8i32(i8 %v, i32 %lhs) minsize {
60 ; CHECK-LABEL: add_s_shli8i32:
62 ; CHECK-NEXT: add w0, w1, w0, sxtb #3
64 %vz = sext i8 %v to i32
70 define i64 @add_s_i8i64(i8 %v, i64 %lhs) minsize {
71 ; CHECK-LABEL: add_s_i8i64:
73 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
74 ; CHECK-NEXT: add x0, x1, w0, sxtb
76 %vz = sext i8 %v to i64
77 %r = add i64 %lhs, %vz
81 define i64 @add_s_shli8i64(i8 %v, i64 %lhs) minsize {
82 ; CHECK-LABEL: add_s_shli8i64:
84 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
85 ; CHECK-NEXT: add x0, x1, w0, sxtb #3
87 %vz = sext i8 %v to i64
93 define i32 @add_z_i16i32(i16 %v, i32 %lhs) minsize {
94 ; CHECK-LABEL: add_z_i16i32:
96 ; CHECK-NEXT: add w0, w1, w0, uxth
98 %vz = zext i16 %v to i32
99 %r = add i32 %lhs, %vz
103 define i32 @add_z_shli16i32(i16 %v, i32 %lhs) minsize {
104 ; CHECK-LABEL: add_z_shli16i32:
106 ; CHECK-NEXT: add w0, w1, w0, uxth #3
108 %vz = zext i16 %v to i32
110 %r = add i32 %lhs, %s
114 define i64 @add_z_i16i64(i16 %v, i64 %lhs) minsize {
115 ; CHECK-LABEL: add_z_i16i64:
117 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
118 ; CHECK-NEXT: add x0, x1, w0, uxth
120 %vz = zext i16 %v to i64
121 %r = add i64 %lhs, %vz
125 define i64 @add_z_shli16i64(i16 %v, i64 %lhs) minsize {
126 ; CHECK-LABEL: add_z_shli16i64:
128 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
129 ; CHECK-NEXT: add x0, x1, w0, uxth #3
131 %vz = zext i16 %v to i64
133 %r = add i64 %lhs, %s
137 define i64 @add_z_i32i64(i32 %v, i64 %lhs) minsize {
138 ; CHECK-LABEL: add_z_i32i64:
140 ; CHECK-NEXT: add x0, x1, w0, uxtw
142 %vz = zext i32 %v to i64
143 %r = add i64 %lhs, %vz
147 define i64 @add_z_shli32i64(i32 %v, i64 %lhs) minsize {
148 ; CHECK-LABEL: add_z_shli32i64:
150 ; CHECK-NEXT: add x0, x1, w0, uxtw #3
152 %vz = zext i32 %v to i64
154 %r = add i64 %lhs, %s
158 define i32 @add_s_i16i32(i16 %v, i32 %lhs) minsize {
159 ; CHECK-LABEL: add_s_i16i32:
161 ; CHECK-NEXT: add w0, w1, w0, sxth
163 %vz = sext i16 %v to i32
164 %r = add i32 %lhs, %vz
168 define i32 @add_s_shli16i32(i16 %v, i32 %lhs) minsize {
169 ; CHECK-LABEL: add_s_shli16i32:
171 ; CHECK-NEXT: add w0, w1, w0, sxth #3
173 %vz = sext i16 %v to i32
175 %r = add i32 %lhs, %s
179 define i64 @add_s_i16i64(i16 %v, i64 %lhs) minsize {
180 ; CHECK-LABEL: add_s_i16i64:
182 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
183 ; CHECK-NEXT: add x0, x1, w0, sxth
185 %vz = sext i16 %v to i64
186 %r = add i64 %lhs, %vz
190 define i64 @add_s_shli16i64(i16 %v, i64 %lhs) minsize {
191 ; CHECK-LABEL: add_s_shli16i64:
193 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
194 ; CHECK-NEXT: add x0, x1, w0, sxth #3
196 %vz = sext i16 %v to i64
198 %r = add i64 %lhs, %s
202 define i64 @add_s_i32i64(i32 %v, i64 %lhs) minsize {
203 ; CHECK-LABEL: add_s_i32i64:
205 ; CHECK-NEXT: add x0, x1, w0, sxtw
207 %vz = sext i32 %v to i64
208 %r = add i64 %lhs, %vz
212 define i64 @add_s_shli32i64(i32 %v, i64 %lhs) minsize {
213 ; CHECK-LABEL: add_s_shli32i64:
215 ; CHECK-NEXT: add x0, x1, w0, sxtw #3
217 %vz = sext i32 %v to i64
219 %r = add i64 %lhs, %s
223 define i32 @sub_z_i8i32(i8 %v, i32 %lhs) minsize {
224 ; CHECK-LABEL: sub_z_i8i32:
226 ; CHECK-NEXT: sub w0, w1, w0, uxtb
228 %vz = zext i8 %v to i32
229 %r = sub i32 %lhs, %vz
233 define i32 @sub_z_shli8i32(i8 %v, i32 %lhs) minsize {
234 ; CHECK-LABEL: sub_z_shli8i32:
236 ; CHECK-NEXT: sub w0, w1, w0, uxtb #3
238 %vz = zext i8 %v to i32
240 %r = sub i32 %lhs, %s
244 define i64 @sub_z_i8i64(i8 %v, i64 %lhs) minsize {
245 ; CHECK-LABEL: sub_z_i8i64:
247 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
248 ; CHECK-NEXT: sub x0, x1, w0, uxtb
250 %vz = zext i8 %v to i64
251 %r = sub i64 %lhs, %vz
255 define i64 @sub_z_shli8i64(i8 %v, i64 %lhs) minsize {
256 ; CHECK-LABEL: sub_z_shli8i64:
258 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
259 ; CHECK-NEXT: sub x0, x1, w0, uxtb #3
261 %vz = zext i8 %v to i64
263 %r = sub i64 %lhs, %s
267 define i32 @sub_s_i8i32(i8 %v, i32 %lhs) minsize {
268 ; CHECK-LABEL: sub_s_i8i32:
270 ; CHECK-NEXT: sub w0, w1, w0, sxtb
272 %vz = sext i8 %v to i32
273 %r = sub i32 %lhs, %vz
277 define i32 @sub_s_shli8i32(i8 %v, i32 %lhs) minsize {
278 ; CHECK-LABEL: sub_s_shli8i32:
280 ; CHECK-NEXT: sub w0, w1, w0, sxtb #3
282 %vz = sext i8 %v to i32
284 %r = sub i32 %lhs, %s
288 define i64 @sub_s_i8i64(i8 %v, i64 %lhs) minsize {
289 ; CHECK-LABEL: sub_s_i8i64:
291 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
292 ; CHECK-NEXT: sub x0, x1, w0, sxtb
294 %vz = sext i8 %v to i64
295 %r = sub i64 %lhs, %vz
299 define i64 @sub_s_shli8i64(i8 %v, i64 %lhs) minsize {
300 ; CHECK-LABEL: sub_s_shli8i64:
302 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
303 ; CHECK-NEXT: sub x0, x1, w0, sxtb #3
305 %vz = sext i8 %v to i64
307 %r = sub i64 %lhs, %s
311 define i32 @sub_z_i16i32(i16 %v, i32 %lhs) minsize {
312 ; CHECK-LABEL: sub_z_i16i32:
314 ; CHECK-NEXT: sub w0, w1, w0, uxth
316 %vz = zext i16 %v to i32
317 %r = sub i32 %lhs, %vz
321 define i32 @sub_z_shli16i32(i16 %v, i32 %lhs) minsize {
322 ; CHECK-LABEL: sub_z_shli16i32:
324 ; CHECK-NEXT: sub w0, w1, w0, uxth #3
326 %vz = zext i16 %v to i32
328 %r = sub i32 %lhs, %s
332 define i64 @sub_z_i16i64(i16 %v, i64 %lhs) minsize {
333 ; CHECK-LABEL: sub_z_i16i64:
335 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
336 ; CHECK-NEXT: sub x0, x1, w0, uxth
338 %vz = zext i16 %v to i64
339 %r = sub i64 %lhs, %vz
343 define i64 @sub_z_shli16i64(i16 %v, i64 %lhs) minsize {
344 ; CHECK-LABEL: sub_z_shli16i64:
346 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
347 ; CHECK-NEXT: sub x0, x1, w0, uxth #3
349 %vz = zext i16 %v to i64
351 %r = sub i64 %lhs, %s
355 define i64 @sub_z_i32i64(i32 %v, i64 %lhs) minsize {
356 ; CHECK-LABEL: sub_z_i32i64:
358 ; CHECK-NEXT: sub x0, x1, w0, uxtw
360 %vz = zext i32 %v to i64
361 %r = sub i64 %lhs, %vz
365 define i64 @sub_z_shli32i64(i32 %v, i64 %lhs) minsize {
366 ; CHECK-LABEL: sub_z_shli32i64:
368 ; CHECK-NEXT: sub x0, x1, w0, uxtw #3
370 %vz = zext i32 %v to i64
372 %r = sub i64 %lhs, %s
376 define i32 @sub_s_i16i32(i16 %v, i32 %lhs) minsize {
377 ; CHECK-LABEL: sub_s_i16i32:
379 ; CHECK-NEXT: sub w0, w1, w0, sxth
381 %vz = sext i16 %v to i32
382 %r = sub i32 %lhs, %vz
386 define i32 @sub_s_shli16i32(i16 %v, i32 %lhs) minsize {
387 ; CHECK-LABEL: sub_s_shli16i32:
389 ; CHECK-NEXT: sub w0, w1, w0, sxth #3
391 %vz = sext i16 %v to i32
393 %r = sub i32 %lhs, %s
397 define i64 @sub_s_i16i64(i16 %v, i64 %lhs) minsize {
398 ; CHECK-LABEL: sub_s_i16i64:
400 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
401 ; CHECK-NEXT: sub x0, x1, w0, sxth
403 %vz = sext i16 %v to i64
404 %r = sub i64 %lhs, %vz
408 define i64 @sub_s_shli16i64(i16 %v, i64 %lhs) minsize {
409 ; CHECK-LABEL: sub_s_shli16i64:
411 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
412 ; CHECK-NEXT: sub x0, x1, w0, sxth #3
414 %vz = sext i16 %v to i64
416 %r = sub i64 %lhs, %s
420 define i64 @sub_s_i32i64(i32 %v, i64 %lhs) minsize {
421 ; CHECK-LABEL: sub_s_i32i64:
423 ; CHECK-NEXT: sub x0, x1, w0, sxtw
425 %vz = sext i32 %v to i64
426 %r = sub i64 %lhs, %vz
430 define i64 @sub_s_shli32i64(i32 %v, i64 %lhs) minsize {
431 ; CHECK-LABEL: sub_s_shli32i64:
433 ; CHECK-NEXT: sub x0, x1, w0, sxtw #3
435 %vz = sext i32 %v to i64
437 %r = sub i64 %lhs, %s
441 define i32 @cmp_s_i8i32(i8 %v, i32 %lhs) minsize {
442 ; CHECK-LABEL: cmp_s_i8i32:
444 ; CHECK-NEXT: cmp w1, w0, uxtb
445 ; CHECK-NEXT: b.ge .LBB40_2
446 ; CHECK-NEXT: // %bb.1: // %then
447 ; CHECK-NEXT: mov w0, #1
449 ; CHECK-NEXT: .LBB40_2: // %end
450 ; CHECK-NEXT: mov w0, w1
452 %vz = zext i8 %v to i32
453 %c = icmp slt i32 %lhs, %vz
454 br i1 %c, label %then, label %end
461 define i64 @cmp_s_i8i64(i8 %v, i64 %lhs) minsize {
462 ; CHECK-LABEL: cmp_s_i8i64:
464 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
465 ; CHECK-NEXT: cmp x1, w0, sxtb
466 ; CHECK-NEXT: b.ge .LBB41_2
467 ; CHECK-NEXT: // %bb.1: // %then
468 ; CHECK-NEXT: mov w0, #1
470 ; CHECK-NEXT: .LBB41_2: // %end
471 ; CHECK-NEXT: mov x0, x1
473 %vz = sext i8 %v to i64
474 %c = icmp slt i64 %lhs, %vz
475 br i1 %c, label %then, label %end
482 define i32 @cmp_s_i16i32(i16 %v, i32 %lhs) minsize {
483 ; CHECK-LABEL: cmp_s_i16i32:
485 ; CHECK-NEXT: cmp w1, w0, uxth
486 ; CHECK-NEXT: b.ge .LBB42_2
487 ; CHECK-NEXT: // %bb.1: // %then
488 ; CHECK-NEXT: mov w0, #1
490 ; CHECK-NEXT: .LBB42_2: // %end
491 ; CHECK-NEXT: mov w0, w1
493 %vz = zext i16 %v to i32
494 %c = icmp slt i32 %lhs, %vz
495 br i1 %c, label %then, label %end
502 define i64 @cmp_s_i16i64(i16 %v, i64 %lhs) minsize {
503 ; CHECK-LABEL: cmp_s_i16i64:
505 ; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
506 ; CHECK-NEXT: cmp x1, w0, sxth
507 ; CHECK-NEXT: b.ge .LBB43_2
508 ; CHECK-NEXT: // %bb.1: // %then
509 ; CHECK-NEXT: mov w0, #1
511 ; CHECK-NEXT: .LBB43_2: // %end
512 ; CHECK-NEXT: mov x0, x1
514 %vz = sext i16 %v to i64
515 %c = icmp slt i64 %lhs, %vz
516 br i1 %c, label %then, label %end
524 ; Check that implicit zext from w reg write is used instead of uxtw form of add.
525 define dso_local i64 @add_fold_uxtw(i32 %x, i64 %y) {
526 ; CHECK-LABEL: add_fold_uxtw:
527 ; CHECK: // %bb.0: // %entry
528 ; CHECK-NEXT: and w8, w0, #0x3
529 ; CHECK-NEXT: add x0, x1, x8
533 %ext = zext i32 %m to i64
534 %ret = add i64 %y, %ext
538 ; Check that implicit zext from w reg write is used instead of uxtw
539 ; form of sub and that mov WZR is folded to form a neg instruction.
540 define dso_local i64 @sub_fold_uxtw_xzr(i32 %x) {
541 ; CHECK-LABEL: sub_fold_uxtw_xzr:
542 ; CHECK: // %bb.0: // %entry
543 ; CHECK-NEXT: and w8, w0, #0x3
544 ; CHECK-NEXT: neg x0, x8
548 %ext = zext i32 %m to i64
549 %ret = sub i64 0, %ext
553 ; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.
554 define dso_local i1 @cmp_fold_uxtw(i32 %x, i64 %y) {
555 ; CHECK-LABEL: cmp_fold_uxtw:
556 ; CHECK: // %bb.0: // %entry
557 ; CHECK-NEXT: and w8, w0, #0x3
558 ; CHECK-NEXT: cmp x1, x8
559 ; CHECK-NEXT: cset w0, eq
563 %ext = zext i32 %m to i64
564 %ret = icmp eq i64 %y, %ext
568 ; Check that implicit zext from w reg write is used instead of uxtw
569 ; form of add, leading to madd selection.
570 define dso_local i64 @madd_fold_uxtw(i32 %x, i64 %y) {
571 ; CHECK-LABEL: madd_fold_uxtw:
572 ; CHECK: // %bb.0: // %entry
573 ; CHECK-NEXT: and w8, w0, #0x3
574 ; CHECK-NEXT: madd x0, x1, x1, x8
578 %ext = zext i32 %m to i64
579 %mul = mul i64 %y, %y
580 %ret = add i64 %mul, %ext
584 ; Check that implicit zext from w reg write is used instead of uxtw
585 ; form of sub, leading to sub/cmp folding.
586 ; Check that implicit zext from w reg write is used instead of uxtw form of subs/cmp.
587 define dso_local i1 @cmp_sub_fold_uxtw(i32 %x, i64 %y, i64 %z) {
588 ; CHECK-LABEL: cmp_sub_fold_uxtw:
589 ; CHECK: // %bb.0: // %entry
590 ; CHECK-NEXT: and w8, w0, #0x3
591 ; CHECK-NEXT: cmp x2, x8
592 ; CHECK-NEXT: cset w0, eq
596 %ext = zext i32 %m to i64
597 %sub = sub i64 %z, %ext
598 %ret = icmp eq i64 %sub, 0
602 ; Check that implicit zext from w reg write is used instead of uxtw
603 ; form of add and add of -1 gets selected as sub.
604 define dso_local i64 @add_imm_fold_uxtw(i32 %x) {
605 ; CHECK-LABEL: add_imm_fold_uxtw:
606 ; CHECK: // %bb.0: // %entry
607 ; CHECK-NEXT: and w8, w0, #0x3
608 ; CHECK-NEXT: sub x0, x8, #1
612 %ext = zext i32 %m to i64
613 %ret = add i64 %ext, -1
617 ; Check that implicit zext from w reg write is used instead of uxtw
618 ; form of add and add lsl form gets selected.
619 define dso_local i64 @add_lsl_fold_uxtw(i32 %x, i64 %y) {
620 ; CHECK-LABEL: add_lsl_fold_uxtw:
621 ; CHECK: // %bb.0: // %entry
622 ; CHECK-NEXT: orr w8, w0, #0x3
623 ; CHECK-NEXT: add x0, x8, x1, lsl #3
627 %ext = zext i32 %m to i64
628 %shift = shl i64 %y, 3
629 %ret = add i64 %ext, %shift