[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / AArch64 / arm64-mte.ll
blobc70bef5706d21eb0c165290ddca706ad49fbbd6d
1 ; RUN: llc < %s -mtriple=arm64-eabi -mattr=+mte | FileCheck %s
3 ; test create_tag
4 define i32* @create_tag(i32* %ptr, i32 %m) {
5 entry:
6 ; CHECK-LABEL: create_tag:
7   %0 = bitcast i32* %ptr to i8*
8   %1 = zext i32 %m to i64
9   %2 = tail call i8* @llvm.aarch64.irg(i8* %0, i64 %1)
10   %3 = bitcast i8* %2 to i32*
11   ret i32* %3
12 ;CHECK: irg x0, x0, {{x[0-9]+}}
15 ; *********** __arm_mte_increment_tag  *************
16 ; test increment_tag1
17 define i32* @increment_tag1(i32* %ptr) {
18 entry:
19 ; CHECK-LABEL: increment_tag1:
20   %0 = bitcast i32* %ptr to i8*
21   %1 = tail call i8* @llvm.aarch64.addg(i8* %0, i64 7)
22   %2 = bitcast i8* %1 to i32*
23   ret i32* %2
24 ; CHECK: addg x0, x0, #0, #7
27 %struct.S2K = type { [512 x i32] }
28 define i32* @increment_tag1stack(i32* %ptr) {
29 entry:
30 ; CHECK-LABEL: increment_tag1stack:
31   %s = alloca %struct.S2K, align 4
32   %0 = bitcast %struct.S2K* %s to i8*
33   call void @llvm.lifetime.start.p0i8(i64 2048, i8* nonnull %0)
34   %1 = call i8* @llvm.aarch64.addg(i8* nonnull %0, i64 7)
35   %2 = bitcast i8* %1 to i32*
36   call void @llvm.lifetime.end.p0i8(i64 2048, i8* nonnull %0)
37   ret i32* %2
38 ; CHECK: addg x0, sp, #0, #7
42 define i32* @increment_tag2(i32* %ptr) {
43 entry:
44 ; CHECK-LABEL: increment_tag2:
45   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 4
46   %0 = bitcast i32* %add.ptr to i8*
47   %1 = tail call i8* @llvm.aarch64.addg(i8* nonnull %0, i64 7)
48   %2 = bitcast i8* %1 to i32*
49   ret i32* %2
50 ; CHECK: addg x0, x0, #16, #7
53 define i32* @increment_tag2stack(i32* %ptr) {
54 entry:
55 ; CHECK-LABEL: increment_tag2stack:
56   %s = alloca %struct.S2K, align 4
57   %0 = bitcast %struct.S2K* %s to i8*
58   call void @llvm.lifetime.start.p0i8(i64 2048, i8* nonnull %0)
59   %arrayidx = getelementptr inbounds %struct.S2K, %struct.S2K* %s, i64 0, i32 0, i64 4
60   %1 = bitcast i32* %arrayidx to i8*
61   %2 = call i8* @llvm.aarch64.addg(i8* nonnull %1, i64 7)
62   %3 = bitcast i8* %2 to i32*
63   call void @llvm.lifetime.end.p0i8(i64 2048, i8* nonnull %0)
64   ret i32* %3
65 ; CHECK: addg x0, sp, #16, #7
68 define i32* @increment_tag3(i32* %ptr) {
69 entry:
70 ; CHECK-LABEL: increment_tag3:
71   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 252
72   %0 = bitcast i32* %add.ptr to i8*
73   %1 = tail call i8* @llvm.aarch64.addg(i8* nonnull %0, i64 7)
74   %2 = bitcast i8* %1 to i32*
75   ret i32* %2
76 ; CHECK: addg x0, x0, #1008, #7
79 define i32* @increment_tag3stack(i32* %ptr) {
80 entry:
81 ; CHECK-LABEL: increment_tag3stack:
82   %s = alloca %struct.S2K, align 4
83   %0 = bitcast %struct.S2K* %s to i8*
84   call void @llvm.lifetime.start.p0i8(i64 2048, i8* nonnull %0)
85   %arrayidx = getelementptr inbounds %struct.S2K, %struct.S2K* %s, i64 0, i32 0, i64 252
86   %1 = bitcast i32* %arrayidx to i8*
87   %2 = call i8* @llvm.aarch64.addg(i8* nonnull %1, i64 7)
88   %3 = bitcast i8* %2 to i32*
89   call void @llvm.lifetime.end.p0i8(i64 2048, i8* nonnull %0)
90   ret i32* %3
91 ; CHECK: addg x0, sp, #1008, #7
95 define i32* @increment_tag4(i32* %ptr) {
96 entry:
97 ; CHECK-LABEL: increment_tag4:
98   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 256
99   %0 = bitcast i32* %add.ptr to i8*
100   %1 = tail call i8* @llvm.aarch64.addg(i8* nonnull %0, i64 7)
101   %2 = bitcast i8* %1 to i32*
102   ret i32* %2
103 ; CHECK: add [[T0:x[0-9]+]], x0, #1024
104 ; CHECK-NEXT: addg x0, [[T0]], #0, #7
107 define i32* @increment_tag4stack(i32* %ptr) {
108 entry:
109 ; CHECK-LABEL: increment_tag4stack:
110   %s = alloca %struct.S2K, align 4
111   %0 = bitcast %struct.S2K* %s to i8*
112   call void @llvm.lifetime.start.p0i8(i64 2048, i8* nonnull %0)
113   %arrayidx = getelementptr inbounds %struct.S2K, %struct.S2K* %s, i64 0, i32 0, i64 256
114   %1 = bitcast i32* %arrayidx to i8*
115   %2 = call i8* @llvm.aarch64.addg(i8* nonnull %1, i64 7)
116   %3 = bitcast i8* %2 to i32*
117   call void @llvm.lifetime.end.p0i8(i64 2048, i8* nonnull %0)
118   ret i32* %3
119 ; CHECK: add [[T0:x[0-9]+]], {{.*}}, #1024
120 ; CHECK-NEXT: addg x0, [[T0]], #0, #7
124 define i32* @increment_tag5(i32* %ptr) {
125 entry:
126 ; CHECK-LABEL: increment_tag5:
127   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 5
128   %0 = bitcast i32* %add.ptr to i8*
129   %1 = tail call i8* @llvm.aarch64.addg(i8* nonnull %0, i64 7)
130   %2 = bitcast i8* %1 to i32*
131   ret i32* %2
132 ; CHECK: add [[T0:x[0-9]+]], x0, #20
133 ; CHECK-NEXT: addg x0, [[T0]], #0, #7
136 define i32* @increment_tag5stack(i32* %ptr) {
137 entry:
138 ; CHECK-LABEL: increment_tag5stack:
139   %s = alloca %struct.S2K, align 4
140   %0 = bitcast %struct.S2K* %s to i8*
141   call void @llvm.lifetime.start.p0i8(i64 2048, i8* nonnull %0)
142   %arrayidx = getelementptr inbounds %struct.S2K, %struct.S2K* %s, i64 0, i32 0, i64 5
143   %1 = bitcast i32* %arrayidx to i8*
144   %2 = call i8* @llvm.aarch64.addg(i8* nonnull %1, i64 7)
145   %3 = bitcast i8* %2 to i32*
146   call void @llvm.lifetime.end.p0i8(i64 2048, i8* nonnull %0)
147   ret i32* %3
148 ; CHECK: add [[T0:x[0-9]+]], {{.*}}, #20
149 ; CHECK-NEXT: addg x0, [[T0]], #0, #7
153 ; *********** __arm_mte_exclude_tag  *************
154 ; test exclude_tag
155 define i32 @exclude_tag(i32* %ptr, i32 %m) local_unnamed_addr #0 {
156 entry:
157 ;CHECK-LABEL: exclude_tag:
158   %0 = zext i32 %m to i64
159   %1 = bitcast i32* %ptr to i8*
160   %2 = tail call i64 @llvm.aarch64.gmi(i8* %1, i64 %0)
161   %conv = trunc i64 %2 to i32
162   ret i32 %conv
163 ; CHECK: gmi    x0, x0, {{x[0-9]+}}
167 ; *********** __arm_mte_get_tag *************
168 %struct.S8K = type { [2048 x i32] }
169 define i32* @get_tag1(i32* %ptr) {
170 entry:
171 ; CHECK-LABEL: get_tag1:
172   %0 = bitcast i32* %ptr to i8*
173   %1 = tail call i8* @llvm.aarch64.ldg(i8* %0, i8* %0)
174   %2 = bitcast i8* %1 to i32*
175   ret i32* %2
176 ; CHECK ldg x0, [x0]
179 define i32* @get_tag1_two_parm(i32* %ret_ptr, i32* %ptr) {
180 entry:
181 ; CHECK-LABEL: get_tag1_two_parm:
182   %0 = bitcast i32* %ret_ptr to i8*
183   %1 = bitcast i32* %ptr to i8*
184   %2 = tail call i8* @llvm.aarch64.ldg(i8* %0, i8* %1)
185   %3 = bitcast i8* %2 to i32*
186   ret i32* %3
187 ; CHECK ldg x0, [x1]
190 define i32* @get_tag1stack() {
191 entry:
192 ; CHECK-LABEL: get_tag1stack:
193   %s = alloca %struct.S8K, align 4
194   %0 = bitcast %struct.S8K* %s to i8*
195   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
196   %1 = call i8* @llvm.aarch64.ldg(i8* nonnull %0, i8* nonnull %0)
197   %2 = bitcast i8* %1 to i32*
198   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
199   ret i32* %2
200 ; CHECK: mov [[T0:x[0-9]+]], sp
201 ; CHECK: ldg [[T0]], [sp]
204 define i32* @get_tag1stack_two_param(i32* %ret_ptr) {
205 entry:
206 ; CHECK-LABEL: get_tag1stack_two_param:
207   %s = alloca %struct.S8K, align 4
208   %0 = bitcast %struct.S8K* %s to i8*
209   %1 = bitcast i32*  %ret_ptr to i8*
210   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
211   %2 = call i8* @llvm.aarch64.ldg(i8* nonnull %1, i8* nonnull %0)
212   %3 = bitcast i8* %2 to i32*
213   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
214   ret i32* %3
215 ; CHECK-NOT: mov {{.*}}, sp
216 ; CHECK: ldg x0, [sp]
220 define i32* @get_tag2(i32* %ptr) {
221 entry:
222 ; CHECK-LABEL: get_tag2:
223   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 4
224   %0 = bitcast i32* %add.ptr to i8*
225   %1 = tail call i8* @llvm.aarch64.ldg(i8* nonnull %0, i8* nonnull %0)
226   %2 = bitcast i8* %1 to i32*
227   ret i32* %2
228 ; CHECK: add  [[T0:x[0-9]+]], x0, #16
229 ; CHECK: ldg  [[T0]], [x0, #16]
232 define i32* @get_tag2stack() {
233 entry:
234 ; CHECK-LABEL: get_tag2stack:
235   %s = alloca %struct.S8K, align 4
236   %0 = bitcast %struct.S8K* %s to i8*
237   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
238   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 4
239   %1 = bitcast i32* %arrayidx to i8*
240   %2 = call i8* @llvm.aarch64.ldg(i8* nonnull %1, i8* nonnull %1)
241   %3 = bitcast i8* %2 to i32*
242   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
243   ret i32* %3
244 ; CHECK: mov [[T0:x[0-9]+]], sp
245 ; CHECK: add x0, [[T0]], #16
246 ; CHECK: ldg x0, [sp, #16]
250 define i32* @get_tag3(i32* %ptr) {
251 entry:
252 ; CHECK-LABEL: get_tag3:
253   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 1020
254   %0 = bitcast i32* %add.ptr to i8*
255   %1 = tail call i8* @llvm.aarch64.ldg(i8* nonnull %0, i8* nonnull %0)
256   %2 = bitcast i8* %1 to i32*
257   ret i32* %2
258 ; CHECK: add [[T0:x[0-8]+]], x0, #4080
259 ; CHECK: ldg [[T0]], [x0, #4080]
262 define i32* @get_tag3stack() {
263 entry:
264 ; CHECK-LABEL: get_tag3stack:
265   %s = alloca %struct.S8K, align 4
266   %0 = bitcast %struct.S8K* %s to i8*
267   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
268   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 1020
269   %1 = bitcast i32* %arrayidx to i8*
270   %2 = call i8* @llvm.aarch64.ldg(i8* nonnull %1, i8* nonnull %1)
271   %3 = bitcast i8* %2 to i32*
272   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
273   ret i32* %3
274 ; CHECK: mov [[T0:x[0-9]+]], sp
275 ; CHECK: add x0, [[T0]], #4080
276 ; CHECK: ldg x0, [sp, #4080]
280 define i32* @get_tag4(i32* %ptr) {
281 entry:
282 ; CHECK-LABEL: get_tag4:
283   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 1024
284   %0 = bitcast i32* %add.ptr to i8*
285   %1 = tail call i8* @llvm.aarch64.ldg(i8* nonnull %0, i8* nonnull %0)
286   %2 = bitcast i8* %1 to i32*
287   ret i32* %2
288 ; CHECK: add x0, x0, #1, lsl #12
289 ; CHECK-NEXT: ldg x0, [x0]
292 define i32* @get_tag4stack() {
293 entry:
294 ; CHECK-LABEL: get_tag4stack:
295   %s = alloca %struct.S8K, align 4
296   %0 = bitcast %struct.S8K* %s to i8*
297   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
298   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 1024
299   %1 = bitcast i32* %arrayidx to i8*
300   %2 = call i8* @llvm.aarch64.ldg(i8* nonnull %1, i8* nonnull %1)
301   %3 = bitcast i8* %2 to i32*
302   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
303   ret i32* %3
304 ; CHECK: mov [[T0:x[0-9]+]], sp
305 ; CHECK-NEXT: add x[[T1:[0-9]+]], [[T0]], #1, lsl #12
306 ; CHECK-NEXT: ldg x[[T1]], [x[[T1]]]
309 define i32* @get_tag5(i32* %ptr) {
310 entry:
311 ; CHECK-LABEL: get_tag5:
312   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 5
313   %0 = bitcast i32* %add.ptr to i8*
314   %1 = tail call i8* @llvm.aarch64.ldg(i8* nonnull %0, i8* nonnull %0)
315   %2 = bitcast i8* %1 to i32*
316   ret i32* %2
317 ; CHECK: add x0, x0, #20
318 ; CHECK-NEXT: ldg x0, [x0]
321 define i32* @get_tag5stack() {
322 entry:
323 ; CHECK-LABEL: get_tag5stack:
324   %s = alloca %struct.S8K, align 4
325   %0 = bitcast %struct.S8K* %s to i8*
326   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
327   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 5
328   %1 = bitcast i32* %arrayidx to i8*
329   %2 = call i8* @llvm.aarch64.ldg(i8* nonnull %1, i8* nonnull %1)
330   %3 = bitcast i8* %2 to i32*
331   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
332   ret i32* %3
333 ; CHECK: mov [[T0:x[0-9]+]], sp
334 ; CHECK: add x[[T1:[0-9]+]], [[T0]], #20
335 ; CHECK-NEXT: ldg x[[T1]], [x[[T1]]]
339 ; *********** __arm_mte_set_tag  *************
340 define void @set_tag1(i32* %tag, i32* %ptr) {
341 entry:
342 ; CHECK-LABEL: set_tag1:
343   %0 = bitcast i32* %tag to i8*
344   %1 = bitcast i32* %ptr to i8*
345   tail call void @llvm.aarch64.stg(i8* %0, i8* %1)
346   ret void
347 ; CHECK: stg x0, [x1]
350 define void @set_tag1stack(i32* %tag) {
351 entry:
352 ; CHECK-LABEL: set_tag1stack:
353   %s = alloca %struct.S8K, align 4
354   %0 = bitcast i32* %tag to i8*
355   %1 = bitcast %struct.S8K* %s to i8*
356   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %1)
357   call void @llvm.aarch64.stg(i8* %0, i8* nonnull %1)
358   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
359   ret void
360 ; CHECK: stg x0, [sp]
364 define void @set_tag2(i32* %tag, i32* %ptr) {
365 entry:
366 ; CHECK-LABEL: set_tag2:
367   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 4
368   %0 = bitcast i32* %tag to i8*
369   %1 = bitcast i32* %add.ptr to i8*
370   tail call void @llvm.aarch64.stg(i8* %0, i8* %1)
371   ret void
372 ; CHECK: stg x0, [x1, #16]
375 define void @set_tag2stack(i32* %tag, i32* %ptr) {
376 entry:
377 ; CHECK-LABEL: set_tag2stack:
378   %s = alloca %struct.S8K, align 4
379   %0 = bitcast %struct.S8K* %s to i8*
380   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
381   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 4
382   %1 = bitcast i32* %arrayidx to i8*
383   %2 = bitcast i32* %tag to i8*
384   call void @llvm.aarch64.stg(i8* %2, i8* nonnull %1)
385   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
386   ret void
387 ; CHECK: stg x0, [sp, #16]
392 define void @set_tag3(i32* %tag, i32* %ptr) {
393 entry:
394 ; CHECK-LABEL: set_tag3:
395   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 1020
396   %0 = bitcast i32* %add.ptr to i8*
397   %1 = bitcast i32* %tag to i8*
398   tail call void @llvm.aarch64.stg(i8* %1, i8* %0)
399   ret void
400 ; CHECK: stg x0, [x1, #4080]
403 define void @set_tag3stack(i32* %tag, i32* %ptr) {
404 entry:
405 ; CHECK-LABEL: set_tag3stack:
406   %s = alloca %struct.S8K, align 4
407   %0 = bitcast %struct.S8K* %s to i8*
408   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
409   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 1020
410   %1 = bitcast i32* %arrayidx to i8*
411   %2 = bitcast i32* %tag to i8*
412   call void @llvm.aarch64.stg(i8* %2, i8* nonnull %1)
413   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
414   ret void
415 ; CHECK: stg x0, [sp, #4080]
420 define void @set_tag4(i32* %tag, i32* %ptr) {
421 entry:
422 ; CHECK-LABEL: set_tag4:
423   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 1024
424   %0 = bitcast i32* %add.ptr to i8*
425   %1 = bitcast i32* %tag to i8*
426   tail call void @llvm.aarch64.stg(i8* %1, i8* %0)
427   ret void
428 ; CHECK: add x[[T0:[0-9]+]], x1, #1, lsl #12
429 ; CHECK-NEXT: stg x0, [x[[T0]]]
432 define void @set_tag4stack(i32* %tag, i32* %ptr) {
433 entry:
434 ; CHECK-LABEL: set_tag4stack:
435   %s = alloca %struct.S8K, align 4
436   %0 = bitcast %struct.S8K* %s to i8*
437   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
438   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 1024
439   %1 = bitcast i32* %arrayidx to i8*
440   %2 = bitcast i32* %tag to i8*
441   call void @llvm.aarch64.stg(i8* %2, i8* nonnull %1)
442   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
443   ret void
444 ; CHECK: add x[[T0:[0-9]+]], {{.*}}, #1, lsl #12
445 ; CHECK-NEXT: stg x0, [x[[T0]]]
449 define void @set_tag5(i32* %tag, i32* %ptr) {
450 entry:
451 ; CHECK-LABEL: set_tag5:
452   %add.ptr = getelementptr inbounds i32, i32* %ptr, i64 5
453   %0 = bitcast i32* %add.ptr to i8*
454   %1 = bitcast i32* %tag to i8*
455   tail call void @llvm.aarch64.stg(i8* %1, i8* %0)
456   ret void
457 ; CHECK: add x[[T0:[0-9]+]], x1, #20
458 ; CHECK-NEXT: stg x0, [x[[T0]]]
461 define void @set_tag5stack(i32* %tag, i32* %ptr) {
462 entry:
463 ; CHECK-LABEL: set_tag5stack:
464   %s = alloca %struct.S8K, align 4
465   %0 = bitcast %struct.S8K* %s to i8*
466   call void @llvm.lifetime.start.p0i8(i64 8192, i8* nonnull %0)
467   %arrayidx = getelementptr inbounds %struct.S8K, %struct.S8K* %s, i64 0, i32 0, i64 5
468   %1 = bitcast i32* %arrayidx to i8*
469   %2 = bitcast i32* %tag to i8*
470   call void @llvm.aarch64.stg(i8* %2, i8* nonnull %1)
471   call void @llvm.lifetime.end.p0i8(i64 8192, i8* nonnull %0)
472   ret void
473 ; CHECK: add x[[T0:[0-9]+]], {{.*}}, #20
474 ; CHECK-NEXT: stg x0, [x[[T0]]]
478 ; *********** __arm_mte_ptrdiff  *************
479 define i64 @subtract_pointers(i32* %ptra, i32* %ptrb) {
480 entry:
481 ; CHECK-LABEL: subtract_pointers:
482   %0 = bitcast i32* %ptra to i8*
483   %1 = bitcast i32* %ptrb to i8*
484   %2 = tail call i64 @llvm.aarch64.subp(i8* %0, i8* %1)
485   ret i64 %2
486 ; CHECK: subp x0, x0, x1
489 declare i8* @llvm.aarch64.irg(i8*, i64)
490 declare i8* @llvm.aarch64.addg(i8*, i64)
491 declare i64 @llvm.aarch64.gmi(i8*, i64)
492 declare i8* @llvm.aarch64.ldg(i8*, i8*)
493 declare void @llvm.aarch64.stg(i8*, i8*)
494 declare i64 @llvm.aarch64.subp(i8*, i8*)
496 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
497 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)