222c9605f83e46a5bdc2fa7b58976fa246dc2cf2
[oota-llvm.git] / test / CodeGen / AArch64 / fast-isel-addressing-modes.ll
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
3
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]
8   %1 = load i1* %a
9   ret i1 %1
10 }
11
12 define zeroext i8 @load_breg_i8(i8* %a) {
13 ; CHECK-LABEL: load_breg_i8
14 ; CHECK:       ldrb {{w[0-9]+}}, [x0]
15   %1 = load i8* %a
16   ret i8 %1
17 }
18
19 define zeroext i16 @load_breg_i16(i16* %a) {
20 ; CHECK-LABEL: load_breg_i16
21 ; CHECK:       ldrh {{w[0-9]+}}, [x0]
22   %1 = load i16* %a
23   ret i16 %1
24 }
25
26 define i32 @load_breg_i32(i32* %a) {
27 ; CHECK-LABEL: load_breg_i32
28 ; CHECK:       ldr {{w[0-9]+}}, [x0]
29   %1 = load i32* %a
30   ret i32 %1
31 }
32
33 define i64 @load_breg_i64(i64* %a) {
34 ; CHECK-LABEL: load_breg_i64
35 ; CHECK:       ldr {{x[0-9]+}}, [x0]
36   %1 = load i64* %a
37   ret i64 %1
38 }
39
40 define float @load_breg_f32(float* %a) {
41 ; CHECK-LABEL: load_breg_f32
42 ; CHECK:       ldr {{s[0-9]+}}, [x0]
43   %1 = load float* %a
44   ret float %1
45 }
46
47 define double @load_breg_f64(double* %a) {
48 ; CHECK-LABEL: load_breg_f64
49 ; CHECK:       ldr {{d[0-9]+}}, [x0]
50   %1 = load double* %a
51   ret double %1
52 }
53
54 define void @store_breg_i1(i1* %a) {
55 ; CHECK-LABEL: store_breg_i1
56 ; CHECK:       strb {{wzr|w[0-9]+}}, [x0]
57   store i1 0, i1* %a
58   ret void
59 }
60
61 define void @store_breg_i8(i8* %a) {
62 ; CHECK-LABEL: store_breg_i8
63 ; CHECK:       strb wzr, [x0]
64   store i8 0, i8* %a
65   ret void
66 }
67
68 define void @store_breg_i16(i16* %a) {
69 ; CHECK-LABEL: store_breg_i16
70 ; CHECK:       strh wzr, [x0]
71   store i16 0, i16* %a
72   ret void
73 }
74
75 define void @store_breg_i32(i32* %a) {
76 ; CHECK-LABEL: store_breg_i32
77 ; CHECK:       str wzr, [x0]
78   store i32 0, i32* %a
79   ret void
80 }
81
82 define void @store_breg_i64(i64* %a) {
83 ; CHECK-LABEL: store_breg_i64
84 ; CHECK:       str xzr, [x0]
85   store i64 0, i64* %a
86   ret void
87 }
88
89 define void @store_breg_f32(float* %a) {
90 ; CHECK-LABEL: store_breg_f32
91 ; CHECK:       str {{wzr|s[0-9]+}}, [x0]
92   store float 0.0, float* %a
93   ret void
94 }
95
96 define void @store_breg_f64(double* %a) {
97 ; CHECK-LABEL: store_breg_f64
98 ; CHECK:       str {{xzr|d[0-9]+}}, [x0]
99   store double 0.0, double* %a
100   ret void
101 }
102
103 ; Load / Store Base Register + Immediate Offset
104 ; Max supported negative offset
105 define i32 @load_breg_immoff_1(i64 %a) {
106 ; CHECK-LABEL: load_breg_immoff_1
107 ; CHECK:       ldur {{w[0-9]+}}, [x0, #-256]
108   %1 = add i64 %a, -256
109   %2 = inttoptr i64 %1 to i32*
110   %3 = load i32* %2
111   ret i32 %3
112 }
113
114 ; Min not-supported negative offset
115 define i32 @load_breg_immoff_2(i64 %a) {
116 ; SDAG-LABEL: load_breg_immoff_2
117 ; SDAG:       sub [[REG:x[0-9]+]], x0, #257
118 ; SDAG-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
119 ; FAST-LABEL: load_breg_immoff_2
120 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
121 ; FAST-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
122   %1 = add i64 %a, -257
123   %2 = inttoptr i64 %1 to i32*
124   %3 = load i32* %2
125   ret i32 %3
126 }
127
128 ; Max supported unscaled offset
129 define i32 @load_breg_immoff_3(i64 %a) {
130 ; CHECK-LABEL: load_breg_immoff_3
131 ; CHECK:       ldur {{w[0-9]+}}, [x0, #255]
132   %1 = add i64 %a, 255
133   %2 = inttoptr i64 %1 to i32*
134   %3 = load i32* %2
135   ret i32 %3
136 }
137
138 ; Min un-supported unscaled offset
139 define i32 @load_breg_immoff_4(i64 %a) {
140 ; SDAG-LABEL: load_breg_immoff_4
141 ; SDAG:       add [[REG:x[0-9]+]], x0, #257
142 ; SDAG-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
143 ; FAST-LABEL: load_breg_immoff_4
144 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
145 ; FAST-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
146   %1 = add i64 %a, 257
147   %2 = inttoptr i64 %1 to i32*
148   %3 = load i32* %2
149   ret i32 %3
150 }
151
152 ; Max supported scaled offset
153 define i32 @load_breg_immoff_5(i64 %a) {
154 ; CHECK-LABEL: load_breg_immoff_5
155 ; CHECK:       ldr {{w[0-9]+}}, [x0, #16380]
156   %1 = add i64 %a, 16380
157   %2 = inttoptr i64 %1 to i32*
158   %3 = load i32* %2
159   ret i32 %3
160 }
161
162 ; Min un-supported scaled offset
163 define i32 @load_breg_immoff_6(i64 %a) {
164 ; SDAG-LABEL: load_breg_immoff_6
165 ; SDAG:       add [[REG:x[0-9]+]], x0, #4, lsl #12
166 ; SDAG-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
167 ; FAST-LABEL: load_breg_immoff_6
168 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
169 ; FAST-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}}
170   %1 = add i64 %a, 16384
171   %2 = inttoptr i64 %1 to i32*
172   %3 = load i32* %2
173   ret i32 %3
174 }
175
176 ; Max supported negative offset
177 define void @store_breg_immoff_1(i64 %a) {
178 ; CHECK-LABEL: store_breg_immoff_1
179 ; CHECK:       stur wzr, [x0, #-256]
180   %1 = add i64 %a, -256
181   %2 = inttoptr i64 %1 to i32*
182   store i32 0, i32* %2
183   ret void
184 }
185
186 ; Min not-supported negative offset
187 define void @store_breg_immoff_2(i64 %a) {
188 ; SDAG-LABEL: store_breg_immoff_2
189 ; SDAG:       sub [[REG:x[0-9]+]], x0, #257
190 ; SDAG-NEXT:  str wzr, {{\[}}[[REG]]{{\]}}
191 ; FAST-LABEL: store_breg_immoff_2
192 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
193 ; FAST-NEXT:  str wzr, {{\[}}[[REG]]{{\]}}
194   %1 = add i64 %a, -257
195   %2 = inttoptr i64 %1 to i32*
196   store i32 0, i32* %2
197   ret void
198 }
199
200 ; Max supported unscaled offset
201 define void @store_breg_immoff_3(i64 %a) {
202 ; CHECK-LABEL: store_breg_immoff_3
203 ; CHECK:       stur wzr, [x0, #255]
204   %1 = add i64 %a, 255
205   %2 = inttoptr i64 %1 to i32*
206   store i32 0, i32* %2
207   ret void
208 }
209
210 ; Min un-supported unscaled offset
211 define void @store_breg_immoff_4(i64 %a) {
212 ; SDAG-LABEL: store_breg_immoff_4
213 ; SDAG:       add [[REG:x[0-9]+]], x0, #257
214 ; SDAG-NEXT:  str wzr, {{\[}}[[REG]]{{\]}}
215 ; FAST-LABEL: store_breg_immoff_4
216 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
217 ; FAST-NEXT:  str wzr, {{\[}}[[REG]]{{\]}}
218   %1 = add i64 %a, 257
219   %2 = inttoptr i64 %1 to i32*
220   store i32 0, i32* %2
221   ret void
222 }
223
224 ; Max supported scaled offset
225 define void @store_breg_immoff_5(i64 %a) {
226 ; CHECK-LABEL: store_breg_immoff_5
227 ; CHECK:       str wzr, [x0, #16380]
228   %1 = add i64 %a, 16380
229   %2 = inttoptr i64 %1 to i32*
230   store i32 0, i32* %2
231   ret void
232 }
233
234 ; Min un-supported scaled offset
235 define void @store_breg_immoff_6(i64 %a) {
236 ; SDAG-LABEL: store_breg_immoff_6
237 ; SDAG:       add [[REG:x[0-9]+]], x0, #4, lsl #12
238 ; SDAG-NEXT:  str wzr, {{\[}}[[REG]]{{\]}}
239 ; FAST-LABEL: store_breg_immoff_6
240 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
241 ; FAST-NEXT:  str wzr, {{\[}}[[REG]]{{\]}}
242   %1 = add i64 %a, 16384
243   %2 = inttoptr i64 %1 to i32*
244   store i32 0, i32* %2
245   ret void
246 }
247
248 define i64 @load_breg_immoff_7(i64 %a) {
249 ; CHECK-LABEL: load_breg_immoff_7
250 ; CHECK:       ldr {{x[0-9]+}}, [x0, #48]
251   %1 = add i64 %a, 48
252   %2 = inttoptr i64 %1 to i64*
253   %3 = load i64* %2
254   ret i64 %3
255 }
256
257 ; Flip add operands
258 define i64 @load_breg_immoff_8(i64 %a) {
259 ; CHECK-LABEL: load_breg_immoff_8
260 ; CHECK:       ldr {{x[0-9]+}}, [x0, #48]
261   %1 = add i64 48, %a
262   %2 = inttoptr i64 %1 to i64*
263   %3 = load i64* %2
264   ret i64 %3
265 }
266
267 ; Load Base Register + Register Offset
268 define i64 @load_breg_offreg_1(i64 %a, i64 %b) {
269 ; CHECK-LABEL: load_breg_offreg_1
270 ; CHECK:       ldr {{x[0-9]+}}, [x0, x1]
271   %1 = add i64 %a, %b
272   %2 = inttoptr i64 %1 to i64*
273   %3 = load i64* %2
274   ret i64 %3
275 }
276
277 ; Flip add operands
278 define i64 @load_breg_offreg_2(i64 %a, i64 %b) {
279 ; CHECK-LABEL: load_breg_offreg_2
280 ; CHECK:       ldr {{x[0-9]+}}, [x1, x0]
281   %1 = add i64 %b, %a
282   %2 = inttoptr i64 %1 to i64*
283   %3 = load i64* %2
284   ret i64 %3
285 }
286
287 ; Load Base Register + Register Offset + Immediate Offset
288 define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) {
289 ; CHECK-LABEL: load_breg_offreg_immoff_1
290 ; CHECK:       add [[REG:x[0-9]+]], x0, x1
291 ; CHECK-NEXT:  ldr x0, {{\[}}[[REG]], #48{{\]}}
292   %1 = add i64 %a, %b
293   %2 = add i64 %1, 48
294   %3 = inttoptr i64 %2 to i64*
295   %4 = load i64* %3
296   ret i64 %4
297 }
298
299 define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) {
300 ; SDAG-LABEL: load_breg_offreg_immoff_2
301 ; SDAG:       add [[REG1:x[0-9]+]], x0, x1
302 ; SDAG-NEXT:  add [[REG2:x[0-9]+]], [[REG1]], #15, lsl #12
303 ; SDAG-NEXT:  ldr x0, {{\[}}[[REG2]]{{\]}}
304 ; FAST-LABEL: load_breg_offreg_immoff_2
305 ; FAST:       add [[REG:x[0-9]+]], x0, {{x[0-9]+}}
306 ; FAST-NEXT:  ldr x0, {{\[}}[[REG]], x1{{\]}}
307   %1 = add i64 %a, %b
308   %2 = add i64 %1, 61440
309   %3 = inttoptr i64 %2 to i64*
310   %4 = load i64* %3
311   ret i64 %4
312 }
313
314 ; Load Base Register + Scaled Register Offset
315 define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) {
316 ; CHECK-LABEL: load_breg_shift_offreg_1
317 ; CHECK:       ldr {{w[0-9]+}}, [x1, x0, lsl #2]
318   %1 = shl i64 %a, 2
319   %2 = add i64 %1, %b
320   %3 = inttoptr i64 %2 to i32*
321   %4 = load i32* %3
322   ret i32 %4
323 }
324
325 define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) {
326 ; CHECK-LABEL: load_breg_shift_offreg_2
327 ; CHECK:       ldr {{w[0-9]+}}, [x1, x0, lsl #2]
328   %1 = shl i64 %a, 2
329   %2 = add i64 %b, %1
330   %3 = inttoptr i64 %2 to i32*
331   %4 = load i32* %3
332   ret i32 %4
333 }
334
335 define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) {
336 ; SDAG-LABEL: load_breg_shift_offreg_3
337 ; SDAG:       lsl [[REG:x[0-9]+]], x0, #2
338 ; SDAG-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]], x1, lsl #2{{\]}}
339 ; FAST-LABEL: load_breg_shift_offreg_3
340 ; FAST:       lsl [[REG:x[0-9]+]], x1, {{x[0-9]+}}
341 ; FAST-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
342   %1 = shl i64 %a, 2
343   %2 = shl i64 %b, 2
344   %3 = add i64 %1, %2
345   %4 = inttoptr i64 %3 to i32*
346   %5 = load i32* %4
347   ret i32 %5
348 }
349
350 define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) {
351 ; SDAG-LABEL: load_breg_shift_offreg_4
352 ; SDAG:       lsl [[REG:x[0-9]+]], x1, #2
353 ; SDAG-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
354 ; FAST-LABEL: load_breg_shift_offreg_4
355 ; FAST:       lsl [[REG:x[0-9]+]], x0, {{x[0-9]+}}
356 ; FAST-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]], x1, lsl #2{{\]}}
357   %1 = shl i64 %a, 2
358   %2 = shl i64 %b, 2
359   %3 = add i64 %2, %1
360   %4 = inttoptr i64 %3 to i32*
361   %5 = load i32* %4
362   ret i32 %5
363 }
364
365 define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) {
366 ; SDAG-LABEL: load_breg_shift_offreg_5
367 ; SDAG:       lsl [[REG:x[0-9]+]], x1, #3
368 ; SDAG-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
369 ; FAST-LABEL: load_breg_shift_offreg_5
370 ; FAST:       lsl [[REG:x[0-9]+]], x1, {{x[0-9]+}}
371 ; FAST-NEXT:  ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}}
372   %1 = shl i64 %a, 2
373   %2 = shl i64 %b, 3
374   %3 = add i64 %1, %2
375   %4 = inttoptr i64 %3 to i32*
376   %5 = load i32* %4
377   ret i32 %5
378 }
379
380
381 ; Load Base Register + Scaled Register Offset + Sign/Zero extension
382 define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) {
383 ; CHECK-LABEL: load_breg_zext_shift_offreg_1
384 ; CHECK:       ldr {{w[0-9]+}}, [x1, w0, uxtw #2]
385   %1 = zext i32 %a to i64
386   %2 = shl i64 %1, 2
387   %3 = add i64 %2, %b
388   %4 = inttoptr i64 %3 to i32*
389   %5 = load i32* %4
390   ret i32 %5
391 }
392
393 define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) {
394 ; CHECK-LABEL: load_breg_zext_shift_offreg_2
395 ; CHECK:       ldr {{w[0-9]+}}, [x1, w0, uxtw #2]
396   %1 = zext i32 %a to i64
397   %2 = shl i64 %1, 2
398   %3 = add i64 %b, %2
399   %4 = inttoptr i64 %3 to i32*
400   %5 = load i32* %4
401   ret i32 %5
402 }
403
404 define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) {
405 ; CHECK-LABEL: load_breg_sext_shift_offreg_1
406 ; CHECK:       ldr {{w[0-9]+}}, [x1, w0, sxtw #2]
407   %1 = sext i32 %a to i64
408   %2 = shl i64 %1, 2
409   %3 = add i64 %2, %b
410   %4 = inttoptr i64 %3 to i32*
411   %5 = load i32* %4
412   ret i32 %5
413 }
414
415 define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
416 ; CHECK-LABEL: load_breg_sext_shift_offreg_2
417 ; CHECK:       ldr {{w[0-9]+}}, [x1, w0, sxtw #2]
418   %1 = sext i32 %a to i64
419   %2 = shl i64 %1, 2
420   %3 = add i64 %b, %2
421   %4 = inttoptr i64 %3 to i32*
422   %5 = load i32* %4
423   ret i32 %5
424 }
425
426 ; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
427 define i64 @load_sext_shift_offreg_imm1(i32 %a) {
428 ; CHECK-LABEL: load_sext_shift_offreg_imm1
429 ; CHECK:       sbfiz [[REG:x[0-9]+]], x0, #3, #32
430 ; CHECK-NEXT:  ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}}
431   %1 = sext i32 %a to i64
432   %2 = shl i64 %1, 3
433   %3 = add i64 %2, 8
434   %4 = inttoptr i64 %3 to i64*
435   %5 = load i64* %4
436   ret i64 %5
437 }
438
439 ; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension
440 define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) {
441 ; CHECK-LABEL: load_breg_sext_shift_offreg_imm1
442 ; CHECK:       add [[REG:x[0-9]+]], x1, w0, sxtw #3
443 ; CHECK-NEXT:  ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}}
444   %1 = sext i32 %a to i64
445   %2 = shl i64 %1, 3
446   %3 = add i64 %b, %2
447   %4 = add i64 %3, 8
448   %5 = inttoptr i64 %4 to i64*
449   %6 = load i64* %5
450   ret i64 %6
451 }
452