1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
3 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
5 ; Load / Store Base Register only
6 define zeroext i1 @load_breg_i1(ptr %a) {
7 ; SDAG-LABEL: load_breg_i1:
9 ; SDAG-NEXT: ldrb w0, [x0]
12 ; FAST-LABEL: load_breg_i1:
14 ; FAST-NEXT: ldrb w8, [x0]
15 ; FAST-NEXT: and w8, w8, #0x1
16 ; FAST-NEXT: and w0, w8, #0x1
22 define zeroext i8 @load_breg_i8(ptr %a) {
23 ; SDAG-LABEL: load_breg_i8:
25 ; SDAG-NEXT: ldrb w0, [x0]
28 ; FAST-LABEL: load_breg_i8:
30 ; FAST-NEXT: ldrb w8, [x0]
31 ; FAST-NEXT: uxtb w0, w8
37 define zeroext i16 @load_breg_i16(ptr %a) {
38 ; SDAG-LABEL: load_breg_i16:
40 ; SDAG-NEXT: ldrh w0, [x0]
43 ; FAST-LABEL: load_breg_i16:
45 ; FAST-NEXT: ldrh w8, [x0]
46 ; FAST-NEXT: uxth w0, w8
52 define i32 @load_breg_i32(ptr %a) {
53 ; CHECK-LABEL: load_breg_i32:
55 ; CHECK-NEXT: ldr w0, [x0]
61 define i64 @load_breg_i64(ptr %a) {
62 ; CHECK-LABEL: load_breg_i64:
64 ; CHECK-NEXT: ldr x0, [x0]
70 define float @load_breg_f32(ptr %a) {
71 ; CHECK-LABEL: load_breg_f32:
73 ; CHECK-NEXT: ldr s0, [x0]
75 %1 = load float, ptr %a
79 define double @load_breg_f64(ptr %a) {
80 ; CHECK-LABEL: load_breg_f64:
82 ; CHECK-NEXT: ldr d0, [x0]
84 %1 = load double, ptr %a
88 define void @store_breg_i1(ptr %a) {
89 ; CHECK-LABEL: store_breg_i1:
91 ; CHECK-NEXT: strb wzr, [x0]
97 define void @store_breg_i1_2(ptr %a) {
98 ; SDAG-LABEL: store_breg_i1_2:
100 ; SDAG-NEXT: mov w8, #1 ; =0x1
101 ; SDAG-NEXT: strb w8, [x0]
104 ; FAST-LABEL: store_breg_i1_2:
106 ; FAST-NEXT: mov w8, #1 ; =0x1
107 ; FAST-NEXT: and w8, w8, #0x1
108 ; FAST-NEXT: strb w8, [x0]
110 store i1 true, ptr %a
114 define void @store_breg_i8(ptr %a) {
115 ; CHECK-LABEL: store_breg_i8:
117 ; CHECK-NEXT: strb wzr, [x0]
123 define void @store_breg_i16(ptr %a) {
124 ; CHECK-LABEL: store_breg_i16:
126 ; CHECK-NEXT: strh wzr, [x0]
132 define void @store_breg_i32(ptr %a) {
133 ; CHECK-LABEL: store_breg_i32:
135 ; CHECK-NEXT: str wzr, [x0]
141 define void @store_breg_i64(ptr %a) {
142 ; CHECK-LABEL: store_breg_i64:
144 ; CHECK-NEXT: str xzr, [x0]
150 define void @store_breg_f32(ptr %a) {
151 ; CHECK-LABEL: store_breg_f32:
153 ; CHECK-NEXT: str wzr, [x0]
155 store float 0.0, ptr %a
159 define void @store_breg_f64(ptr %a) {
160 ; CHECK-LABEL: store_breg_f64:
162 ; CHECK-NEXT: str xzr, [x0]
164 store double 0.0, ptr %a
169 define i32 @load_immoff_1() {
170 ; SDAG-LABEL: load_immoff_1:
172 ; SDAG-NEXT: mov w8, #128 ; =0x80
173 ; SDAG-NEXT: ldr w0, [x8]
176 ; FAST-LABEL: load_immoff_1:
178 ; FAST-NEXT: mov x8, #128 ; =0x80
179 ; FAST-NEXT: ldr w0, [x8]
181 %1 = inttoptr i64 128 to ptr
182 %2 = load i32, ptr %1
186 ; Load / Store Base Register + Immediate Offset
187 ; Max supported negative offset
188 define i32 @load_breg_immoff_1(i64 %a) {
189 ; CHECK-LABEL: load_breg_immoff_1:
191 ; CHECK-NEXT: ldur w0, [x0, #-256]
193 %1 = add i64 %a, -256
194 %2 = inttoptr i64 %1 to ptr
195 %3 = load i32, ptr %2
199 ; Min not-supported negative offset
200 define i32 @load_breg_immoff_2(i64 %a) {
201 ; CHECK-LABEL: load_breg_immoff_2:
203 ; CHECK-NEXT: sub x8, x0, #257
204 ; CHECK-NEXT: ldr w0, [x8]
206 %1 = add i64 %a, -257
207 %2 = inttoptr i64 %1 to ptr
208 %3 = load i32, ptr %2
212 ; Max supported unscaled offset
213 define i32 @load_breg_immoff_3(i64 %a) {
214 ; CHECK-LABEL: load_breg_immoff_3:
216 ; CHECK-NEXT: ldur w0, [x0, #255]
219 %2 = inttoptr i64 %1 to ptr
220 %3 = load i32, ptr %2
224 ; Min un-supported unscaled offset
225 define i32 @load_breg_immoff_4(i64 %a) {
226 ; CHECK-LABEL: load_breg_immoff_4:
228 ; CHECK-NEXT: add x8, x0, #257
229 ; CHECK-NEXT: ldr w0, [x8]
232 %2 = inttoptr i64 %1 to ptr
233 %3 = load i32, ptr %2
237 ; Max supported scaled offset
238 define i32 @load_breg_immoff_5(i64 %a) {
239 ; CHECK-LABEL: load_breg_immoff_5:
241 ; CHECK-NEXT: ldr w0, [x0, #16380]
243 %1 = add i64 %a, 16380
244 %2 = inttoptr i64 %1 to ptr
245 %3 = load i32, ptr %2
249 ; Min un-supported scaled offset
250 define i32 @load_breg_immoff_6(i64 %a) {
251 ; SDAG-LABEL: load_breg_immoff_6:
253 ; SDAG-NEXT: mov w8, #16384 ; =0x4000
254 ; SDAG-NEXT: ldr w0, [x0, x8]
257 ; FAST-LABEL: load_breg_immoff_6:
259 ; FAST-NEXT: add x8, x0, #4, lsl #12 ; =16384
260 ; FAST-NEXT: ldr w0, [x8]
262 %1 = add i64 %a, 16384
263 %2 = inttoptr i64 %1 to ptr
264 %3 = load i32, ptr %2
268 ; Max supported negative offset
269 define void @store_breg_immoff_1(i64 %a) {
270 ; CHECK-LABEL: store_breg_immoff_1:
272 ; CHECK-NEXT: stur wzr, [x0, #-256]
274 %1 = add i64 %a, -256
275 %2 = inttoptr i64 %1 to ptr
280 ; Min not-supported negative offset
281 define void @store_breg_immoff_2(i64 %a) {
282 ; CHECK-LABEL: store_breg_immoff_2:
284 ; CHECK-NEXT: sub x8, x0, #257
285 ; CHECK-NEXT: str wzr, [x8]
287 %1 = add i64 %a, -257
288 %2 = inttoptr i64 %1 to ptr
293 ; Max supported unscaled offset
294 define void @store_breg_immoff_3(i64 %a) {
295 ; CHECK-LABEL: store_breg_immoff_3:
297 ; CHECK-NEXT: stur wzr, [x0, #255]
300 %2 = inttoptr i64 %1 to ptr
305 ; Min un-supported unscaled offset
306 define void @store_breg_immoff_4(i64 %a) {
307 ; CHECK-LABEL: store_breg_immoff_4:
309 ; CHECK-NEXT: add x8, x0, #257
310 ; CHECK-NEXT: str wzr, [x8]
313 %2 = inttoptr i64 %1 to ptr
318 ; Max supported scaled offset
319 define void @store_breg_immoff_5(i64 %a) {
320 ; CHECK-LABEL: store_breg_immoff_5:
322 ; CHECK-NEXT: str wzr, [x0, #16380]
324 %1 = add i64 %a, 16380
325 %2 = inttoptr i64 %1 to ptr
330 ; Min un-supported scaled offset
331 define void @store_breg_immoff_6(i64 %a) {
332 ; SDAG-LABEL: store_breg_immoff_6:
334 ; SDAG-NEXT: mov w8, #16384 ; =0x4000
335 ; SDAG-NEXT: str wzr, [x0, x8]
338 ; FAST-LABEL: store_breg_immoff_6:
340 ; FAST-NEXT: add x8, x0, #4, lsl #12 ; =16384
341 ; FAST-NEXT: str wzr, [x8]
343 %1 = add i64 %a, 16384
344 %2 = inttoptr i64 %1 to ptr
349 define i64 @load_breg_immoff_7(i64 %a) {
350 ; CHECK-LABEL: load_breg_immoff_7:
352 ; CHECK-NEXT: ldr x0, [x0, #48]
355 %2 = inttoptr i64 %1 to ptr
356 %3 = load i64, ptr %2
361 define i64 @load_breg_immoff_8(i64 %a) {
362 ; CHECK-LABEL: load_breg_immoff_8:
364 ; CHECK-NEXT: ldr x0, [x0, #48]
367 %2 = inttoptr i64 %1 to ptr
368 %3 = load i64, ptr %2
372 ; Load Base Register + Register Offset
373 define i64 @load_breg_offreg_1(i64 %a, i64 %b) {
374 ; CHECK-LABEL: load_breg_offreg_1:
376 ; CHECK-NEXT: ldr x0, [x0, x1]
379 %2 = inttoptr i64 %1 to ptr
380 %3 = load i64, ptr %2
385 define i64 @load_breg_offreg_2(i64 %a, i64 %b) {
386 ; CHECK-LABEL: load_breg_offreg_2:
388 ; CHECK-NEXT: ldr x0, [x1, x0]
391 %2 = inttoptr i64 %1 to ptr
392 %3 = load i64, ptr %2
396 ; Load Base Register + Register Offset + Immediate Offset
397 define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) {
398 ; CHECK-LABEL: load_breg_offreg_immoff_1:
400 ; CHECK-NEXT: add x8, x0, x1
401 ; CHECK-NEXT: ldr x0, [x8, #48]
405 %3 = inttoptr i64 %2 to ptr
406 %4 = load i64, ptr %3
410 define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) {
411 ; SDAG-LABEL: load_breg_offreg_immoff_2:
413 ; SDAG-NEXT: mov w8, #61440 ; =0xf000
414 ; SDAG-NEXT: add x9, x0, x1
415 ; SDAG-NEXT: ldr x0, [x9, x8]
418 ; FAST-LABEL: load_breg_offreg_immoff_2:
420 ; FAST-NEXT: add x8, x0, #15, lsl #12 ; =61440
421 ; FAST-NEXT: ldr x0, [x8, x1]
424 %2 = add i64 %1, 61440
425 %3 = inttoptr i64 %2 to ptr
426 %4 = load i64, ptr %3
430 ; Load Scaled Register Offset
431 define i32 @load_shift_offreg_1(i64 %a) {
432 ; CHECK-LABEL: load_shift_offreg_1:
434 ; CHECK-NEXT: lsl x8, x0, #2
435 ; CHECK-NEXT: ldr w0, [x8]
438 %2 = inttoptr i64 %1 to ptr
439 %3 = load i32, ptr %2
443 define i32 @load_mul_offreg_1(i64 %a) {
444 ; CHECK-LABEL: load_mul_offreg_1:
446 ; CHECK-NEXT: lsl x8, x0, #2
447 ; CHECK-NEXT: ldr w0, [x8]
450 %2 = inttoptr i64 %1 to ptr
451 %3 = load i32, ptr %2
455 ; Load Base Register + Scaled Register Offset
456 define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) {
457 ; CHECK-LABEL: load_breg_shift_offreg_1:
459 ; CHECK-NEXT: ldr w0, [x1, x0, lsl #2]
463 %3 = inttoptr i64 %2 to ptr
464 %4 = load i32, ptr %3
468 define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) {
469 ; CHECK-LABEL: load_breg_shift_offreg_2:
471 ; CHECK-NEXT: ldr w0, [x1, x0, lsl #2]
475 %3 = inttoptr i64 %2 to ptr
476 %4 = load i32, ptr %3
480 define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) {
481 ; SDAG-LABEL: load_breg_shift_offreg_3:
483 ; SDAG-NEXT: lsl x8, x0, #2
484 ; SDAG-NEXT: ldr w0, [x8, x1, lsl #2]
487 ; FAST-LABEL: load_breg_shift_offreg_3:
489 ; FAST-NEXT: lsl x8, x1, #2
490 ; FAST-NEXT: ldr w0, [x8, x0, lsl #2]
495 %4 = inttoptr i64 %3 to ptr
496 %5 = load i32, ptr %4
500 define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) {
501 ; SDAG-LABEL: load_breg_shift_offreg_4:
503 ; SDAG-NEXT: lsl x8, x1, #2
504 ; SDAG-NEXT: ldr w0, [x8, x0, lsl #2]
507 ; FAST-LABEL: load_breg_shift_offreg_4:
509 ; FAST-NEXT: lsl x8, x0, #2
510 ; FAST-NEXT: ldr w0, [x8, x1, lsl #2]
515 %4 = inttoptr i64 %3 to ptr
516 %5 = load i32, ptr %4
520 define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) {
521 ; CHECK-LABEL: load_breg_shift_offreg_5:
523 ; CHECK-NEXT: lsl x8, x1, #3
524 ; CHECK-NEXT: ldr w0, [x8, x0, lsl #2]
529 %4 = inttoptr i64 %3 to ptr
530 %5 = load i32, ptr %4
534 define i32 @load_breg_mul_offreg_1(i64 %a, i64 %b) {
535 ; CHECK-LABEL: load_breg_mul_offreg_1:
537 ; CHECK-NEXT: ldr w0, [x1, x0, lsl #2]
541 %3 = inttoptr i64 %2 to ptr
542 %4 = load i32, ptr %3
546 define zeroext i8 @load_breg_and_offreg_1(i64 %a, i64 %b) {
547 ; SDAG-LABEL: load_breg_and_offreg_1:
549 ; SDAG-NEXT: ldrb w0, [x1, w0, uxtw]
552 ; FAST-LABEL: load_breg_and_offreg_1:
554 ; FAST-NEXT: ldrb w8, [x1, w0, uxtw]
555 ; FAST-NEXT: uxtb w0, w8
557 %1 = and i64 %a, 4294967295
559 %3 = inttoptr i64 %2 to ptr
564 define zeroext i16 @load_breg_and_offreg_2(i64 %a, i64 %b) {
565 ; SDAG-LABEL: load_breg_and_offreg_2:
567 ; SDAG-NEXT: ldrh w0, [x1, w0, uxtw #1]
570 ; FAST-LABEL: load_breg_and_offreg_2:
572 ; FAST-NEXT: ldrh w8, [x1, w0, uxtw #1]
573 ; FAST-NEXT: uxth w0, w8
575 %1 = and i64 %a, 4294967295
578 %4 = inttoptr i64 %3 to ptr
579 %5 = load i16, ptr %4
583 define i32 @load_breg_and_offreg_3(i64 %a, i64 %b) {
584 ; CHECK-LABEL: load_breg_and_offreg_3:
586 ; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
588 %1 = and i64 %a, 4294967295
591 %4 = inttoptr i64 %3 to ptr
592 %5 = load i32, ptr %4
596 define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) {
597 ; CHECK-LABEL: load_breg_and_offreg_4:
599 ; CHECK-NEXT: ldr x0, [x1, w0, uxtw #3]
601 %1 = and i64 %a, 4294967295
604 %4 = inttoptr i64 %3 to ptr
605 %5 = load i64, ptr %4
609 ; Not all 'and' instructions have immediates.
610 define i64 @load_breg_and_offreg_5(i64 %a, i64 %b, i64 %c) {
611 ; CHECK-LABEL: load_breg_and_offreg_5:
613 ; CHECK-NEXT: and x8, x0, x2
614 ; CHECK-NEXT: ldr x0, [x8, x1]
618 %3 = inttoptr i64 %2 to ptr
619 %4 = load i64, ptr %3
623 define i64 @load_breg_and_offreg_6(i64 %a, i64 %b, i64 %c) {
624 ; CHECK-LABEL: load_breg_and_offreg_6:
626 ; CHECK-NEXT: and x8, x0, x2
627 ; CHECK-NEXT: ldr x0, [x1, x8, lsl #3]
632 %4 = inttoptr i64 %3 to ptr
633 %5 = load i64, ptr %4
637 ; Load Base Register + Scaled Register Offset + Sign/Zero extension
638 define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) {
639 ; CHECK-LABEL: load_breg_zext_shift_offreg_1:
641 ; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
643 %1 = zext i32 %a to i64
646 %4 = inttoptr i64 %3 to ptr
647 %5 = load i32, ptr %4
651 define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) {
652 ; CHECK-LABEL: load_breg_zext_shift_offreg_2:
654 ; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
656 %1 = zext i32 %a to i64
659 %4 = inttoptr i64 %3 to ptr
660 %5 = load i32, ptr %4
664 define i32 @load_breg_zext_mul_offreg_1(i32 %a, i64 %b) {
665 ; CHECK-LABEL: load_breg_zext_mul_offreg_1:
667 ; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
669 %1 = zext i32 %a to i64
672 %4 = inttoptr i64 %3 to ptr
673 %5 = load i32, ptr %4
677 define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) {
678 ; CHECK-LABEL: load_breg_sext_shift_offreg_1:
680 ; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2]
682 %1 = sext i32 %a to i64
685 %4 = inttoptr i64 %3 to ptr
686 %5 = load i32, ptr %4
690 define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
691 ; CHECK-LABEL: load_breg_sext_shift_offreg_2:
693 ; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2]
695 %1 = sext i32 %a to i64
698 %4 = inttoptr i64 %3 to ptr
699 %5 = load i32, ptr %4
703 ; Make sure that we don't drop the first 'add' instruction.
704 define i32 @load_breg_sext_shift_offreg_3(i32 %a, i64 %b) {
705 ; CHECK-LABEL: load_breg_sext_shift_offreg_3:
707 ; CHECK-NEXT: add w8, w0, #4
708 ; CHECK-NEXT: ldr w0, [x1, w8, sxtw #2]
711 %2 = sext i32 %1 to i64
714 %5 = inttoptr i64 %4 to ptr
715 %6 = load i32, ptr %5
720 define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) {
721 ; CHECK-LABEL: load_breg_sext_mul_offreg_1:
723 ; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2]
725 %1 = sext i32 %a to i64
728 %4 = inttoptr i64 %3 to ptr
729 %5 = load i32, ptr %4
733 ; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
734 define i64 @load_sext_shift_offreg_imm1(i32 %a) {
735 ; CHECK-LABEL: load_sext_shift_offreg_imm1:
737 ; CHECK-NEXT: ; kill: def $w0 killed $w0 def $x0
738 ; CHECK-NEXT: sbfiz x8, x0, #3, #32
739 ; CHECK-NEXT: ldr x0, [x8, #8]
741 %1 = sext i32 %a to i64
744 %4 = inttoptr i64 %3 to ptr
745 %5 = load i64, ptr %4
749 ; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension
750 define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) {
751 ; CHECK-LABEL: load_breg_sext_shift_offreg_imm1:
753 ; CHECK-NEXT: add x8, x1, w0, sxtw #3
754 ; CHECK-NEXT: ldr x0, [x8, #8]
756 %1 = sext i32 %a to i64
760 %5 = inttoptr i64 %4 to ptr
761 %6 = load i64, ptr %5
765 ; Test that the kill flag is not set - the machine instruction verifier does that for us.
766 define i64 @kill_reg(i64 %a) {
767 ; SDAG-LABEL: kill_reg:
769 ; SDAG-NEXT: ldr x8, [x0, #88]!
770 ; SDAG-NEXT: add x0, x0, x8
773 ; FAST-LABEL: kill_reg:
775 ; FAST-NEXT: sub x8, x0, #8
776 ; FAST-NEXT: ldr x9, [x0, #88]
777 ; FAST-NEXT: add x8, x8, #96
778 ; FAST-NEXT: add x0, x8, x9
782 %3 = inttoptr i64 %2 to ptr
783 %4 = load i64, ptr %3
788 define void @store_fi(i64 %i) {
789 ; CHECK-LABEL: store_fi:
791 ; CHECK-NEXT: sub sp, sp, #32
792 ; CHECK-NEXT: .cfi_def_cfa_offset 32
793 ; CHECK-NEXT: mov x8, sp
794 ; CHECK-NEXT: mov w9, #47 ; =0x2f
795 ; CHECK-NEXT: str w9, [x8, x0, lsl #2]
796 ; CHECK-NEXT: add sp, sp, #32
798 %1 = alloca [8 x i32]
799 %2 = ptrtoint ptr %1 to i64
802 %5 = inttoptr i64 %4 to ptr
803 store i32 47, ptr %5, align 4
807 define i32 @load_fi(i64 %i) {
808 ; CHECK-LABEL: load_fi:
810 ; CHECK-NEXT: sub sp, sp, #32
811 ; CHECK-NEXT: .cfi_def_cfa_offset 32
812 ; CHECK-NEXT: mov x8, sp
813 ; CHECK-NEXT: ldr w0, [x8, x0, lsl #2]
814 ; CHECK-NEXT: add sp, sp, #32
816 %1 = alloca [8 x i32]
817 %2 = ptrtoint ptr %1 to i64
820 %5 = inttoptr i64 %4 to ptr
821 %6 = load i32, ptr %5, align 4