xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64-mte.ll (revision 5ddce70ef0e5a641d7fea95e31fc5e2439cb98cb)
1; RUN: llc < %s -mtriple=arm64-eabi -mattr=+mte | FileCheck %s
2
3; test create_tag
4define ptr @create_tag(ptr %ptr, i32 %m) {
5entry:
6; CHECK-LABEL: create_tag:
7  %0 = zext i32 %m to i64
8  %1 = tail call ptr @llvm.aarch64.irg(ptr %ptr, i64 %0)
9  ret ptr %1
10;CHECK: irg x0, x0, {{x[0-9]+}}
11}
12
13; *********** __arm_mte_increment_tag  *************
14; test increment_tag1
15define ptr @increment_tag1(ptr %ptr) {
16entry:
17; CHECK-LABEL: increment_tag1:
18  %0 = tail call ptr @llvm.aarch64.addg(ptr %ptr, i64 7)
19  ret ptr %0
20; CHECK: addg x0, x0, #0, #7
21}
22
23%struct.S2K = type { [512 x i32] }
24define ptr @increment_tag1stack(ptr %ptr) {
25entry:
26; CHECK-LABEL: increment_tag1stack:
27  %s = alloca %struct.S2K, align 4
28  call void @llvm.lifetime.start.p0(i64 2048, ptr nonnull %s)
29  %0 = call ptr @llvm.aarch64.addg(ptr nonnull %s, i64 7)
30  call void @llvm.lifetime.end.p0(i64 2048, ptr nonnull %s)
31  ret ptr %0
32; CHECK: addg x0, sp, #0, #7
33}
34
35
36define ptr @increment_tag2(ptr %ptr) {
37entry:
38; CHECK-LABEL: increment_tag2:
39  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 4
40  %0 = tail call ptr @llvm.aarch64.addg(ptr nonnull %add.ptr, i64 7)
41  ret ptr %0
42; CHECK: addg x0, x0, #16, #7
43}
44
45define ptr @increment_tag2stack(ptr %ptr) {
46entry:
47; CHECK-LABEL: increment_tag2stack:
48  %s = alloca %struct.S2K, align 4
49  call void @llvm.lifetime.start.p0(i64 2048, ptr nonnull %s)
50  %arrayidx = getelementptr inbounds %struct.S2K, ptr %s, i64 0, i32 0, i64 4
51  %0 = call ptr @llvm.aarch64.addg(ptr nonnull %arrayidx, i64 7)
52  call void @llvm.lifetime.end.p0(i64 2048, ptr nonnull %s)
53  ret ptr %0
54; CHECK: addg x0, sp, #16, #7
55}
56
57define ptr @increment_tag3(ptr %ptr) {
58entry:
59; CHECK-LABEL: increment_tag3:
60  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 252
61  %0 = tail call ptr @llvm.aarch64.addg(ptr nonnull %add.ptr, i64 7)
62  ret ptr %0
63; CHECK: addg x0, x0, #1008, #7
64}
65
66define ptr @increment_tag3stack(ptr %ptr) {
67entry:
68; CHECK-LABEL: increment_tag3stack:
69  %s = alloca %struct.S2K, align 4
70  call void @llvm.lifetime.start.p0(i64 2048, ptr nonnull %s)
71  %arrayidx = getelementptr inbounds %struct.S2K, ptr %s, i64 0, i32 0, i64 252
72  %0 = call ptr @llvm.aarch64.addg(ptr nonnull %arrayidx, i64 7)
73  call void @llvm.lifetime.end.p0(i64 2048, ptr nonnull %s)
74  ret ptr %0
75; CHECK: addg x0, sp, #1008, #7
76}
77
78
79define ptr @increment_tag4(ptr %ptr) {
80entry:
81; CHECK-LABEL: increment_tag4:
82  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 256
83  %0 = tail call ptr @llvm.aarch64.addg(ptr nonnull %add.ptr, i64 7)
84  ret ptr %0
85; CHECK: add [[T0:x[0-9]+]], x0, #1024
86; CHECK-NEXT: addg x0, [[T0]], #0, #7
87}
88
89define ptr @increment_tag4stack(ptr %ptr) {
90entry:
91; CHECK-LABEL: increment_tag4stack:
92  %s = alloca %struct.S2K, align 4
93  call void @llvm.lifetime.start.p0(i64 2048, ptr nonnull %s)
94  %arrayidx = getelementptr inbounds %struct.S2K, ptr %s, i64 0, i32 0, i64 256
95  %0 = call ptr @llvm.aarch64.addg(ptr nonnull %arrayidx, i64 7)
96  call void @llvm.lifetime.end.p0(i64 2048, ptr nonnull %s)
97  ret ptr %0
98; CHECK: add [[T0:x[0-9]+]], {{.*}}, #1024
99; CHECK-NEXT: addg x0, [[T0]], #0, #7
100}
101
102
103define ptr @increment_tag5(ptr %ptr) {
104entry:
105; CHECK-LABEL: increment_tag5:
106  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 5
107  %0 = tail call ptr @llvm.aarch64.addg(ptr nonnull %add.ptr, i64 7)
108  ret ptr %0
109; CHECK: add [[T0:x[0-9]+]], x0, #20
110; CHECK-NEXT: addg x0, [[T0]], #0, #7
111}
112
113define ptr @increment_tag5stack(ptr %ptr) {
114entry:
115; CHECK-LABEL: increment_tag5stack:
116  %s = alloca %struct.S2K, align 4
117  call void @llvm.lifetime.start.p0(i64 2048, ptr nonnull %s)
118  %arrayidx = getelementptr inbounds %struct.S2K, ptr %s, i64 0, i32 0, i64 5
119  %0 = call ptr @llvm.aarch64.addg(ptr nonnull %arrayidx, i64 7)
120  call void @llvm.lifetime.end.p0(i64 2048, ptr nonnull %s)
121  ret ptr %0
122; CHECK: add [[T0:x[0-9]+]], {{.*}}, #20
123; CHECK-NEXT: addg x0, [[T0]], #0, #7
124}
125
126
127; *********** __arm_mte_exclude_tag  *************
128; test exclude_tag
129define i32 @exclude_tag(ptr %ptr, i32 %m) local_unnamed_addr #0 {
130entry:
131;CHECK-LABEL: exclude_tag:
132  %0 = zext i32 %m to i64
133  %1 = tail call i64 @llvm.aarch64.gmi(ptr %ptr, i64 %0)
134  %conv = trunc i64 %1 to i32
135  ret i32 %conv
136; CHECK: gmi	x0, x0, {{x[0-9]+}}
137}
138
139
140; *********** __arm_mte_get_tag *************
141%struct.S8K = type { [2048 x i32] }
142define ptr @get_tag1(ptr %ptr) {
143entry:
144; CHECK-LABEL: get_tag1:
145  %0 = tail call ptr @llvm.aarch64.ldg(ptr %ptr, ptr %ptr)
146  ret ptr %0
147; CHECK: ldg x0, [x0]
148}
149
150define ptr @get_tag1_two_parm(ptr %ret_ptr, ptr %ptr) {
151entry:
152; CHECK-LABEL: get_tag1_two_parm:
153  %0 = tail call ptr @llvm.aarch64.ldg(ptr %ret_ptr, ptr %ptr)
154  ret ptr %0
155; CHECK: ldg x0, [x1]
156}
157
158define ptr @get_tag1stack() {
159entry:
160; CHECK-LABEL: get_tag1stack:
161  %s = alloca %struct.S8K, align 4
162  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
163  %0 = call ptr @llvm.aarch64.ldg(ptr nonnull %s, ptr nonnull %s)
164  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
165  ret ptr %0
166; CHECK: mov [[T0:x[0-9]+]], sp
167; CHECK: ldg [[T0]], [sp]
168}
169
170define ptr @get_tag1stack_two_param(ptr %ret_ptr) {
171entry:
172; CHECK-LABEL: get_tag1stack_two_param:
173  %s = alloca %struct.S8K, align 4
174  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
175  %0 = call ptr @llvm.aarch64.ldg(ptr nonnull %ret_ptr, ptr nonnull %s)
176  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
177  ret ptr %0
178; CHECK-NOT: mov {{.*}}, sp
179; CHECK: ldg x0, [sp]
180}
181
182
183define ptr @get_tag2(ptr %ptr) {
184entry:
185; CHECK-LABEL: get_tag2:
186  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 4
187  %0 = tail call ptr @llvm.aarch64.ldg(ptr nonnull %add.ptr, ptr nonnull %add.ptr)
188  ret ptr %0
189; CHECK: add  [[T0:x[0-9]+]], x0, #16
190; CHECK: ldg  [[T0]], [x0, #16]
191}
192
193define ptr @get_tag2stack() {
194entry:
195; CHECK-LABEL: get_tag2stack:
196  %s = alloca %struct.S8K, align 4
197  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
198  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 4
199  %0 = call ptr @llvm.aarch64.ldg(ptr nonnull %arrayidx, ptr nonnull %arrayidx)
200  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
201  ret ptr %0
202; CHECK: mov [[T0:x[0-9]+]], sp
203; CHECK: add x0, [[T0]], #16
204; CHECK: ldg x0, [sp, #16]
205}
206
207
208define ptr @get_tag3(ptr %ptr) {
209entry:
210; CHECK-LABEL: get_tag3:
211  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 1020
212  %0 = tail call ptr @llvm.aarch64.ldg(ptr nonnull %add.ptr, ptr nonnull %add.ptr)
213  ret ptr %0
214; CHECK: add [[T0:x[0-8]+]], x0, #4080
215; CHECK: ldg [[T0]], [x0, #4080]
216}
217
218define ptr @get_tag3stack() {
219entry:
220; CHECK-LABEL: get_tag3stack:
221  %s = alloca %struct.S8K, align 4
222  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
223  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 1020
224  %0 = call ptr @llvm.aarch64.ldg(ptr nonnull %arrayidx, ptr nonnull %arrayidx)
225  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
226  ret ptr %0
227; CHECK: mov [[T0:x[0-9]+]], sp
228; CHECK: add x0, [[T0]], #4080
229; CHECK: ldg x0, [sp, #4080]
230}
231
232
233define ptr @get_tag4(ptr %ptr) {
234entry:
235; CHECK-LABEL: get_tag4:
236  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 1024
237  %0 = tail call ptr @llvm.aarch64.ldg(ptr nonnull %add.ptr, ptr nonnull %add.ptr)
238  ret ptr %0
239; CHECK: add x0, x0, #1, lsl #12
240; CHECK-NEXT: ldg x0, [x0]
241}
242
243define ptr @get_tag4stack() {
244entry:
245; CHECK-LABEL: get_tag4stack:
246  %s = alloca %struct.S8K, align 4
247  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
248  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 1024
249  %0 = call ptr @llvm.aarch64.ldg(ptr nonnull %arrayidx, ptr nonnull %arrayidx)
250  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
251  ret ptr %0
252; CHECK: mov [[T0:x[0-9]+]], sp
253; CHECK-NEXT: add x[[T1:[0-9]+]], [[T0]], #1, lsl #12
254; CHECK-NEXT: ldg x[[T1]], [x[[T1]]]
255}
256
257define ptr @get_tag5(ptr %ptr) {
258entry:
259; CHECK-LABEL: get_tag5:
260  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 5
261  %0 = tail call ptr @llvm.aarch64.ldg(ptr nonnull %add.ptr, ptr nonnull %add.ptr)
262  ret ptr %0
263; CHECK: add x0, x0, #20
264; CHECK-NEXT: ldg x0, [x0]
265}
266
267define ptr @get_tag5stack() {
268entry:
269; CHECK-LABEL: get_tag5stack:
270  %s = alloca %struct.S8K, align 4
271  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
272  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 5
273  %0 = call ptr @llvm.aarch64.ldg(ptr nonnull %arrayidx, ptr nonnull %arrayidx)
274  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
275  ret ptr %0
276; CHECK: mov [[T0:x[0-9]+]], sp
277; CHECK: add x[[T1:[0-9]+]], [[T0]], #20
278; CHECK-NEXT: ldg x[[T1]], [x[[T1]]]
279}
280
281
282; *********** __arm_mte_set_tag  *************
283define void @set_tag1(ptr %tag, ptr %ptr) {
284entry:
285; CHECK-LABEL: set_tag1:
286  tail call void @llvm.aarch64.stg(ptr %tag, ptr %ptr)
287  ret void
288; CHECK: stg x0, [x1]
289}
290
291define void @set_tag1stack(ptr %tag) {
292entry:
293; CHECK-LABEL: set_tag1stack:
294  %s = alloca %struct.S8K, align 4
295  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
296  call void @llvm.aarch64.stg(ptr %tag, ptr nonnull %s)
297  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %tag)
298  ret void
299; CHECK: stg x0, [sp]
300}
301
302
303define void @set_tag2(ptr %tag, ptr %ptr) {
304entry:
305; CHECK-LABEL: set_tag2:
306  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 4
307  tail call void @llvm.aarch64.stg(ptr %tag, ptr %add.ptr)
308  ret void
309; CHECK: stg x0, [x1, #16]
310}
311
312define void @set_tag2stack(ptr %tag, ptr %ptr) {
313entry:
314; CHECK-LABEL: set_tag2stack:
315  %s = alloca %struct.S8K, align 4
316  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
317  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 4
318  call void @llvm.aarch64.stg(ptr %tag, ptr nonnull %arrayidx)
319  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
320  ret void
321; CHECK: stg x0, [sp, #16]
322}
323
324
325
326define void @set_tag3(ptr %tag, ptr %ptr) {
327entry:
328; CHECK-LABEL: set_tag3:
329  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 1020
330  tail call void @llvm.aarch64.stg(ptr %tag, ptr %add.ptr)
331  ret void
332; CHECK: stg x0, [x1, #4080]
333}
334
335define void @set_tag3stack(ptr %tag, ptr %ptr) {
336entry:
337; CHECK-LABEL: set_tag3stack:
338  %s = alloca %struct.S8K, align 4
339  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
340  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 1020
341  call void @llvm.aarch64.stg(ptr %tag, ptr nonnull %arrayidx)
342  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
343  ret void
344; CHECK: stg x0, [sp, #4080]
345}
346
347
348
349define void @set_tag4(ptr %tag, ptr %ptr) {
350entry:
351; CHECK-LABEL: set_tag4:
352  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 1024
353  tail call void @llvm.aarch64.stg(ptr %tag, ptr %add.ptr)
354  ret void
355; CHECK: add x[[T0:[0-9]+]], x1, #1, lsl #12
356; CHECK-NEXT: stg x0, [x[[T0]]]
357}
358
359define void @set_tag4stack(ptr %tag, ptr %ptr) {
360entry:
361; CHECK-LABEL: set_tag4stack:
362  %s = alloca %struct.S8K, align 4
363  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
364  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 1024
365  call void @llvm.aarch64.stg(ptr %tag, ptr nonnull %arrayidx)
366  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
367  ret void
368; CHECK: add x[[T0:[0-9]+]], {{.*}}, #1, lsl #12
369; CHECK-NEXT: stg x0, [x[[T0]]]
370}
371
372
373define void @set_tag5(ptr %tag, ptr %ptr) {
374entry:
375; CHECK-LABEL: set_tag5:
376  %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 5
377  tail call void @llvm.aarch64.stg(ptr %tag, ptr %add.ptr)
378  ret void
379; CHECK: add x[[T0:[0-9]+]], x1, #20
380; CHECK-NEXT: stg x0, [x[[T0]]]
381}
382
383define void @set_tag5stack(ptr %tag, ptr %ptr) {
384entry:
385; CHECK-LABEL: set_tag5stack:
386  %s = alloca %struct.S8K, align 4
387  call void @llvm.lifetime.start.p0(i64 8192, ptr nonnull %s)
388  %arrayidx = getelementptr inbounds %struct.S8K, ptr %s, i64 0, i32 0, i64 5
389  call void @llvm.aarch64.stg(ptr %tag, ptr nonnull %arrayidx)
390  call void @llvm.lifetime.end.p0(i64 8192, ptr nonnull %s)
391  ret void
392; CHECK: add x[[T0:[0-9]+]], {{.*}}, #20
393; CHECK-NEXT: stg x0, [x[[T0]]]
394}
395
396
397; *********** __arm_mte_ptrdiff  *************
398define i64 @subtract_pointers(ptr %ptra, ptr %ptrb) {
399entry:
400; CHECK-LABEL: subtract_pointers:
401  %0 = tail call i64 @llvm.aarch64.subp(ptr %ptra, ptr %ptrb)
402  ret i64 %0
403; CHECK: subp x0, x0, x1
404}
405
406declare ptr @llvm.aarch64.irg(ptr, i64)
407declare ptr @llvm.aarch64.addg(ptr, i64)
408declare i64 @llvm.aarch64.gmi(ptr, i64)
409declare ptr @llvm.aarch64.ldg(ptr, ptr)
410declare void @llvm.aarch64.stg(ptr, ptr)
411declare i64 @llvm.aarch64.subp(ptr, ptr)
412
413declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
414declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
415