1; RUN: llc < %s -mtriple=arm64-eabi -aarch64-redzone | FileCheck %s
2
3define i64* @store64(i64* %ptr, i64 %index, i64 %spacing) {
4; CHECK-LABEL: store64:
5; CHECK: str x{{[0-9+]}}, [x{{[0-9+]}}], #8
6; CHECK: ret
7  %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 1
8  store i64 %spacing, i64* %ptr, align 4
9  ret i64* %incdec.ptr
10}
11
12define i64* @store64idxpos256(i64* %ptr, i64 %index, i64 %spacing) {
13; CHECK-LABEL: store64idxpos256:
14; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256
15; CHECK: str x{{[0-9+]}}, [x{{[0-9+]}}]
16; CHECK: ret
17  %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 32
18  store i64 %spacing, i64* %ptr, align 4
19  ret i64* %incdec.ptr
20}
21
22define i64* @store64idxneg256(i64* %ptr, i64 %index, i64 %spacing) {
23; CHECK-LABEL: store64idxneg256:
24; CHECK: str x{{[0-9+]}}, [x{{[0-9+]}}], #-256
25; CHECK: ret
26  %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 -32
27  store i64 %spacing, i64* %ptr, align 4
28  ret i64* %incdec.ptr
29}
30
31define i32* @store32(i32* %ptr, i32 %index, i32 %spacing) {
32; CHECK-LABEL: store32:
33; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}], #4
34; CHECK: ret
35  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
36  store i32 %spacing, i32* %ptr, align 4
37  ret i32* %incdec.ptr
38}
39
40define i32* @store32idxpos256(i32* %ptr, i32 %index, i32 %spacing) {
41; CHECK-LABEL: store32idxpos256:
42; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256
43; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}]
44; CHECK: ret
45  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 64
46  store i32 %spacing, i32* %ptr, align 4
47  ret i32* %incdec.ptr
48}
49
50define i32* @store32idxneg256(i32* %ptr, i32 %index, i32 %spacing) {
51; CHECK-LABEL: store32idxneg256:
52; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}], #-256
53; CHECK: ret
54  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 -64
55  store i32 %spacing, i32* %ptr, align 4
56  ret i32* %incdec.ptr
57}
58
59define i16* @store16(i16* %ptr, i16 %index, i16 %spacing) {
60; CHECK-LABEL: store16:
61; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}], #2
62; CHECK: ret
63  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 1
64  store i16 %spacing, i16* %ptr, align 4
65  ret i16* %incdec.ptr
66}
67
68define i16* @store16idxpos256(i16* %ptr, i16 %index, i16 %spacing) {
69; CHECK-LABEL: store16idxpos256:
70; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256
71; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}]
72; CHECK: ret
73  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 128
74  store i16 %spacing, i16* %ptr, align 4
75  ret i16* %incdec.ptr
76}
77
78define i16* @store16idxneg256(i16* %ptr, i16 %index, i16 %spacing) {
79; CHECK-LABEL: store16idxneg256:
80; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}], #-256
81; CHECK: ret
82  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 -128
83  store i16 %spacing, i16* %ptr, align 4
84  ret i16* %incdec.ptr
85}
86
87define i8* @store8(i8* %ptr, i8 %index, i8 %spacing) {
88; CHECK-LABEL: store8:
89; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}], #1
90; CHECK: ret
91  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 1
92  store i8 %spacing, i8* %ptr, align 4
93  ret i8* %incdec.ptr
94}
95
96define i8* @store8idxpos256(i8* %ptr, i8 %index, i8 %spacing) {
97; CHECK-LABEL: store8idxpos256:
98; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256
99; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}]
100; CHECK: ret
101  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 256
102  store i8 %spacing, i8* %ptr, align 4
103  ret i8* %incdec.ptr
104}
105
106define i8* @store8idxneg256(i8* %ptr, i8 %index, i8 %spacing) {
107; CHECK-LABEL: store8idxneg256:
108; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}], #-256
109; CHECK: ret
110  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 -256
111  store i8 %spacing, i8* %ptr, align 4
112  ret i8* %incdec.ptr
113}
114
115define i32* @truncst64to32(i32* %ptr, i32 %index, i64 %spacing) {
116; CHECK-LABEL: truncst64to32:
117; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}], #4
118; CHECK: ret
119  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 1
120  %trunc = trunc i64 %spacing to i32
121  store i32 %trunc, i32* %ptr, align 4
122  ret i32* %incdec.ptr
123}
124
125define i16* @truncst64to16(i16* %ptr, i16 %index, i64 %spacing) {
126; CHECK-LABEL: truncst64to16:
127; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}], #2
128; CHECK: ret
129  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 1
130  %trunc = trunc i64 %spacing to i16
131  store i16 %trunc, i16* %ptr, align 4
132  ret i16* %incdec.ptr
133}
134
135define i8* @truncst64to8(i8* %ptr, i8 %index, i64 %spacing) {
136; CHECK-LABEL: truncst64to8:
137; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}], #1
138; CHECK: ret
139  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 1
140  %trunc = trunc i64 %spacing to i8
141  store i8 %trunc, i8* %ptr, align 4
142  ret i8* %incdec.ptr
143}
144
145
146define half* @storef16(half* %ptr, half %index, half %spacing) nounwind {
147; CHECK-LABEL: storef16:
148; CHECK: str h{{[0-9+]}}, [x{{[0-9+]}}], #2
149; CHECK: ret
150  %incdec.ptr = getelementptr inbounds half, half* %ptr, i64 1
151  store half %spacing, half* %ptr, align 2
152  ret half* %incdec.ptr
153}
154
155define float* @storef32(float* %ptr, float %index, float %spacing) {
156; CHECK-LABEL: storef32:
157; CHECK: str s{{[0-9+]}}, [x{{[0-9+]}}], #4
158; CHECK: ret
159  %incdec.ptr = getelementptr inbounds float, float* %ptr, i64 1
160  store float %spacing, float* %ptr, align 4
161  ret float* %incdec.ptr
162}
163
164define double* @storef64(double* %ptr, double %index, double %spacing) {
165; CHECK-LABEL: storef64:
166; CHECK: str d{{[0-9+]}}, [x{{[0-9+]}}], #8
167; CHECK: ret
168  %incdec.ptr = getelementptr inbounds double, double* %ptr, i64 1
169  store double %spacing, double* %ptr, align 4
170  ret double* %incdec.ptr
171}
172
173
174define double* @pref64(double* %ptr, double %spacing) {
175; CHECK-LABEL: pref64:
176; CHECK:      str d0, [x0, #32]!
177; CHECK-NEXT: ret
178  %incdec.ptr = getelementptr inbounds double, double* %ptr, i64 4
179  store double %spacing, double* %incdec.ptr, align 4
180  ret double *%incdec.ptr
181}
182
183define float* @pref32(float* %ptr, float %spacing) {
184; CHECK-LABEL: pref32:
185; CHECK:      str s0, [x0, #12]!
186; CHECK-NEXT: ret
187  %incdec.ptr = getelementptr inbounds float, float* %ptr, i64 3
188  store float %spacing, float* %incdec.ptr, align 4
189  ret float *%incdec.ptr
190}
191
192define half* @pref16(half* %ptr, half %spacing) nounwind {
193; CHECK-LABEL: pref16:
194; CHECK:      str h0, [x0, #6]!
195; CHECK-NEXT: ret
196  %incdec.ptr = getelementptr inbounds half, half* %ptr, i64 3
197  store half %spacing, half* %incdec.ptr, align 2
198  ret half *%incdec.ptr
199}
200
201define i64* @pre64(i64* %ptr, i64 %spacing) {
202; CHECK-LABEL: pre64:
203; CHECK:      str x1, [x0, #16]!
204; CHECK-NEXT: ret
205  %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 2
206  store i64 %spacing, i64* %incdec.ptr, align 4
207  ret i64 *%incdec.ptr
208}
209
210define i64* @pre64idxpos256(i64* %ptr, i64 %spacing) {
211; CHECK-LABEL: pre64idxpos256:
212; CHECK:      add x8, x0, #256
213; CHECK-NEXT: str x1, [x0, #256]
214; CHECK-NEXT: mov x0, x8
215; CHECK-NEXT: ret
216  %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 32
217  store i64 %spacing, i64* %incdec.ptr, align 4
218  ret i64 *%incdec.ptr
219}
220
221define i64* @pre64idxneg256(i64* %ptr, i64 %spacing) {
222; CHECK-LABEL: pre64idxneg256:
223; CHECK:      str x1, [x0, #-256]!
224; CHECK-NEXT: ret
225  %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 -32
226  store i64 %spacing, i64* %incdec.ptr, align 4
227  ret i64 *%incdec.ptr
228}
229
230define i32* @pre32(i32* %ptr, i32 %spacing) {
231; CHECK-LABEL: pre32:
232; CHECK:      str w1, [x0, #8]!
233; CHECK-NEXT: ret
234  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 2
235  store i32 %spacing, i32* %incdec.ptr, align 4
236  ret i32 *%incdec.ptr
237}
238
239define i32* @pre32idxpos256(i32* %ptr, i32 %spacing) {
240; CHECK-LABEL: pre32idxpos256:
241; CHECK:      add x8, x0, #256
242; CHECK-NEXT: str w1, [x0, #256]
243; CHECK-NEXT: mov x0, x8
244; CHECK-NEXT: ret
245  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 64
246  store i32 %spacing, i32* %incdec.ptr, align 4
247  ret i32 *%incdec.ptr
248}
249
250define i32* @pre32idxneg256(i32* %ptr, i32 %spacing) {
251; CHECK-LABEL: pre32idxneg256:
252; CHECK:      str w1, [x0, #-256]!
253; CHECK-NEXT: ret
254  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 -64
255  store i32 %spacing, i32* %incdec.ptr, align 4
256  ret i32 *%incdec.ptr
257}
258
259define i16* @pre16(i16* %ptr, i16 %spacing) {
260; CHECK-LABEL: pre16:
261; CHECK:      strh w1, [x0, #4]!
262; CHECK-NEXT: ret
263  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 2
264  store i16 %spacing, i16* %incdec.ptr, align 4
265  ret i16 *%incdec.ptr
266}
267
268define i16* @pre16idxpos256(i16* %ptr, i16 %spacing) {
269; CHECK-LABEL: pre16idxpos256:
270; CHECK:      add x8, x0, #256
271; CHECK-NEXT: strh w1, [x0, #256]
272; CHECK-NEXT: mov x0, x8
273; CHECK-NEXT: ret
274  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 128
275  store i16 %spacing, i16* %incdec.ptr, align 4
276  ret i16 *%incdec.ptr
277}
278
279define i16* @pre16idxneg256(i16* %ptr, i16 %spacing) {
280; CHECK-LABEL: pre16idxneg256:
281; CHECK:      strh w1, [x0, #-256]!
282; CHECK-NEXT: ret
283  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 -128
284  store i16 %spacing, i16* %incdec.ptr, align 4
285  ret i16 *%incdec.ptr
286}
287
288define i8* @pre8(i8* %ptr, i8 %spacing) {
289; CHECK-LABEL: pre8:
290; CHECK:      strb w1, [x0, #2]!
291; CHECK-NEXT: ret
292  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 2
293  store i8 %spacing, i8* %incdec.ptr, align 4
294  ret i8 *%incdec.ptr
295}
296
297define i8* @pre8idxpos256(i8* %ptr, i8 %spacing) {
298; CHECK-LABEL: pre8idxpos256:
299; CHECK:      add x8, x0, #256
300; CHECK-NEXT: strb w1, [x0, #256]
301; CHECK-NEXT: mov x0, x8
302; CHECK-NEXT: ret
303  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 256
304  store i8 %spacing, i8* %incdec.ptr, align 4
305  ret i8 *%incdec.ptr
306}
307
308define i8* @pre8idxneg256(i8* %ptr, i8 %spacing) {
309; CHECK-LABEL: pre8idxneg256:
310; CHECK:      strb w1, [x0, #-256]!
311; CHECK-NEXT: ret
312  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 -256
313  store i8 %spacing, i8* %incdec.ptr, align 4
314  ret i8 *%incdec.ptr
315}
316
317define i32* @pretrunc64to32(i32* %ptr, i64 %spacing) {
318; CHECK-LABEL: pretrunc64to32:
319; CHECK:      str w1, [x0, #8]!
320; CHECK-NEXT: ret
321  %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 2
322  %trunc = trunc i64 %spacing to i32
323  store i32 %trunc, i32* %incdec.ptr, align 4
324  ret i32 *%incdec.ptr
325}
326
327define i16* @pretrunc64to16(i16* %ptr, i64 %spacing) {
328; CHECK-LABEL: pretrunc64to16:
329; CHECK:      strh w1, [x0, #4]!
330; CHECK-NEXT: ret
331  %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 2
332  %trunc = trunc i64 %spacing to i16
333  store i16 %trunc, i16* %incdec.ptr, align 4
334  ret i16 *%incdec.ptr
335}
336
337define i8* @pretrunc64to8(i8* %ptr, i64 %spacing) {
338; CHECK-LABEL: pretrunc64to8:
339; CHECK:      strb w1, [x0, #2]!
340; CHECK-NEXT: ret
341  %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 2
342  %trunc = trunc i64 %spacing to i8
343  store i8 %trunc, i8* %incdec.ptr, align 4
344  ret i8 *%incdec.ptr
345}
346
347;-----
348; Pre-indexed loads
349;-----
350define double* @preidxf64(double* %src, double* %out) {
351; CHECK-LABEL: preidxf64:
352; CHECK: ldr     d0, [x0, #8]!
353; CHECK: str     d0, [x1]
354; CHECK: ret
355  %ptr = getelementptr inbounds double, double* %src, i64 1
356  %tmp = load double, double* %ptr, align 4
357  store double %tmp, double* %out, align 4
358  ret double* %ptr
359}
360
361define float* @preidxf32(float* %src, float* %out) {
362; CHECK-LABEL: preidxf32:
363; CHECK: ldr     s0, [x0, #4]!
364; CHECK: str     s0, [x1]
365; CHECK: ret
366  %ptr = getelementptr inbounds float, float* %src, i64 1
367  %tmp = load float, float* %ptr, align 4
368  store float %tmp, float* %out, align 4
369  ret float* %ptr
370}
371
372define half* @preidxf16(half* %src, half* %out) {
373; CHECK-LABEL: preidxf16:
374; CHECK: ldr     h0, [x0, #2]!
375; CHECK: str     h0, [x1]
376; CHECK: ret
377  %ptr = getelementptr inbounds half, half* %src, i64 1
378  %tmp = load half, half* %ptr, align 2
379  store half %tmp, half* %out, align 2
380  ret half* %ptr
381}
382
383define i64* @preidx64(i64* %src, i64* %out) {
384; CHECK-LABEL: preidx64:
385; CHECK: ldr     x[[REG:[0-9]+]], [x0, #8]!
386; CHECK: str     x[[REG]], [x1]
387; CHECK: ret
388  %ptr = getelementptr inbounds i64, i64* %src, i64 1
389  %tmp = load i64, i64* %ptr, align 4
390  store i64 %tmp, i64* %out, align 4
391  ret i64* %ptr
392}
393
394define i32* @preidx32(i32* %src, i32* %out) {
395; CHECK: ldr     w[[REG:[0-9]+]], [x0, #4]!
396; CHECK: str     w[[REG]], [x1]
397; CHECK: ret
398  %ptr = getelementptr inbounds i32, i32* %src, i64 1
399  %tmp = load i32, i32* %ptr, align 4
400  store i32 %tmp, i32* %out, align 4
401  ret i32* %ptr
402}
403
404define i16* @preidx16zext32(i16* %src, i32* %out) {
405; CHECK: ldrh    w[[REG:[0-9]+]], [x0, #2]!
406; CHECK: str     w[[REG]], [x1]
407; CHECK: ret
408  %ptr = getelementptr inbounds i16, i16* %src, i64 1
409  %tmp = load i16, i16* %ptr, align 4
410  %ext = zext i16 %tmp to i32
411  store i32 %ext, i32* %out, align 4
412  ret i16* %ptr
413}
414
415define i16* @preidx16zext64(i16* %src, i64* %out) {
416; CHECK: ldrh    w[[REG:[0-9]+]], [x0, #2]!
417; CHECK: str     x[[REG]], [x1]
418; CHECK: ret
419  %ptr = getelementptr inbounds i16, i16* %src, i64 1
420  %tmp = load i16, i16* %ptr, align 4
421  %ext = zext i16 %tmp to i64
422  store i64 %ext, i64* %out, align 4
423  ret i16* %ptr
424}
425
426define i8* @preidx8zext32(i8* %src, i32* %out) {
427; CHECK: ldrb    w[[REG:[0-9]+]], [x0, #1]!
428; CHECK: str     w[[REG]], [x1]
429; CHECK: ret
430  %ptr = getelementptr inbounds i8, i8* %src, i64 1
431  %tmp = load i8, i8* %ptr, align 4
432  %ext = zext i8 %tmp to i32
433  store i32 %ext, i32* %out, align 4
434  ret i8* %ptr
435}
436
437define i8* @preidx8zext64(i8* %src, i64* %out) {
438; CHECK: ldrb    w[[REG:[0-9]+]], [x0, #1]!
439; CHECK: str     x[[REG]], [x1]
440; CHECK: ret
441  %ptr = getelementptr inbounds i8, i8* %src, i64 1
442  %tmp = load i8, i8* %ptr, align 4
443  %ext = zext i8 %tmp to i64
444  store i64 %ext, i64* %out, align 4
445  ret i8* %ptr
446}
447
448define i32* @preidx32sext64(i32* %src, i64* %out) {
449; CHECK: ldrsw   x[[REG:[0-9]+]], [x0, #4]!
450; CHECK: str     x[[REG]], [x1]
451; CHECK: ret
452  %ptr = getelementptr inbounds i32, i32* %src, i64 1
453  %tmp = load i32, i32* %ptr, align 4
454  %ext = sext i32 %tmp to i64
455  store i64 %ext, i64* %out, align 8
456  ret i32* %ptr
457}
458
459define i16* @preidx16sext32(i16* %src, i32* %out) {
460; CHECK: ldrsh   w[[REG:[0-9]+]], [x0, #2]!
461; CHECK: str     w[[REG]], [x1]
462; CHECK: ret
463  %ptr = getelementptr inbounds i16, i16* %src, i64 1
464  %tmp = load i16, i16* %ptr, align 4
465  %ext = sext i16 %tmp to i32
466  store i32 %ext, i32* %out, align 4
467  ret i16* %ptr
468}
469
470define i16* @preidx16sext64(i16* %src, i64* %out) {
471; CHECK: ldrsh   x[[REG:[0-9]+]], [x0, #2]!
472; CHECK: str     x[[REG]], [x1]
473; CHECK: ret
474  %ptr = getelementptr inbounds i16, i16* %src, i64 1
475  %tmp = load i16, i16* %ptr, align 4
476  %ext = sext i16 %tmp to i64
477  store i64 %ext, i64* %out, align 4
478  ret i16* %ptr
479}
480
481define i8* @preidx8sext32(i8* %src, i32* %out) {
482; CHECK: ldrsb   w[[REG:[0-9]+]], [x0, #1]!
483; CHECK: str     w[[REG]], [x1]
484; CHECK: ret
485  %ptr = getelementptr inbounds i8, i8* %src, i64 1
486  %tmp = load i8, i8* %ptr, align 4
487  %ext = sext i8 %tmp to i32
488  store i32 %ext, i32* %out, align 4
489  ret i8* %ptr
490}
491
492define i8* @preidx8sext64(i8* %src, i64* %out) {
493; CHECK: ldrsb   x[[REG:[0-9]+]], [x0, #1]!
494; CHECK: str     x[[REG]], [x1]
495; CHECK: ret
496  %ptr = getelementptr inbounds i8, i8* %src, i64 1
497  %tmp = load i8, i8* %ptr, align 4
498  %ext = sext i8 %tmp to i64
499  store i64 %ext, i64* %out, align 4
500  ret i8* %ptr
501}
502
503; This test checks if illegal post-index is generated
504
505define i64* @postidx_clobber(i64* %addr) nounwind noinline ssp {
506; CHECK-LABEL: postidx_clobber:
507; CHECK-NOT: str     x0, [x0], #8
508; ret
509 %paddr = bitcast i64* %addr to i64**
510 store i64* %addr, i64** %paddr
511 %newaddr = getelementptr i64, i64* %addr, i32 1
512 ret i64* %newaddr
513}
514