1; RUN: llc < %s -mtriple=arm64-eabi -mattr=+mte | FileCheck %s 2 3; test create_tag 4define i32* @create_tag(i32* %ptr, i32 %m) { 5entry: 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]+}} 13} 14 15; *********** __arm_mte_increment_tag ************* 16; test increment_tag1 17define i32* @increment_tag1(i32* %ptr) { 18entry: 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 25} 26 27%struct.S2K = type { [512 x i32] } 28define i32* @increment_tag1stack(i32* %ptr) { 29entry: 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 39} 40 41 42define i32* @increment_tag2(i32* %ptr) { 43entry: 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 51} 52 53define i32* @increment_tag2stack(i32* %ptr) { 54entry: 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 66} 67 68define i32* @increment_tag3(i32* %ptr) { 69entry: 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 77} 78 79define i32* @increment_tag3stack(i32* %ptr) { 80entry: 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 92} 93 94 95define i32* @increment_tag4(i32* %ptr) { 96entry: 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 105} 106 107define i32* @increment_tag4stack(i32* %ptr) { 108entry: 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 121} 122 123 124define i32* @increment_tag5(i32* %ptr) { 125entry: 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 134} 135 136define i32* @increment_tag5stack(i32* %ptr) { 137entry: 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 150} 151 152 153; *********** __arm_mte_exclude_tag ************* 154; test exclude_tag 155define i32 @exclude_tag(i32* %ptr, i32 %m) local_unnamed_addr #0 { 156entry: 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]+}} 164} 165 166 167; *********** __arm_mte_get_tag ************* 168%struct.S8K = type { [2048 x i32] } 169define i32* @get_tag1(i32* %ptr) { 170entry: 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] 177} 178 179define i32* @get_tag1_two_parm(i32* %ret_ptr, i32* %ptr) { 180entry: 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] 188} 189 190define i32* @get_tag1stack() { 191entry: 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] 202} 203 204define i32* @get_tag1stack_two_param(i32* %ret_ptr) { 205entry: 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] 217} 218 219 220define i32* @get_tag2(i32* %ptr) { 221entry: 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] 230} 231 232define i32* @get_tag2stack() { 233entry: 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] 247} 248 249 250define i32* @get_tag3(i32* %ptr) { 251entry: 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] 260} 261 262define i32* @get_tag3stack() { 263entry: 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] 277} 278 279 280define i32* @get_tag4(i32* %ptr) { 281entry: 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] 290} 291 292define i32* @get_tag4stack() { 293entry: 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]]] 307} 308 309define i32* @get_tag5(i32* %ptr) { 310entry: 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] 319} 320 321define i32* @get_tag5stack() { 322entry: 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]]] 336} 337 338 339; *********** __arm_mte_set_tag ************* 340define void @set_tag1(i32* %tag, i32* %ptr) { 341entry: 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] 348} 349 350define void @set_tag1stack(i32* %tag) { 351entry: 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] 361} 362 363 364define void @set_tag2(i32* %tag, i32* %ptr) { 365entry: 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] 373} 374 375define void @set_tag2stack(i32* %tag, i32* %ptr) { 376entry: 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] 388} 389 390 391 392define void @set_tag3(i32* %tag, i32* %ptr) { 393entry: 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] 401} 402 403define void @set_tag3stack(i32* %tag, i32* %ptr) { 404entry: 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] 416} 417 418 419 420define void @set_tag4(i32* %tag, i32* %ptr) { 421entry: 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]]] 430} 431 432define void @set_tag4stack(i32* %tag, i32* %ptr) { 433entry: 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]]] 446} 447 448 449define void @set_tag5(i32* %tag, i32* %ptr) { 450entry: 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]]] 459} 460 461define void @set_tag5stack(i32* %tag, i32* %ptr) { 462entry: 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]]] 475} 476 477 478; *********** __arm_mte_ptrdiff ************* 479define i64 @subtract_pointers(i32* %ptra, i32* %ptrb) { 480entry: 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 487} 488 489declare i8* @llvm.aarch64.irg(i8*, i64) 490declare i8* @llvm.aarch64.addg(i8*, i64) 491declare i64 @llvm.aarch64.gmi(i8*, i64) 492declare i8* @llvm.aarch64.ldg(i8*, i8*) 493declare void @llvm.aarch64.stg(i8*, i8*) 494declare i64 @llvm.aarch64.subp(i8*, i8*) 495 496declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) 497declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) 498