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