Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / AArch64 / stack-tagging-unchecked-ld-st.ll
blob88c00a33042594768553f52f272b94892c990941
1 ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s --check-prefixes=DEFAULT,COMMON
2 ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte -stack-tagging-unchecked-ld-st=never | FileCheck %s --check-prefixes=NEVER,COMMON
3 ; RUN: llc < %s -mtriple=aarch64 -mattr=+mte -stack-tagging-unchecked-ld-st=always | FileCheck %s --check-prefixes=ALWAYS,COMMON
5 declare void @use8(ptr)
6 declare void @use16(ptr)
7 declare void @use32(ptr)
8 declare void @use64(ptr)
9 declare void @use2x64(ptr)
10 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
11 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
13 define i64 @CallLd64() sanitize_memtag {
14 entry:
15   %x = alloca i64, align 4
16   call void @use64(ptr %x)
17   %a = load i64, ptr %x
18   ret i64 %a
21 ; COMMON:  CallLd64:
22 ; COMMON:  bl  use64
24 ; ALWAYS:  ldr x0, [sp]
25 ; DEFAULT: ldr x0, [sp]
26 ; NEVER:   ldr x0, [x{{.*}}]
28 ; COMMON:  ret
31 define i32 @CallLd32() sanitize_memtag {
32 entry:
33   %x = alloca i32, align 4
34   call void @use32(ptr %x)
35   %a = load i32, ptr %x
36   ret i32 %a
39 ; COMMON:  CallLd32:
40 ; COMMON:  bl  use32
42 ; ALWAYS:  ldr w0, [sp]
43 ; DEFAULT: ldr w0, [sp]
44 ; NEVER:   ldr w0, [x{{.*}}]
46 ; COMMON:  ret
49 define i16 @CallLd16() sanitize_memtag {
50 entry:
51   %x = alloca i16, align 4
52   call void @use16(ptr %x)
53   %a = load i16, ptr %x
54   ret i16 %a
57 ; COMMON:  CallLd16:
58 ; COMMON:  bl  use16
60 ; ALWAYS:  ldrh w0, [sp]
61 ; DEFAULT: ldrh w0, [sp]
62 ; NEVER:   ldrh w0, [x{{.*}}]
64 ; COMMON:  ret
67 define i8 @CallLd8() sanitize_memtag {
68 entry:
69   %x = alloca i8, align 4
70   call void @use8(ptr %x)
71   %a = load i8, ptr %x
72   ret i8 %a
75 ; COMMON:  CallLd8:
76 ; COMMON:  bl  use8
78 ; ALWAYS:  ldrb w0, [sp]
79 ; DEFAULT: ldrb w0, [sp]
80 ; NEVER:   ldrb w0, [x{{.*}}]
82 ; COMMON:  ret
85 define void @CallSt64Call() sanitize_memtag {
86 entry:
87   %x = alloca i64, align 4
88   call void @use64(ptr %x)
89   store i64 42, ptr %x
90   call void @use64(ptr %x)
91   ret void
94 ; COMMON:  CallSt64Call:
95 ; COMMON:  bl  use64
97 ; ALWAYS:  str x{{.*}}, [sp]
98 ; DEFAULT: str x{{.*}}, [sp]
99 ; NEVER:   str x{{.*}}, [x{{.*}}]
101 ; COMMON:  bl  use64
102 ; COMMON:  ret
105 define void @CallSt32Call() sanitize_memtag {
106 entry:
107   %x = alloca i32, align 4
108   call void @use32(ptr %x)
109   store i32 42, ptr %x
110   call void @use32(ptr %x)
111   ret void
114 ; COMMON:  CallSt32Call:
115 ; COMMON:  bl  use32
117 ; ALWAYS:  str w{{.*}}, [sp]
118 ; DEFAULT: str w{{.*}}, [sp]
119 ; NEVER:   str w{{.*}}, [x{{.*}}]
121 ; COMMON:  bl  use32
122 ; COMMON:  ret
125 define void @CallSt16Call() sanitize_memtag {
126 entry:
127   %x = alloca i16, align 4
128   call void @use16(ptr %x)
129   store i16 42, ptr %x
130   call void @use16(ptr %x)
131   ret void
135 ; COMMON:  CallSt16Call:
136 ; COMMON:  bl  use16
138 ; ALWAYS:  strh w{{.*}}, [sp]
139 ; DEFAULT: strh w{{.*}}, [sp]
140 ; NEVER:   strh w{{.*}}, [x{{.*}}]
142 ; COMMON:  bl  use16
143 ; COMMON:  ret
146 define void @CallSt8Call() sanitize_memtag {
147 entry:
148   %x = alloca i8, align 4
149   call void @use8(ptr %x)
150   store i8 42, ptr %x
151   call void @use8(ptr %x)
152   ret void
155 ; COMMON:  CallSt8Call:
156 ; COMMON:  bl  use8
158 ; ALWAYS:  strb w{{.*}}, [sp]
159 ; DEFAULT: strb w{{.*}}, [sp]
160 ; NEVER:   strb w{{.*}}, [x{{.*}}]
162 ; COMMON:  bl  use8
163 ; COMMON:  ret
166 define void @CallStPair(i64 %z) sanitize_memtag {
167 entry:
168   %x = alloca [2 x i64], align 8
169   call void @use2x64(ptr %x)
170   store i64 %z, ptr %x, align 8
171   %x1 = getelementptr inbounds [2 x i64], ptr %x, i64 0, i64 1
172   store i64 %z, ptr %x1, align 8
173   call void @use2x64(ptr %x)
174   ret void
177 ; COMMON:  CallStPair:
178 ; COMMON:  bl  use2x64
180 ; ALWAYS:  stp {{.*}}, [sp]
181 ; DEFAULT: stp {{.*}}, [sp]
182 ; NEVER:   stp {{.*}}, [x{{.*}}]
184 ; COMMON:  bl  use2x64
185 ; COMMON:  ret
187 ; One of the two allocas will end up out of range of ldrb [sp].
188 define dso_local i8 @LargeFrame() sanitize_memtag {
189 entry:
190   %x = alloca [4096 x i8], align 4
191   %y = alloca [4096 x i8], align 4
192   call void @use8(ptr %x)
193   call void @use8(ptr %y)
194   %0 = load i8, ptr %x, align 4
195   %1 = load i8, ptr %y, align 4
196   %add = add i8 %1, %0
197   ret i8 %add
200 ; COMMON: LargeFrame:
201 ; COMMON: bl use8
202 ; COMMON: bl use8
204 ; NEVER:  ldrb [[A:w.*]], [x{{.*}}]
205 ; NEVER:  ldrb [[B:w.*]], [x{{.*}}]
207 ; DEFAULT:  ldrb [[A:w.*]], [x{{.*}}]
208 ; DEFAULT:  ldrb [[B:w.*]], [x{{.*}}]
210 ; ALWAYS-DAG: ldg [[PA:x.*]], [x{{.*}}]
211 ; ALWAYS-DAG: ldrb [[B:w.*]], [sp]
212 ; ALWAYS-DAG: ldrb [[A:w.*]], [[[PA]]]
214 ; COMMON: ret
216 ; One of these allocas is closer to FP than to SP, and within 256 bytes
217 ; of the former (see hardcoded limit in resolveFrameOffsetReference).
218 ; It could be lowered to an FP-relative load, but not when doing an
219 ; unchecked access to tagged memory!
220 define i8 @FPOffset() "frame-pointer"="all" sanitize_memtag {
221   %x = alloca [200 x i8], align 4
222   %y = alloca [200 x i8], align 4
223   %z = alloca [200 x i8], align 4
224   call void @use8(ptr %x)
225   call void @use8(ptr %y)
226   call void @use8(ptr %z)
227   %x1 = load i8, ptr %x, align 4
228   %y1 = load i8, ptr %y, align 4
229   %z1 = load i8, ptr %z, align 4
230   %a = add i8 %x1, %y1
231   %b = add i8 %a, %z1
232   ret i8 %b
235 ; COMMON: FPOffset:
236 ; COMMON: bl use8
237 ; COMMON: bl use8
238 ; COMMON: bl use8
240 ; All three loads are SP-based.
241 ; ALWAYS-DAG: ldrb  w{{.*}}, [sp, #416]
242 ; ALWAYS-DAG: ldrb  w{{.*}}, [sp, #208]
243 ; ALWAYS-DAG: ldrb  w{{.*}}, [sp]
245 ; DEFAULT-DAG: ldrb  w{{.*}}, [sp, #416]
246 ; DEFAULT-DAG: ldrb  w{{.*}}, [sp, #208]
247 ; DEFAULT-DAG: ldrb  w{{.*}}, [sp]
249 ; NEVER-DAG: ldrb  w{{.*}}, [x{{.*}}]
250 ; NEVER-DAG: ldrb  w{{.*}}, [x{{.*}}]
251 ; NEVER-DAG: ldrb  w{{.*}}, [x{{.*}}]
253 ; COMMON: ret