xref: /llvm-project/llvm/test/CodeGen/AArch64/fast-isel-addressing-modes.ll (revision db158c7c830807caeeb0691739c41f1d522029e9)
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
4
5; Load / Store Base Register only
6define zeroext i1 @load_breg_i1(ptr %a) {
7; SDAG-LABEL: load_breg_i1:
8; SDAG:       ; %bb.0:
9; SDAG-NEXT:    ldrb w0, [x0]
10; SDAG-NEXT:    ret
11;
12; FAST-LABEL: load_breg_i1:
13; FAST:       ; %bb.0:
14; FAST-NEXT:    ldrb w8, [x0]
15; FAST-NEXT:    and w8, w8, #0x1
16; FAST-NEXT:    and w0, w8, #0x1
17; FAST-NEXT:    ret
18  %1 = load i1, ptr %a
19  ret i1 %1
20}
21
22define zeroext i8 @load_breg_i8(ptr %a) {
23; SDAG-LABEL: load_breg_i8:
24; SDAG:       ; %bb.0:
25; SDAG-NEXT:    ldrb w0, [x0]
26; SDAG-NEXT:    ret
27;
28; FAST-LABEL: load_breg_i8:
29; FAST:       ; %bb.0:
30; FAST-NEXT:    ldrb w8, [x0]
31; FAST-NEXT:    uxtb w0, w8
32; FAST-NEXT:    ret
33  %1 = load i8, ptr %a
34  ret i8 %1
35}
36
37define zeroext i16 @load_breg_i16(ptr %a) {
38; SDAG-LABEL: load_breg_i16:
39; SDAG:       ; %bb.0:
40; SDAG-NEXT:    ldrh w0, [x0]
41; SDAG-NEXT:    ret
42;
43; FAST-LABEL: load_breg_i16:
44; FAST:       ; %bb.0:
45; FAST-NEXT:    ldrh w8, [x0]
46; FAST-NEXT:    uxth w0, w8
47; FAST-NEXT:    ret
48  %1 = load i16, ptr %a
49  ret i16 %1
50}
51
52define i32 @load_breg_i32(ptr %a) {
53; CHECK-LABEL: load_breg_i32:
54; CHECK:       ; %bb.0:
55; CHECK-NEXT:    ldr w0, [x0]
56; CHECK-NEXT:    ret
57  %1 = load i32, ptr %a
58  ret i32 %1
59}
60
61define i64 @load_breg_i64(ptr %a) {
62; CHECK-LABEL: load_breg_i64:
63; CHECK:       ; %bb.0:
64; CHECK-NEXT:    ldr x0, [x0]
65; CHECK-NEXT:    ret
66  %1 = load i64, ptr %a
67  ret i64 %1
68}
69
70define float @load_breg_f32(ptr %a) {
71; CHECK-LABEL: load_breg_f32:
72; CHECK:       ; %bb.0:
73; CHECK-NEXT:    ldr s0, [x0]
74; CHECK-NEXT:    ret
75  %1 = load float, ptr %a
76  ret float %1
77}
78
79define double @load_breg_f64(ptr %a) {
80; CHECK-LABEL: load_breg_f64:
81; CHECK:       ; %bb.0:
82; CHECK-NEXT:    ldr d0, [x0]
83; CHECK-NEXT:    ret
84  %1 = load double, ptr %a
85  ret double %1
86}
87
88define void @store_breg_i1(ptr %a) {
89; CHECK-LABEL: store_breg_i1:
90; CHECK:       ; %bb.0:
91; CHECK-NEXT:    strb wzr, [x0]
92; CHECK-NEXT:    ret
93  store i1 0, ptr %a
94  ret void
95}
96
97define void @store_breg_i1_2(ptr %a) {
98; SDAG-LABEL: store_breg_i1_2:
99; SDAG:       ; %bb.0:
100; SDAG-NEXT:    mov w8, #1 ; =0x1
101; SDAG-NEXT:    strb w8, [x0]
102; SDAG-NEXT:    ret
103;
104; FAST-LABEL: store_breg_i1_2:
105; FAST:       ; %bb.0:
106; FAST-NEXT:    mov w8, #1 ; =0x1
107; FAST-NEXT:    and w8, w8, #0x1
108; FAST-NEXT:    strb w8, [x0]
109; FAST-NEXT:    ret
110  store i1 true, ptr %a
111  ret void
112}
113
114define void @store_breg_i8(ptr %a) {
115; CHECK-LABEL: store_breg_i8:
116; CHECK:       ; %bb.0:
117; CHECK-NEXT:    strb wzr, [x0]
118; CHECK-NEXT:    ret
119  store i8 0, ptr %a
120  ret void
121}
122
123define void @store_breg_i16(ptr %a) {
124; CHECK-LABEL: store_breg_i16:
125; CHECK:       ; %bb.0:
126; CHECK-NEXT:    strh wzr, [x0]
127; CHECK-NEXT:    ret
128  store i16 0, ptr %a
129  ret void
130}
131
132define void @store_breg_i32(ptr %a) {
133; CHECK-LABEL: store_breg_i32:
134; CHECK:       ; %bb.0:
135; CHECK-NEXT:    str wzr, [x0]
136; CHECK-NEXT:    ret
137  store i32 0, ptr %a
138  ret void
139}
140
141define void @store_breg_i64(ptr %a) {
142; CHECK-LABEL: store_breg_i64:
143; CHECK:       ; %bb.0:
144; CHECK-NEXT:    str xzr, [x0]
145; CHECK-NEXT:    ret
146  store i64 0, ptr %a
147  ret void
148}
149
150define void @store_breg_f32(ptr %a) {
151; CHECK-LABEL: store_breg_f32:
152; CHECK:       ; %bb.0:
153; CHECK-NEXT:    str wzr, [x0]
154; CHECK-NEXT:    ret
155  store float 0.0, ptr %a
156  ret void
157}
158
159define void @store_breg_f64(ptr %a) {
160; CHECK-LABEL: store_breg_f64:
161; CHECK:       ; %bb.0:
162; CHECK-NEXT:    str xzr, [x0]
163; CHECK-NEXT:    ret
164  store double 0.0, ptr %a
165  ret void
166}
167
168; Load Immediate
169define i32 @load_immoff_1() {
170; SDAG-LABEL: load_immoff_1:
171; SDAG:       ; %bb.0:
172; SDAG-NEXT:    mov w8, #128 ; =0x80
173; SDAG-NEXT:    ldr w0, [x8]
174; SDAG-NEXT:    ret
175;
176; FAST-LABEL: load_immoff_1:
177; FAST:       ; %bb.0:
178; FAST-NEXT:    mov x8, #128 ; =0x80
179; FAST-NEXT:    ldr w0, [x8]
180; FAST-NEXT:    ret
181  %1 = inttoptr i64 128 to ptr
182  %2 = load i32, ptr %1
183  ret i32 %2
184}
185
186; Load / Store Base Register + Immediate Offset
187; Max supported negative offset
188define i32 @load_breg_immoff_1(i64 %a) {
189; CHECK-LABEL: load_breg_immoff_1:
190; CHECK:       ; %bb.0:
191; CHECK-NEXT:    ldur w0, [x0, #-256]
192; CHECK-NEXT:    ret
193  %1 = add i64 %a, -256
194  %2 = inttoptr i64 %1 to ptr
195  %3 = load i32, ptr %2
196  ret i32 %3
197}
198
199; Min not-supported negative offset
200define i32 @load_breg_immoff_2(i64 %a) {
201; CHECK-LABEL: load_breg_immoff_2:
202; CHECK:       ; %bb.0:
203; CHECK-NEXT:    sub x8, x0, #257
204; CHECK-NEXT:    ldr w0, [x8]
205; CHECK-NEXT:    ret
206  %1 = add i64 %a, -257
207  %2 = inttoptr i64 %1 to ptr
208  %3 = load i32, ptr %2
209  ret i32 %3
210}
211
212; Max supported unscaled offset
213define i32 @load_breg_immoff_3(i64 %a) {
214; CHECK-LABEL: load_breg_immoff_3:
215; CHECK:       ; %bb.0:
216; CHECK-NEXT:    ldur w0, [x0, #255]
217; CHECK-NEXT:    ret
218  %1 = add i64 %a, 255
219  %2 = inttoptr i64 %1 to ptr
220  %3 = load i32, ptr %2
221  ret i32 %3
222}
223
224; Min un-supported unscaled offset
225define i32 @load_breg_immoff_4(i64 %a) {
226; CHECK-LABEL: load_breg_immoff_4:
227; CHECK:       ; %bb.0:
228; CHECK-NEXT:    add x8, x0, #257
229; CHECK-NEXT:    ldr w0, [x8]
230; CHECK-NEXT:    ret
231  %1 = add i64 %a, 257
232  %2 = inttoptr i64 %1 to ptr
233  %3 = load i32, ptr %2
234  ret i32 %3
235}
236
237; Max supported scaled offset
238define i32 @load_breg_immoff_5(i64 %a) {
239; CHECK-LABEL: load_breg_immoff_5:
240; CHECK:       ; %bb.0:
241; CHECK-NEXT:    ldr w0, [x0, #16380]
242; CHECK-NEXT:    ret
243  %1 = add i64 %a, 16380
244  %2 = inttoptr i64 %1 to ptr
245  %3 = load i32, ptr %2
246  ret i32 %3
247}
248
249; Min un-supported scaled offset
250define i32 @load_breg_immoff_6(i64 %a) {
251; SDAG-LABEL: load_breg_immoff_6:
252; SDAG:       ; %bb.0:
253; SDAG-NEXT:    mov w8, #16384 ; =0x4000
254; SDAG-NEXT:    ldr w0, [x0, x8]
255; SDAG-NEXT:    ret
256;
257; FAST-LABEL: load_breg_immoff_6:
258; FAST:       ; %bb.0:
259; FAST-NEXT:    add x8, x0, #4, lsl #12 ; =16384
260; FAST-NEXT:    ldr w0, [x8]
261; FAST-NEXT:    ret
262  %1 = add i64 %a, 16384
263  %2 = inttoptr i64 %1 to ptr
264  %3 = load i32, ptr %2
265  ret i32 %3
266}
267
268; Max supported negative offset
269define void @store_breg_immoff_1(i64 %a) {
270; CHECK-LABEL: store_breg_immoff_1:
271; CHECK:       ; %bb.0:
272; CHECK-NEXT:    stur wzr, [x0, #-256]
273; CHECK-NEXT:    ret
274  %1 = add i64 %a, -256
275  %2 = inttoptr i64 %1 to ptr
276  store i32 0, ptr %2
277  ret void
278}
279
280; Min not-supported negative offset
281define void @store_breg_immoff_2(i64 %a) {
282; CHECK-LABEL: store_breg_immoff_2:
283; CHECK:       ; %bb.0:
284; CHECK-NEXT:    sub x8, x0, #257
285; CHECK-NEXT:    str wzr, [x8]
286; CHECK-NEXT:    ret
287  %1 = add i64 %a, -257
288  %2 = inttoptr i64 %1 to ptr
289  store i32 0, ptr %2
290  ret void
291}
292
293; Max supported unscaled offset
294define void @store_breg_immoff_3(i64 %a) {
295; CHECK-LABEL: store_breg_immoff_3:
296; CHECK:       ; %bb.0:
297; CHECK-NEXT:    stur wzr, [x0, #255]
298; CHECK-NEXT:    ret
299  %1 = add i64 %a, 255
300  %2 = inttoptr i64 %1 to ptr
301  store i32 0, ptr %2
302  ret void
303}
304
305; Min un-supported unscaled offset
306define void @store_breg_immoff_4(i64 %a) {
307; CHECK-LABEL: store_breg_immoff_4:
308; CHECK:       ; %bb.0:
309; CHECK-NEXT:    add x8, x0, #257
310; CHECK-NEXT:    str wzr, [x8]
311; CHECK-NEXT:    ret
312  %1 = add i64 %a, 257
313  %2 = inttoptr i64 %1 to ptr
314  store i32 0, ptr %2
315  ret void
316}
317
318; Max supported scaled offset
319define void @store_breg_immoff_5(i64 %a) {
320; CHECK-LABEL: store_breg_immoff_5:
321; CHECK:       ; %bb.0:
322; CHECK-NEXT:    str wzr, [x0, #16380]
323; CHECK-NEXT:    ret
324  %1 = add i64 %a, 16380
325  %2 = inttoptr i64 %1 to ptr
326  store i32 0, ptr %2
327  ret void
328}
329
330; Min un-supported scaled offset
331define void @store_breg_immoff_6(i64 %a) {
332; SDAG-LABEL: store_breg_immoff_6:
333; SDAG:       ; %bb.0:
334; SDAG-NEXT:    mov w8, #16384 ; =0x4000
335; SDAG-NEXT:    str wzr, [x0, x8]
336; SDAG-NEXT:    ret
337;
338; FAST-LABEL: store_breg_immoff_6:
339; FAST:       ; %bb.0:
340; FAST-NEXT:    add x8, x0, #4, lsl #12 ; =16384
341; FAST-NEXT:    str wzr, [x8]
342; FAST-NEXT:    ret
343  %1 = add i64 %a, 16384
344  %2 = inttoptr i64 %1 to ptr
345  store i32 0, ptr %2
346  ret void
347}
348
349define i64 @load_breg_immoff_7(i64 %a) {
350; CHECK-LABEL: load_breg_immoff_7:
351; CHECK:       ; %bb.0:
352; CHECK-NEXT:    ldr x0, [x0, #48]
353; CHECK-NEXT:    ret
354  %1 = add i64 %a, 48
355  %2 = inttoptr i64 %1 to ptr
356  %3 = load i64, ptr %2
357  ret i64 %3
358}
359
360; Flip add operands
361define i64 @load_breg_immoff_8(i64 %a) {
362; CHECK-LABEL: load_breg_immoff_8:
363; CHECK:       ; %bb.0:
364; CHECK-NEXT:    ldr x0, [x0, #48]
365; CHECK-NEXT:    ret
366  %1 = add i64 48, %a
367  %2 = inttoptr i64 %1 to ptr
368  %3 = load i64, ptr %2
369  ret i64 %3
370}
371
372; Load Base Register + Register Offset
373define i64 @load_breg_offreg_1(i64 %a, i64 %b) {
374; CHECK-LABEL: load_breg_offreg_1:
375; CHECK:       ; %bb.0:
376; CHECK-NEXT:    ldr x0, [x0, x1]
377; CHECK-NEXT:    ret
378  %1 = add i64 %a, %b
379  %2 = inttoptr i64 %1 to ptr
380  %3 = load i64, ptr %2
381  ret i64 %3
382}
383
384; Flip add operands
385define i64 @load_breg_offreg_2(i64 %a, i64 %b) {
386; CHECK-LABEL: load_breg_offreg_2:
387; CHECK:       ; %bb.0:
388; CHECK-NEXT:    ldr x0, [x1, x0]
389; CHECK-NEXT:    ret
390  %1 = add i64 %b, %a
391  %2 = inttoptr i64 %1 to ptr
392  %3 = load i64, ptr %2
393  ret i64 %3
394}
395
396; Load Base Register + Register Offset + Immediate Offset
397define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) {
398; CHECK-LABEL: load_breg_offreg_immoff_1:
399; CHECK:       ; %bb.0:
400; CHECK-NEXT:    add x8, x0, x1
401; CHECK-NEXT:    ldr x0, [x8, #48]
402; CHECK-NEXT:    ret
403  %1 = add i64 %a, %b
404  %2 = add i64 %1, 48
405  %3 = inttoptr i64 %2 to ptr
406  %4 = load i64, ptr %3
407  ret i64 %4
408}
409
410define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) {
411; SDAG-LABEL: load_breg_offreg_immoff_2:
412; SDAG:       ; %bb.0:
413; SDAG-NEXT:    mov w8, #61440 ; =0xf000
414; SDAG-NEXT:    add x9, x0, x1
415; SDAG-NEXT:    ldr x0, [x9, x8]
416; SDAG-NEXT:    ret
417;
418; FAST-LABEL: load_breg_offreg_immoff_2:
419; FAST:       ; %bb.0:
420; FAST-NEXT:    add x8, x0, #15, lsl #12 ; =61440
421; FAST-NEXT:    ldr x0, [x8, x1]
422; FAST-NEXT:    ret
423  %1 = add i64 %a, %b
424  %2 = add i64 %1, 61440
425  %3 = inttoptr i64 %2 to ptr
426  %4 = load i64, ptr %3
427  ret i64 %4
428}
429
430; Load Scaled Register Offset
431define i32 @load_shift_offreg_1(i64 %a) {
432; CHECK-LABEL: load_shift_offreg_1:
433; CHECK:       ; %bb.0:
434; CHECK-NEXT:    lsl x8, x0, #2
435; CHECK-NEXT:    ldr w0, [x8]
436; CHECK-NEXT:    ret
437  %1 = shl i64 %a, 2
438  %2 = inttoptr i64 %1 to ptr
439  %3 = load i32, ptr %2
440  ret i32 %3
441}
442
443define i32 @load_mul_offreg_1(i64 %a) {
444; CHECK-LABEL: load_mul_offreg_1:
445; CHECK:       ; %bb.0:
446; CHECK-NEXT:    lsl x8, x0, #2
447; CHECK-NEXT:    ldr w0, [x8]
448; CHECK-NEXT:    ret
449  %1 = mul i64 %a, 4
450  %2 = inttoptr i64 %1 to ptr
451  %3 = load i32, ptr %2
452  ret i32 %3
453}
454
455; Load Base Register + Scaled Register Offset
456define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) {
457; CHECK-LABEL: load_breg_shift_offreg_1:
458; CHECK:       ; %bb.0:
459; CHECK-NEXT:    ldr w0, [x1, x0, lsl #2]
460; CHECK-NEXT:    ret
461  %1 = shl i64 %a, 2
462  %2 = add i64 %1, %b
463  %3 = inttoptr i64 %2 to ptr
464  %4 = load i32, ptr %3
465  ret i32 %4
466}
467
468define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) {
469; CHECK-LABEL: load_breg_shift_offreg_2:
470; CHECK:       ; %bb.0:
471; CHECK-NEXT:    ldr w0, [x1, x0, lsl #2]
472; CHECK-NEXT:    ret
473  %1 = shl i64 %a, 2
474  %2 = add i64 %b, %1
475  %3 = inttoptr i64 %2 to ptr
476  %4 = load i32, ptr %3
477  ret i32 %4
478}
479
480define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) {
481; SDAG-LABEL: load_breg_shift_offreg_3:
482; SDAG:       ; %bb.0:
483; SDAG-NEXT:    lsl x8, x0, #2
484; SDAG-NEXT:    ldr w0, [x8, x1, lsl #2]
485; SDAG-NEXT:    ret
486;
487; FAST-LABEL: load_breg_shift_offreg_3:
488; FAST:       ; %bb.0:
489; FAST-NEXT:    lsl x8, x1, #2
490; FAST-NEXT:    ldr w0, [x8, x0, lsl #2]
491; FAST-NEXT:    ret
492  %1 = shl i64 %a, 2
493  %2 = shl i64 %b, 2
494  %3 = add i64 %1, %2
495  %4 = inttoptr i64 %3 to ptr
496  %5 = load i32, ptr %4
497  ret i32 %5
498}
499
500define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) {
501; SDAG-LABEL: load_breg_shift_offreg_4:
502; SDAG:       ; %bb.0:
503; SDAG-NEXT:    lsl x8, x1, #2
504; SDAG-NEXT:    ldr w0, [x8, x0, lsl #2]
505; SDAG-NEXT:    ret
506;
507; FAST-LABEL: load_breg_shift_offreg_4:
508; FAST:       ; %bb.0:
509; FAST-NEXT:    lsl x8, x0, #2
510; FAST-NEXT:    ldr w0, [x8, x1, lsl #2]
511; FAST-NEXT:    ret
512  %1 = shl i64 %a, 2
513  %2 = shl i64 %b, 2
514  %3 = add i64 %2, %1
515  %4 = inttoptr i64 %3 to ptr
516  %5 = load i32, ptr %4
517  ret i32 %5
518}
519
520define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) {
521; CHECK-LABEL: load_breg_shift_offreg_5:
522; CHECK:       ; %bb.0:
523; CHECK-NEXT:    lsl x8, x1, #3
524; CHECK-NEXT:    ldr w0, [x8, x0, lsl #2]
525; CHECK-NEXT:    ret
526  %1 = shl i64 %a, 2
527  %2 = shl i64 %b, 3
528  %3 = add i64 %1, %2
529  %4 = inttoptr i64 %3 to ptr
530  %5 = load i32, ptr %4
531  ret i32 %5
532}
533
534define i32 @load_breg_mul_offreg_1(i64 %a, i64 %b) {
535; CHECK-LABEL: load_breg_mul_offreg_1:
536; CHECK:       ; %bb.0:
537; CHECK-NEXT:    ldr w0, [x1, x0, lsl #2]
538; CHECK-NEXT:    ret
539  %1 = mul i64 %a, 4
540  %2 = add i64 %1, %b
541  %3 = inttoptr i64 %2 to ptr
542  %4 = load i32, ptr %3
543  ret i32 %4
544}
545
546define zeroext i8 @load_breg_and_offreg_1(i64 %a, i64 %b) {
547; SDAG-LABEL: load_breg_and_offreg_1:
548; SDAG:       ; %bb.0:
549; SDAG-NEXT:    ldrb w0, [x1, w0, uxtw]
550; SDAG-NEXT:    ret
551;
552; FAST-LABEL: load_breg_and_offreg_1:
553; FAST:       ; %bb.0:
554; FAST-NEXT:    ldrb w8, [x1, w0, uxtw]
555; FAST-NEXT:    uxtb w0, w8
556; FAST-NEXT:    ret
557  %1 = and i64 %a, 4294967295
558  %2 = add i64 %1, %b
559  %3 = inttoptr i64 %2 to ptr
560  %4 = load i8, ptr %3
561  ret i8 %4
562}
563
564define zeroext i16 @load_breg_and_offreg_2(i64 %a, i64 %b) {
565; SDAG-LABEL: load_breg_and_offreg_2:
566; SDAG:       ; %bb.0:
567; SDAG-NEXT:    ldrh w0, [x1, w0, uxtw #1]
568; SDAG-NEXT:    ret
569;
570; FAST-LABEL: load_breg_and_offreg_2:
571; FAST:       ; %bb.0:
572; FAST-NEXT:    ldrh w8, [x1, w0, uxtw #1]
573; FAST-NEXT:    uxth w0, w8
574; FAST-NEXT:    ret
575  %1 = and i64 %a, 4294967295
576  %2 = shl i64 %1, 1
577  %3 = add i64 %2, %b
578  %4 = inttoptr i64 %3 to ptr
579  %5 = load i16, ptr %4
580  ret i16 %5
581}
582
583define i32 @load_breg_and_offreg_3(i64 %a, i64 %b) {
584; CHECK-LABEL: load_breg_and_offreg_3:
585; CHECK:       ; %bb.0:
586; CHECK-NEXT:    ldr w0, [x1, w0, uxtw #2]
587; CHECK-NEXT:    ret
588  %1 = and i64 %a, 4294967295
589  %2 = shl i64 %1, 2
590  %3 = add i64 %2, %b
591  %4 = inttoptr i64 %3 to ptr
592  %5 = load i32, ptr %4
593  ret i32 %5
594}
595
596define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) {
597; CHECK-LABEL: load_breg_and_offreg_4:
598; CHECK:       ; %bb.0:
599; CHECK-NEXT:    ldr x0, [x1, w0, uxtw #3]
600; CHECK-NEXT:    ret
601  %1 = and i64 %a, 4294967295
602  %2 = shl i64 %1, 3
603  %3 = add i64 %2, %b
604  %4 = inttoptr i64 %3 to ptr
605  %5 = load i64, ptr %4
606  ret i64 %5
607}
608
609; Not all 'and' instructions have immediates.
610define i64 @load_breg_and_offreg_5(i64 %a, i64 %b, i64 %c) {
611; CHECK-LABEL: load_breg_and_offreg_5:
612; CHECK:       ; %bb.0:
613; CHECK-NEXT:    and x8, x0, x2
614; CHECK-NEXT:    ldr x0, [x8, x1]
615; CHECK-NEXT:    ret
616  %1 = and i64 %a, %c
617  %2 = add i64 %1, %b
618  %3 = inttoptr i64 %2 to ptr
619  %4 = load i64, ptr %3
620  ret i64 %4
621}
622
623define i64 @load_breg_and_offreg_6(i64 %a, i64 %b, i64 %c) {
624; CHECK-LABEL: load_breg_and_offreg_6:
625; CHECK:       ; %bb.0:
626; CHECK-NEXT:    and x8, x0, x2
627; CHECK-NEXT:    ldr x0, [x1, x8, lsl #3]
628; CHECK-NEXT:    ret
629  %1 = and i64 %a, %c
630  %2 = shl i64 %1, 3
631  %3 = add i64 %2, %b
632  %4 = inttoptr i64 %3 to ptr
633  %5 = load i64, ptr %4
634  ret i64 %5
635}
636
637; Load Base Register + Scaled Register Offset + Sign/Zero extension
638define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) {
639; CHECK-LABEL: load_breg_zext_shift_offreg_1:
640; CHECK:       ; %bb.0:
641; CHECK-NEXT:    ldr w0, [x1, w0, uxtw #2]
642; CHECK-NEXT:    ret
643  %1 = zext i32 %a to i64
644  %2 = shl i64 %1, 2
645  %3 = add i64 %2, %b
646  %4 = inttoptr i64 %3 to ptr
647  %5 = load i32, ptr %4
648  ret i32 %5
649}
650
651define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) {
652; CHECK-LABEL: load_breg_zext_shift_offreg_2:
653; CHECK:       ; %bb.0:
654; CHECK-NEXT:    ldr w0, [x1, w0, uxtw #2]
655; CHECK-NEXT:    ret
656  %1 = zext i32 %a to i64
657  %2 = shl i64 %1, 2
658  %3 = add i64 %b, %2
659  %4 = inttoptr i64 %3 to ptr
660  %5 = load i32, ptr %4
661  ret i32 %5
662}
663
664define i32 @load_breg_zext_mul_offreg_1(i32 %a, i64 %b) {
665; CHECK-LABEL: load_breg_zext_mul_offreg_1:
666; CHECK:       ; %bb.0:
667; CHECK-NEXT:    ldr w0, [x1, w0, uxtw #2]
668; CHECK-NEXT:    ret
669  %1 = zext i32 %a to i64
670  %2 = mul i64 %1, 4
671  %3 = add i64 %2, %b
672  %4 = inttoptr i64 %3 to ptr
673  %5 = load i32, ptr %4
674  ret i32 %5
675}
676
677define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) {
678; CHECK-LABEL: load_breg_sext_shift_offreg_1:
679; CHECK:       ; %bb.0:
680; CHECK-NEXT:    ldr w0, [x1, w0, sxtw #2]
681; CHECK-NEXT:    ret
682  %1 = sext i32 %a to i64
683  %2 = shl i64 %1, 2
684  %3 = add i64 %2, %b
685  %4 = inttoptr i64 %3 to ptr
686  %5 = load i32, ptr %4
687  ret i32 %5
688}
689
690define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
691; CHECK-LABEL: load_breg_sext_shift_offreg_2:
692; CHECK:       ; %bb.0:
693; CHECK-NEXT:    ldr w0, [x1, w0, sxtw #2]
694; CHECK-NEXT:    ret
695  %1 = sext i32 %a to i64
696  %2 = shl i64 %1, 2
697  %3 = add i64 %b, %2
698  %4 = inttoptr i64 %3 to ptr
699  %5 = load i32, ptr %4
700  ret i32 %5
701}
702
703; Make sure that we don't drop the first 'add' instruction.
704define i32 @load_breg_sext_shift_offreg_3(i32 %a, i64 %b) {
705; CHECK-LABEL: load_breg_sext_shift_offreg_3:
706; CHECK:       ; %bb.0:
707; CHECK-NEXT:    add w8, w0, #4
708; CHECK-NEXT:    ldr w0, [x1, w8, sxtw #2]
709; CHECK-NEXT:    ret
710  %1 = add i32 %a, 4
711  %2 = sext i32 %1 to i64
712  %3 = shl i64 %2, 2
713  %4 = add i64 %b, %3
714  %5 = inttoptr i64 %4 to ptr
715  %6 = load i32, ptr %5
716  ret i32 %6
717}
718
719
720define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) {
721; CHECK-LABEL: load_breg_sext_mul_offreg_1:
722; CHECK:       ; %bb.0:
723; CHECK-NEXT:    ldr w0, [x1, w0, sxtw #2]
724; CHECK-NEXT:    ret
725  %1 = sext i32 %a to i64
726  %2 = mul i64 %1, 4
727  %3 = add i64 %2, %b
728  %4 = inttoptr i64 %3 to ptr
729  %5 = load i32, ptr %4
730  ret i32 %5
731}
732
733; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
734define i64 @load_sext_shift_offreg_imm1(i32 %a) {
735; CHECK-LABEL: load_sext_shift_offreg_imm1:
736; CHECK:       ; %bb.0:
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]
740; CHECK-NEXT:    ret
741  %1 = sext i32 %a to i64
742  %2 = shl i64 %1, 3
743  %3 = add i64 %2, 8
744  %4 = inttoptr i64 %3 to ptr
745  %5 = load i64, ptr %4
746  ret i64 %5
747}
748
749; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension
750define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) {
751; CHECK-LABEL: load_breg_sext_shift_offreg_imm1:
752; CHECK:       ; %bb.0:
753; CHECK-NEXT:    add x8, x1, w0, sxtw #3
754; CHECK-NEXT:    ldr x0, [x8, #8]
755; CHECK-NEXT:    ret
756  %1 = sext i32 %a to i64
757  %2 = shl i64 %1, 3
758  %3 = add i64 %b, %2
759  %4 = add i64 %3, 8
760  %5 = inttoptr i64 %4 to ptr
761  %6 = load i64, ptr %5
762  ret i64 %6
763}
764
765; Test that the kill flag is not set - the machine instruction verifier does that for us.
766define i64 @kill_reg(i64 %a) {
767; SDAG-LABEL: kill_reg:
768; SDAG:       ; %bb.0:
769; SDAG-NEXT:    ldr x8, [x0, #88]!
770; SDAG-NEXT:    add x0, x0, x8
771; SDAG-NEXT:    ret
772;
773; FAST-LABEL: kill_reg:
774; FAST:       ; %bb.0:
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
779; FAST-NEXT:    ret
780  %1 = sub i64 %a, 8
781  %2 = add i64 %1, 96
782  %3 = inttoptr i64 %2 to ptr
783  %4 = load i64, ptr %3
784  %5 = add i64 %2, %4
785  ret i64 %5
786}
787
788define void @store_fi(i64 %i) {
789; CHECK-LABEL: store_fi:
790; CHECK:       ; %bb.0:
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
797; CHECK-NEXT:    ret
798  %1 = alloca [8 x i32]
799  %2 = ptrtoint ptr %1 to i64
800  %3 = mul i64 %i, 4
801  %4 = add i64 %2, %3
802  %5 = inttoptr i64 %4 to ptr
803  store i32 47, ptr %5, align 4
804  ret void
805}
806
807define i32 @load_fi(i64 %i) {
808; CHECK-LABEL: load_fi:
809; CHECK:       ; %bb.0:
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
815; CHECK-NEXT:    ret
816  %1 = alloca [8 x i32]
817  %2 = ptrtoint ptr %1 to i64
818  %3 = mul i64 %i, 4
819  %4 = add i64 %2, %3
820  %5 = inttoptr i64 %4 to ptr
821  %6 = load i32, ptr %5, align 4
822  ret i32 %6
823}
824
825