1 ; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
2 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
4 ; Load / Store Base Register only
5 define zeroext i1 @load_breg_i1(i1* %a) {
6 ; CHECK-LABEL: load_breg_i1
7 ; CHECK: ldrb {{w[0-9]+}}, [x0]
12 define zeroext i8 @load_breg_i8(i8* %a) {
13 ; CHECK-LABEL: load_breg_i8
14 ; CHECK: ldrb {{w[0-9]+}}, [x0]
19 define zeroext i16 @load_breg_i16(i16* %a) {
20 ; CHECK-LABEL: load_breg_i16
21 ; CHECK: ldrh {{w[0-9]+}}, [x0]
26 define i32 @load_breg_i32(i32* %a) {
27 ; CHECK-LABEL: load_breg_i32
28 ; CHECK: ldr {{w[0-9]+}}, [x0]
33 define i64 @load_breg_i64(i64* %a) {
34 ; CHECK-LABEL: load_breg_i64
35 ; CHECK: ldr {{x[0-9]+}}, [x0]
40 define float @load_breg_f32(float* %a) {
41 ; CHECK-LABEL: load_breg_f32
42 ; CHECK: ldr {{s[0-9]+}}, [x0]
47 define double @load_breg_f64(double* %a) {
48 ; CHECK-LABEL: load_breg_f64
49 ; CHECK: ldr {{d[0-9]+}}, [x0]
54 define void @store_breg_i1(i1* %a) {
55 ; CHECK-LABEL: store_breg_i1
56 ; CHECK: strb wzr, [x0]
61 define void @store_breg_i1_2(i1* %a) {
62 ; CHECK-LABEL: store_breg_i1_2
63 ; CHECK: strb {{w[0-9]+}}, [x0]
68 define void @store_breg_i8(i8* %a) {
69 ; CHECK-LABEL: store_breg_i8
70 ; CHECK: strb wzr, [x0]
75 define void @store_breg_i16(i16* %a) {
76 ; CHECK-LABEL: store_breg_i16
77 ; CHECK: strh wzr, [x0]
82 define void @store_breg_i32(i32* %a) {
83 ; CHECK-LABEL: store_breg_i32
84 ; CHECK: str wzr, [x0]
89 define void @store_breg_i64(i64* %a) {
90 ; CHECK-LABEL: store_breg_i64
91 ; CHECK: str xzr, [x0]
96 define void @store_breg_f32(float* %a) {
97 ; CHECK-LABEL: store_breg_f32
98 ; CHECK: str wzr, [x0]
99 store float 0.0, float* %a
103 define void @store_breg_f64(double* %a) {
104 ; CHECK-LABEL: store_breg_f64
105 ; CHECK: str xzr, [x0]
106 store double 0.0, double* %a
111 define i32 @load_immoff_1() {
112 ; CHECK-LABEL: load_immoff_1
113 ; CHECK: orr {{w|x}}[[REG:[0-9]+]], {{wzr|xzr}}, #0x80
114 ; CHECK: ldr {{w[0-9]+}}, {{\[}}x[[REG]]{{\]}}
115 %1 = inttoptr i64 128 to i32*
120 ; Load / Store Base Register + Immediate Offset
121 ; Max supported negative offset
122 define i32 @load_breg_immoff_1(i64 %a) {
123 ; CHECK-LABEL: load_breg_immoff_1
124 ; CHECK: ldur {{w[0-9]+}}, [x0, #-256]
125 %1 = add i64 %a, -256
126 %2 = inttoptr i64 %1 to i32*
131 ; Min not-supported negative offset
132 define i32 @load_breg_immoff_2(i64 %a) {
133 ; SDAG-LABEL: load_breg_immoff_2
134 ; SDAG: sub [[REG:x[0-9]+]], x0, #257
135 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
136 ; FAST-LABEL: load_breg_immoff_2
137 ; FAST: add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
138 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
139 %1 = add i64 %a, -257
140 %2 = inttoptr i64 %1 to i32*
145 ; Max supported unscaled offset
146 define i32 @load_breg_immoff_3(i64 %a) {
147 ; CHECK-LABEL: load_breg_immoff_3
148 ; CHECK: ldur {{w[0-9]+}}, [x0, #255]
150 %2 = inttoptr i64 %1 to i32*
155 ; Min un-supported unscaled offset
156 define i32 @load_breg_immoff_4(i64 %a) {
157 ; CHECK-LABEL: load_breg_immoff_4
158 ; CHECK: add [[REG:x[0-9]+]], x0, #257
159 ; CHECK-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
161 %2 = inttoptr i64 %1 to i32*
166 ; Max supported scaled offset
167 define i32 @load_breg_immoff_5(i64 %a) {
168 ; CHECK-LABEL: load_breg_immoff_5
169 ; CHECK: ldr {{w[0-9]+}}, [x0, #16380]
170 %1 = add i64 %a, 16380
171 %2 = inttoptr i64 %1 to i32*
176 ; Min un-supported scaled offset
177 define i32 @load_breg_immoff_6(i64 %a) {
178 ; CHECK-LABEL: load_breg_immoff_6
179 ; CHECK: add [[REG:x[0-9]+]], x0, #4, lsl #12
180 ; CHECK-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
181 %1 = add i64 %a, 16384
182 %2 = inttoptr i64 %1 to i32*
187 ; Max supported negative offset
188 define void @store_breg_immoff_1(i64 %a) {
189 ; CHECK-LABEL: store_breg_immoff_1
190 ; CHECK: stur wzr, [x0, #-256]
191 %1 = add i64 %a, -256
192 %2 = inttoptr i64 %1 to i32*
197 ; Min not-supported negative offset
198 define void @store_breg_immoff_2(i64 %a) {
199 ; SDAG-LABEL: store_breg_immoff_2
200 ; SDAG: sub [[REG:x[0-9]+]], x0, #257
201 ; SDAG-NEXT: str wzr, {{\[}}[[REG]]{{\]}}
202 ; FAST-LABEL: store_breg_immoff_2
203 ; FAST: add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
204 ; FAST-NEXT: str wzr, {{\[}}[[REG]]{{\]}}
205 %1 = add i64 %a, -257
206 %2 = inttoptr i64 %1 to i32*
211 ; Max supported unscaled offset
212 define void @store_breg_immoff_3(i64 %a) {
213 ; CHECK-LABEL: store_breg_immoff_3
214 ; CHECK: stur wzr, [x0, #255]
216 %2 = inttoptr i64 %1 to i32*
221 ; Min un-supported unscaled offset
222 define void @store_breg_immoff_4(i64 %a) {
223 ; CHECK-LABEL: store_breg_immoff_4
224 ; CHECK: add [[REG:x[0-9]+]], x0, #257
225 ; CHECK-NEXT: str wzr, {{\[}}[[REG]]{{\]}}
227 %2 = inttoptr i64 %1 to i32*
232 ; Max supported scaled offset
233 define void @store_breg_immoff_5(i64 %a) {
234 ; CHECK-LABEL: store_breg_immoff_5
235 ; CHECK: str wzr, [x0, #16380]
236 %1 = add i64 %a, 16380
237 %2 = inttoptr i64 %1 to i32*
242 ; Min un-supported scaled offset
243 define void @store_breg_immoff_6(i64 %a) {
244 ; CHECK-LABEL: store_breg_immoff_6
245 ; CHECK: add [[REG:x[0-9]+]], x0, #4, lsl #12
246 ; CHECK-NEXT: str wzr, {{\[}}[[REG]]{{\]}}
247 %1 = add i64 %a, 16384
248 %2 = inttoptr i64 %1 to i32*
253 define i64 @load_breg_immoff_7(i64 %a) {
254 ; CHECK-LABEL: load_breg_immoff_7
255 ; CHECK: ldr {{x[0-9]+}}, [x0, #48]
257 %2 = inttoptr i64 %1 to i64*
263 define i64 @load_breg_immoff_8(i64 %a) {
264 ; CHECK-LABEL: load_breg_immoff_8
265 ; CHECK: ldr {{x[0-9]+}}, [x0, #48]
267 %2 = inttoptr i64 %1 to i64*
272 ; Load Base Register + Register Offset
273 define i64 @load_breg_offreg_1(i64 %a, i64 %b) {
274 ; CHECK-LABEL: load_breg_offreg_1
275 ; CHECK: ldr {{x[0-9]+}}, [x0, x1]
277 %2 = inttoptr i64 %1 to i64*
283 define i64 @load_breg_offreg_2(i64 %a, i64 %b) {
284 ; CHECK-LABEL: load_breg_offreg_2
285 ; CHECK: ldr {{x[0-9]+}}, [x1, x0]
287 %2 = inttoptr i64 %1 to i64*
292 ; Load Base Register + Register Offset + Immediate Offset
293 define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) {
294 ; CHECK-LABEL: load_breg_offreg_immoff_1
295 ; CHECK: add [[REG:x[0-9]+]], x0, x1
296 ; CHECK-NEXT: ldr x0, {{\[}}[[REG]], #48{{\]}}
299 %3 = inttoptr i64 %2 to i64*
304 define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) {
305 ; SDAG-LABEL: load_breg_offreg_immoff_2
306 ; SDAG: add [[REG1:x[0-9]+]], x0, x1
307 ; SDAG-NEXT: add [[REG2:x[0-9]+]], [[REG1]], #15, lsl #12
308 ; SDAG-NEXT: ldr x0, {{\[}}[[REG2]]{{\]}}
309 ; FAST-LABEL: load_breg_offreg_immoff_2
310 ; FAST: add [[REG:x[0-9]+]], x0, #15, lsl #12
311 ; FAST-NEXT: ldr x0, {{\[}}[[REG]], x1{{\]}}
313 %2 = add i64 %1, 61440
314 %3 = inttoptr i64 %2 to i64*
319 ; Load Scaled Register Offset
320 define i32 @load_shift_offreg_1(i64 %a) {
321 ; CHECK-LABEL: load_shift_offreg_1
322 ; CHECK: lsl [[REG:x[0-9]+]], x0, #2
323 ; CHECK: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
325 %2 = inttoptr i64 %1 to i32*
330 define i32 @load_mul_offreg_1(i64 %a) {
331 ; CHECK-LABEL: load_mul_offreg_1
332 ; CHECK: lsl [[REG:x[0-9]+]], x0, #2
333 ; CHECK: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
335 %2 = inttoptr i64 %1 to i32*
340 ; Load Base Register + Scaled Register Offset
341 define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) {
342 ; CHECK-LABEL: load_breg_shift_offreg_1
343 ; CHECK: ldr {{w[0-9]+}}, [x1, x0, lsl #2]
346 %3 = inttoptr i64 %2 to i32*
351 define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) {
352 ; CHECK-LABEL: load_breg_shift_offreg_2
353 ; CHECK: ldr {{w[0-9]+}}, [x1, x0, lsl #2]
356 %3 = inttoptr i64 %2 to i32*
361 define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) {
362 ; SDAG-LABEL: load_breg_shift_offreg_3
363 ; SDAG: lsl [[REG:x[0-9]+]], x0, #2
364 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x1, lsl #2{{\]}}
365 ; FAST-LABEL: load_breg_shift_offreg_3
366 ; FAST: lsl [[REG:x[0-9]+]], x1, #2
367 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
371 %4 = inttoptr i64 %3 to i32*
376 define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) {
377 ; SDAG-LABEL: load_breg_shift_offreg_4
378 ; SDAG: lsl [[REG:x[0-9]+]], x1, #2
379 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
380 ; FAST-LABEL: load_breg_shift_offreg_4
381 ; FAST: lsl [[REG:x[0-9]+]], x0, #2
382 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x1, lsl #2{{\]}}
386 %4 = inttoptr i64 %3 to i32*
391 define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) {
392 ; SDAG-LABEL: load_breg_shift_offreg_5
393 ; SDAG: lsl [[REG:x[0-9]+]], x1, #3
394 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
395 ; FAST-LABEL: load_breg_shift_offreg_5
396 ; FAST: lsl [[REG:x[0-9]+]], x1, #3
397 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
401 %4 = inttoptr i64 %3 to i32*
406 define i32 @load_breg_mul_offreg_1(i64 %a, i64 %b) {
407 ; CHECK-LABEL: load_breg_mul_offreg_1
408 ; CHECK: ldr {{w[0-9]+}}, [x1, x0, lsl #2]
411 %3 = inttoptr i64 %2 to i32*
416 define zeroext i8 @load_breg_and_offreg_1(i64 %a, i64 %b) {
417 ; CHECK-LABEL: load_breg_and_offreg_1
418 ; CHECK: ldrb {{w[0-9]+}}, [x1, w0, uxtw]
419 %1 = and i64 %a, 4294967295
421 %3 = inttoptr i64 %2 to i8*
426 define zeroext i16 @load_breg_and_offreg_2(i64 %a, i64 %b) {
427 ; CHECK-LABEL: load_breg_and_offreg_2
428 ; CHECK: ldrh {{w[0-9]+}}, [x1, w0, uxtw #1]
429 %1 = and i64 %a, 4294967295
432 %4 = inttoptr i64 %3 to i16*
437 define i32 @load_breg_and_offreg_3(i64 %a, i64 %b) {
438 ; CHECK-LABEL: load_breg_and_offreg_3
439 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2]
440 %1 = and i64 %a, 4294967295
443 %4 = inttoptr i64 %3 to i32*
448 define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) {
449 ; CHECK-LABEL: load_breg_and_offreg_4
450 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
451 %1 = and i64 %a, 4294967295
454 %4 = inttoptr i64 %3 to i64*
459 ; Load Base Register + Scaled Register Offset + Sign/Zero extension
460 define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) {
461 ; CHECK-LABEL: load_breg_zext_shift_offreg_1
462 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2]
463 %1 = zext i32 %a to i64
466 %4 = inttoptr i64 %3 to i32*
471 define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) {
472 ; CHECK-LABEL: load_breg_zext_shift_offreg_2
473 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2]
474 %1 = zext i32 %a to i64
477 %4 = inttoptr i64 %3 to i32*
482 define i32 @load_breg_zext_mul_offreg_1(i32 %a, i64 %b) {
483 ; CHECK-LABEL: load_breg_zext_mul_offreg_1
484 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2]
485 %1 = zext i32 %a to i64
488 %4 = inttoptr i64 %3 to i32*
493 define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) {
494 ; CHECK-LABEL: load_breg_sext_shift_offreg_1
495 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2]
496 %1 = sext i32 %a to i64
499 %4 = inttoptr i64 %3 to i32*
504 define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
505 ; CHECK-LABEL: load_breg_sext_shift_offreg_2
506 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2]
507 %1 = sext i32 %a to i64
510 %4 = inttoptr i64 %3 to i32*
515 define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) {
516 ; CHECK-LABEL: load_breg_sext_mul_offreg_1
517 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2]
518 %1 = sext i32 %a to i64
521 %4 = inttoptr i64 %3 to i32*
526 ; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
527 define i64 @load_sext_shift_offreg_imm1(i32 %a) {
528 ; CHECK-LABEL: load_sext_shift_offreg_imm1
529 ; CHECK: sbfiz [[REG:x[0-9]+]], {{x[0-9]+}}, #3, #32
530 ; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}}
531 %1 = sext i32 %a to i64
534 %4 = inttoptr i64 %3 to i64*
539 ; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension
540 define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) {
541 ; CHECK-LABEL: load_breg_sext_shift_offreg_imm1
542 ; CHECK: add [[REG:x[0-9]+]], x1, w0, sxtw #3
543 ; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}}
544 %1 = sext i32 %a to i64
548 %5 = inttoptr i64 %4 to i64*
553 ; Test that the kill flag is not set - the machine instruction verifier does that for us.
554 define i64 @kill_reg(i64 %a) {
557 %3 = inttoptr i64 %2 to i64*