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