1; RUN: llc < %s -mtriple=aarch64 -mattr=+mte | FileCheck %s
2
3define void @stg1(i8* %p) {
4entry:
5; CHECK-LABEL: stg1:
6; CHECK: stg x0, [x0]
7; CHECK: ret
8  call void @llvm.aarch64.settag(i8* %p, i64 16)
9  ret void
10}
11
12define void @stg2(i8* %p) {
13entry:
14; CHECK-LABEL: stg2:
15; CHECK: st2g x0, [x0]
16; CHECK: ret
17  call void @llvm.aarch64.settag(i8* %p, i64 32)
18  ret void
19}
20
21define void @stg3(i8* %p) {
22entry:
23; CHECK-LABEL: stg3:
24; CHECK: stg  x0, [x0, #32]
25; CHECK: st2g x0, [x0]
26; CHECK: ret
27  call void @llvm.aarch64.settag(i8* %p, i64 48)
28  ret void
29}
30
31define void @stg4(i8* %p) {
32entry:
33; CHECK-LABEL: stg4:
34; CHECK: st2g x0, [x0, #32]
35; CHECK: st2g x0, [x0]
36; CHECK: ret
37  call void @llvm.aarch64.settag(i8* %p, i64 64)
38  ret void
39}
40
41define void @stg5(i8* %p) {
42entry:
43; CHECK-LABEL: stg5:
44; CHECK: stg  x0, [x0, #64]
45; CHECK: st2g x0, [x0, #32]
46; CHECK: st2g x0, [x0]
47; CHECK: ret
48  call void @llvm.aarch64.settag(i8* %p, i64 80)
49  ret void
50}
51
52define void @stg16(i8* %p) {
53entry:
54; CHECK-LABEL: stg16:
55; CHECK: mov  {{(w|x)}}[[R:[0-9]+]], #256
56; CHECK: st2g x0, [x0], #32
57; CHECK: sub  x[[R]], x[[R]], #32
58; CHECK: cbnz x[[R]],
59; CHECK: ret
60  call void @llvm.aarch64.settag(i8* %p, i64 256)
61  ret void
62}
63
64define void @stg17(i8* %p) {
65entry:
66; CHECK-LABEL: stg17:
67; CHECK: stg x0, [x0], #16
68; CHECK: mov  {{(w|x)}}[[R:[0-9]+]], #256
69; CHECK: st2g x0, [x0], #32
70; CHECK: sub  x[[R]], x[[R]], #32
71; CHECK: cbnz x[[R]],
72; CHECK: ret
73  call void @llvm.aarch64.settag(i8* %p, i64 272)
74  ret void
75}
76
77define void @stzg3(i8* %p) {
78entry:
79; CHECK-LABEL: stzg3:
80; CHECK: stzg  x0, [x0, #32]
81; CHECK: stz2g x0, [x0]
82; CHECK: ret
83  call void @llvm.aarch64.settag.zero(i8* %p, i64 48)
84  ret void
85}
86
87define void @stzg17(i8* %p) {
88entry:
89; CHECK-LABEL: stzg17:
90; CHECK: stzg x0, [x0], #16
91; CHECK: mov  {{w|x}}[[R:[0-9]+]], #256
92; CHECK: stz2g x0, [x0], #32
93; CHECK: sub  x[[R]], x[[R]], #32
94; CHECK: cbnz x[[R]],
95; CHECK: ret
96  call void @llvm.aarch64.settag.zero(i8* %p, i64 272)
97  ret void
98}
99
100define void @stg_alloca1() {
101entry:
102; CHECK-LABEL: stg_alloca1:
103; CHECK: stg sp, [sp]
104; CHECK: ret
105  %a = alloca i8, i32 16, align 16
106  call void @llvm.aarch64.settag(i8* %a, i64 16)
107  ret void
108}
109
110define void @stg_alloca5() {
111entry:
112; CHECK-LABEL: stg_alloca5:
113; CHECK:         st2g    sp, [sp, #32]
114; CHECK-NEXT:    stg     sp, [sp, #64]
115; CHECK-NEXT:    st2g    sp, [sp], #80
116; CHECK-NEXT:    ret
117  %a = alloca i8, i32 80, align 16
118  call void @llvm.aarch64.settag(i8* %a, i64 80)
119  ret void
120}
121
122define void @stg_alloca17() {
123entry:
124; CHECK-LABEL: stg_alloca17:
125; CHECK: mov  {{w|x}}[[R:[0-9]+]], #256
126; CHECK: st2g sp, [sp], #32
127; CHECK: sub  x[[R]], x[[R]], #32
128; CHECK: cbnz x[[R]],
129; CHECK: stg sp, [sp], #16
130; CHECK: ret
131  %a = alloca i8, i32 272, align 16
132  call void @llvm.aarch64.settag(i8* %a, i64 272)
133  ret void
134}
135
136declare void @llvm.aarch64.settag(i8* %p, i64 %a)
137declare void @llvm.aarch64.settag.zero(i8* %p, i64 %a)
138