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 {
15 %x = alloca i64, align 4
16 call void @use64(ptr %x)
24 ; ALWAYS: ldr x0, [sp]
25 ; DEFAULT: ldr x0, [sp]
26 ; NEVER: ldr x0, [x{{.*}}]
31 define i32 @CallLd32() sanitize_memtag {
33 %x = alloca i32, align 4
34 call void @use32(ptr %x)
42 ; ALWAYS: ldr w0, [sp]
43 ; DEFAULT: ldr w0, [sp]
44 ; NEVER: ldr w0, [x{{.*}}]
49 define i16 @CallLd16() sanitize_memtag {
51 %x = alloca i16, align 4
52 call void @use16(ptr %x)
60 ; ALWAYS: ldrh w0, [sp]
61 ; DEFAULT: ldrh w0, [sp]
62 ; NEVER: ldrh w0, [x{{.*}}]
67 define i8 @CallLd8() sanitize_memtag {
69 %x = alloca i8, align 4
70 call void @use8(ptr %x)
78 ; ALWAYS: ldrb w0, [sp]
79 ; DEFAULT: ldrb w0, [sp]
80 ; NEVER: ldrb w0, [x{{.*}}]
85 define void @CallSt64Call() sanitize_memtag {
87 %x = alloca i64, align 4
88 call void @use64(ptr %x)
90 call void @use64(ptr %x)
94 ; COMMON: CallSt64Call:
97 ; ALWAYS: str x{{.*}}, [sp]
98 ; DEFAULT: str x{{.*}}, [sp]
99 ; NEVER: str x{{.*}}, [x{{.*}}]
105 define void @CallSt32Call() sanitize_memtag {
107 %x = alloca i32, align 4
108 call void @use32(ptr %x)
110 call void @use32(ptr %x)
114 ; COMMON: CallSt32Call:
117 ; ALWAYS: str w{{.*}}, [sp]
118 ; DEFAULT: str w{{.*}}, [sp]
119 ; NEVER: str w{{.*}}, [x{{.*}}]
125 define void @CallSt16Call() sanitize_memtag {
127 %x = alloca i16, align 4
128 call void @use16(ptr %x)
130 call void @use16(ptr %x)
135 ; COMMON: CallSt16Call:
138 ; ALWAYS: strh w{{.*}}, [sp]
139 ; DEFAULT: strh w{{.*}}, [sp]
140 ; NEVER: strh w{{.*}}, [x{{.*}}]
146 define void @CallSt8Call() sanitize_memtag {
148 %x = alloca i8, align 4
149 call void @use8(ptr %x)
151 call void @use8(ptr %x)
155 ; COMMON: CallSt8Call:
158 ; ALWAYS: strb w{{.*}}, [sp]
159 ; DEFAULT: strb w{{.*}}, [sp]
160 ; NEVER: strb w{{.*}}, [x{{.*}}]
166 define void @CallStPair(i64 %z) sanitize_memtag {
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)
177 ; COMMON: CallStPair:
180 ; ALWAYS: stp {{.*}}, [sp]
181 ; DEFAULT: stp {{.*}}, [sp]
182 ; NEVER: stp {{.*}}, [x{{.*}}]
187 ; One of the two allocas will end up out of range of ldrb [sp].
188 define dso_local i8 @LargeFrame() sanitize_memtag {
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
200 ; COMMON: LargeFrame:
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]]]
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
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{{.*}}]