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