1; RUN: opt -S -analyze -stack-safety-local < %s | FileCheck %s --check-prefixes=CHECK,LOCAL 2; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL 3; RUN: opt -S -analyze -stack-safety < %s | FileCheck %s --check-prefixes=CHECK,GLOBAL 4; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL 5 6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 7target triple = "x86_64-unknown-linux-gnu" 8 9@sink = global i8* null, align 8 10 11declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile) 12declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 13declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 14 15; Address leaked. 16define void @LeakAddress() { 17; CHECK-LABEL: @LeakAddress dso_preemptable{{$}} 18; CHECK-NEXT: args uses: 19; CHECK-NEXT: allocas uses: 20; CHECK-NEXT: x[4]: full-set{{$}} 21; CHECK-NOT: ]: 22entry: 23 %x = alloca i32, align 4 24 %x1 = bitcast i32* %x to i8* 25 store i8* %x1, i8** @sink, align 8 26 ret void 27} 28 29define void @StoreInBounds() { 30; CHECK-LABEL: @StoreInBounds dso_preemptable{{$}} 31; CHECK-NEXT: args uses: 32; CHECK-NEXT: allocas uses: 33; CHECK-NEXT: x[4]: [0,1){{$}} 34; CHECK-NOT: ]: 35entry: 36 %x = alloca i32, align 4 37 %x1 = bitcast i32* %x to i8* 38 store i8 0, i8* %x1, align 1 39 ret void 40} 41 42define void @StoreInBounds2() { 43; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}} 44; CHECK-NEXT: args uses: 45; CHECK-NEXT: allocas uses: 46; CHECK-NEXT: x[4]: [0,4){{$}} 47; CHECK-NOT: ]: 48entry: 49 %x = alloca i32, align 4 50 store i32 0, i32* %x, align 4 51 ret void 52} 53 54define void @StoreInBounds3() { 55; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}} 56; CHECK-NEXT: args uses: 57; CHECK-NEXT: allocas uses: 58; CHECK-NEXT: x[4]: [2,3){{$}} 59; CHECK-NOT: ]: 60entry: 61 %x = alloca i32, align 4 62 %x1 = bitcast i32* %x to i8* 63 %x2 = getelementptr i8, i8* %x1, i64 2 64 store i8 0, i8* %x2, align 1 65 ret void 66} 67 68; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr. 69define void @StoreInBounds4() { 70; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}} 71; CHECK-NEXT: args uses: 72; CHECK-NEXT: allocas uses: 73; CHECK-NEXT: x[4]: [-9223372036854775808,9223372036854775807){{$}} 74; CHECK-NOT: ]: 75entry: 76 %x = alloca i32, align 4 77 %x1 = ptrtoint i32* %x to i64 78 %x2 = add i64 %x1, 2 79 %x3 = inttoptr i64 %x2 to i8* 80 store i8 0, i8* %x3, align 1 81 ret void 82} 83 84define void @StoreOutOfBounds() { 85; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}} 86; CHECK-NEXT: args uses: 87; CHECK-NEXT: allocas uses: 88; CHECK-NEXT: x[4]: [2,6){{$}} 89; CHECK-NOT: ]: 90entry: 91 %x = alloca i32, align 4 92 %x1 = bitcast i32* %x to i8* 93 %x2 = getelementptr i8, i8* %x1, i64 2 94 %x3 = bitcast i8* %x2 to i32* 95 store i32 0, i32* %x3, align 1 96 ret void 97} 98 99; There is no difference in load vs store handling. 100define void @LoadInBounds() { 101; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}} 102; CHECK-NEXT: args uses: 103; CHECK-NEXT: allocas uses: 104; CHECK-NEXT: x[4]: [0,1){{$}} 105; CHECK-NOT: ]: 106entry: 107 %x = alloca i32, align 4 108 %x1 = bitcast i32* %x to i8* 109 %v = load i8, i8* %x1, align 1 110 ret void 111} 112 113define void @LoadOutOfBounds() { 114; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}} 115; CHECK-NEXT: args uses: 116; CHECK-NEXT: allocas uses: 117; CHECK-NEXT: x[4]: [2,6){{$}} 118; CHECK-NOT: ]: 119entry: 120 %x = alloca i32, align 4 121 %x1 = bitcast i32* %x to i8* 122 %x2 = getelementptr i8, i8* %x1, i64 2 123 %x3 = bitcast i8* %x2 to i32* 124 %v = load i32, i32* %x3, align 1 125 ret void 126} 127 128; Leak through ret. 129define i8* @Ret() { 130; CHECK-LABEL: @Ret dso_preemptable{{$}} 131; CHECK-NEXT: args uses: 132; CHECK-NEXT: allocas uses: 133; CHECK-NEXT: x[4]: full-set{{$}} 134; CHECK-NOT: ]: 135entry: 136 %x = alloca i32, align 4 137 %x1 = bitcast i32* %x to i8* 138 %x2 = getelementptr i8, i8* %x1, i64 2 139 ret i8* %x2 140} 141 142declare void @Foo(i16* %p) 143 144define void @DirectCall() { 145; CHECK-LABEL: @DirectCall dso_preemptable{{$}} 146; CHECK-NEXT: args uses: 147; CHECK-NEXT: allocas uses: 148; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}} 149; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}} 150; CHECK-NOT: ]: 151entry: 152 %x = alloca i64, align 4 153 %x1 = bitcast i64* %x to i16* 154 %x2 = getelementptr i16, i16* %x1, i64 1 155 call void @Foo(i16* %x2); 156 ret void 157} 158 159; Indirect calls can not be analyzed (yet). 160; FIXME: %p[]: full-set looks invalid 161define void @IndirectCall(void (i8*)* %p) { 162; CHECK-LABEL: @IndirectCall dso_preemptable{{$}} 163; CHECK-NEXT: args uses: 164; CHECK-NEXT: p[]: full-set{{$}} 165; CHECK-NEXT: allocas uses: 166; CHECK-NEXT: x[4]: full-set{{$}} 167; CHECK-NOT: ]: 168entry: 169 %x = alloca i32, align 4 170 %x1 = bitcast i32* %x to i8* 171 call void %p(i8* %x1); 172 ret void 173} 174 175define void @NonConstantOffset(i1 zeroext %z) { 176; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}} 177; CHECK-NEXT: args uses: 178; CHECK-NEXT: allocas uses: 179; FIXME: SCEV can't look through selects. 180; CHECK-NEXT: x[4]: [-4,4){{$}} 181; CHECK-NOT: ]: 182entry: 183 %x = alloca i32, align 4 184 %x1 = bitcast i32* %x to i8* 185 %idx = select i1 %z, i64 1, i64 2 186 %x2 = getelementptr i8, i8* %x1, i64 %idx 187 store i8 0, i8* %x2, align 1 188 ret void 189} 190 191define void @NegativeOffset() { 192; CHECK-LABEL: @NegativeOffset dso_preemptable{{$}} 193; CHECK-NEXT: args uses: 194; CHECK-NEXT: allocas uses: 195; CHECK-NEXT: x[40]: [-1600000000000,-1599999999996){{$}} 196; CHECK-NOT: ]: 197entry: 198 %x = alloca i32, i32 10, align 4 199 %x2 = getelementptr i32, i32* %x, i64 -400000000000 200 store i32 0, i32* %x2, align 1 201 ret void 202} 203 204define void @PossiblyNegativeOffset(i16 %z) { 205; CHECK-LABEL: @PossiblyNegativeOffset dso_preemptable{{$}} 206; CHECK-NEXT: args uses: 207; CHECK-NEXT: allocas uses: 208; CHECK-NEXT: x[40]: [-131072,131072){{$}} 209; CHECK-NOT: ]: 210entry: 211 %x = alloca i32, i32 10, align 4 212 %x2 = getelementptr i32, i32* %x, i16 %z 213 store i32 0, i32* %x2, align 1 214 ret void 215} 216 217define void @NonConstantOffsetOOB(i1 zeroext %z) { 218; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}} 219; CHECK-NEXT: args uses: 220; CHECK-NEXT: allocas uses: 221; CHECK-NEXT: x[4]: [-8,8){{$}} 222; CHECK-NOT: ]: 223entry: 224 %x = alloca i32, align 4 225 %x1 = bitcast i32* %x to i8* 226 %idx = select i1 %z, i64 1, i64 4 227 %x2 = getelementptr i8, i8* %x1, i64 %idx 228 store i8 0, i8* %x2, align 1 229 ret void 230} 231 232define void @ArrayAlloca() { 233; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}} 234; CHECK-NEXT: args uses: 235; CHECK-NEXT: allocas uses: 236; CHECK-NEXT: x[40]: [36,40){{$}} 237; CHECK-NOT: ]: 238entry: 239 %x = alloca i32, i32 10, align 4 240 %x1 = bitcast i32* %x to i8* 241 %x2 = getelementptr i8, i8* %x1, i64 36 242 %x3 = bitcast i8* %x2 to i32* 243 store i32 0, i32* %x3, align 1 244 ret void 245} 246 247define void @ArrayAllocaOOB() { 248; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}} 249; CHECK-NEXT: args uses: 250; CHECK-NEXT: allocas uses: 251; CHECK-NEXT: x[40]: [37,41){{$}} 252; CHECK-NOT: ]: 253entry: 254 %x = alloca i32, i32 10, align 4 255 %x1 = bitcast i32* %x to i8* 256 %x2 = getelementptr i8, i8* %x1, i64 37 257 %x3 = bitcast i8* %x2 to i32* 258 store i32 0, i32* %x3, align 1 259 ret void 260} 261 262define void @DynamicAllocaUnused(i64 %size) { 263; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}} 264; CHECK-NEXT: args uses: 265; CHECK-NEXT: allocas uses: 266; CHECK-NEXT: x[0]: empty-set{{$}} 267; CHECK-NOT: ]: 268entry: 269 %x = alloca i32, i64 %size, align 16 270 ret void 271} 272 273; Dynamic alloca with unknown size. 274define void @DynamicAlloca(i64 %size) { 275; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}} 276; CHECK-NEXT: args uses: 277; CHECK-NEXT: allocas uses: 278; CHECK-NEXT: x[0]: [0,4){{$}} 279; CHECK-NOT: ]: 280entry: 281 %x = alloca i32, i64 %size, align 16 282 store i32 0, i32* %x, align 1 283 ret void 284} 285 286; Dynamic alloca with limited size. 287; FIXME: could be proved safe. Implement. 288define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) { 289; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}} 290; CHECK-NEXT: args uses: 291; CHECK-NEXT: allocas uses: 292; CHECK-NEXT: x[0]: [0,4){{$}} 293; CHECK-NOT: ]: 294entry: 295 %size = select i1 %z, i64 3, i64 5 296 %x = alloca i32, i64 %size, align 16 297 store i32 0, i32* %x, align 1 298 ret void 299} 300 301define signext i8 @SimpleLoop() { 302; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}} 303; CHECK-NEXT: args uses: 304; CHECK-NEXT: allocas uses: 305; CHECK-NEXT: x[10]: [0,10){{$}} 306; CHECK-NOT: ]: 307entry: 308 %x = alloca [10 x i8], align 1 309 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0 310 %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 10 311 br label %for.body 312 313for.body: 314 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ] 315 %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ] 316 %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1 317 %1 = load volatile i8, i8* %p.09, align 1 318 %add = add i8 %1, %sum.010 319 %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit 320 br i1 %exitcond, label %for.cond.cleanup, label %for.body 321 322for.cond.cleanup: 323 ret i8 %add 324} 325 326; OOB in a loop. 327define signext i8 @SimpleLoopOOB() { 328; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}} 329; CHECK-NEXT: args uses: 330; CHECK-NEXT: allocas uses: 331; CHECK-NEXT: x[10]: [0,11){{$}} 332; CHECK-NOT: ]: 333entry: 334 %x = alloca [10 x i8], align 1 335 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0 336 ; 11 iterations 337 %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 11 338 br label %for.body 339 340for.body: 341 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ] 342 %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ] 343 %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1 344 %1 = load volatile i8, i8* %p.09, align 1 345 %add = add i8 %1, %sum.010 346 %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit 347 br i1 %exitcond, label %for.cond.cleanup, label %for.body 348 349for.cond.cleanup: 350 ret i8 %add 351} 352 353define dso_local void @SizeCheck(i32 %sz) { 354; CHECK-LABEL: @SizeCheck{{$}} 355; CHECK-NEXT: args uses: 356; CHECK-NEXT: allocas uses: 357; CHECK-NEXT: x1[128]: [0,4294967295){{$}} 358; CHECK-NOT: ]: 359entry: 360 %x1 = alloca [128 x i8], align 16 361 %x1.sub = getelementptr inbounds [128 x i8], [128 x i8]* %x1, i64 0, i64 0 362 %cmp = icmp slt i32 %sz, 129 363 br i1 %cmp, label %if.then, label %if.end 364 365if.then: 366 call void @llvm.memset.p0i8.i32(i8* nonnull align 16 %x1.sub, i8 0, i32 %sz, i1 false) 367 br label %if.end 368 369if.end: 370 ret void 371} 372 373; FIXME: scalable allocas are considered to be of size zero, and scalable accesses to be full-range. 374; This effectively disables safety analysis for scalable allocations. 375define void @Scalable(<vscale x 4 x i32>* %p, <vscale x 4 x i32>* %unused, <vscale x 4 x i32> %v) { 376; CHECK-LABEL: @Scalable dso_preemptable{{$}} 377; CHECK-NEXT: args uses: 378; CHECK-NEXT: p[]: full-set 379; CHECK-NEXT: unused[]: empty-set 380; CHECK-NEXT: allocas uses: 381; CHECK-NEXT: x[0]: [0,1){{$}} 382; CHECK-NOT: ]: 383entry: 384 %x = alloca <vscale x 4 x i32>, align 4 385 %x1 = bitcast <vscale x 4 x i32>* %x to i8* 386 store i8 0, i8* %x1, align 1 387 store <vscale x 4 x i32> %v, <vscale x 4 x i32>* %p, align 4 388 ret void 389} 390 391%zerosize_type = type {} 392 393define void @ZeroSize(%zerosize_type *%p) { 394; CHECK-LABEL: @ZeroSize dso_preemptable{{$}} 395; CHECK-NEXT: args uses: 396; CHECK-NEXT: p[]: empty-set 397; CHECK-NEXT: allocas uses: 398; CHECK-NEXT: x[0]: empty-set 399; CHECK-NOT: ]: 400entry: 401 %x = alloca %zerosize_type, align 4 402 store %zerosize_type undef, %zerosize_type* %x, align 4 403 store %zerosize_type undef, %zerosize_type* undef, align 4 404 %val = load %zerosize_type, %zerosize_type* %p, align 4 405 ret void 406} 407 408define void @OperandBundle() { 409; CHECK-LABEL: @OperandBundle dso_preemptable{{$}} 410; CHECK-NEXT: args uses: 411; CHECK-NEXT: allocas uses: 412; CHECK-NEXT: a[4]: full-set 413; CHECK-NOT: ]: 414entry: 415 %a = alloca i32, align 4 416 call void @LeakAddress() ["unknown"(i32* %a)] 417 ret void 418} 419 420define void @ByVal(i16* byval %p) { 421 ; CHECK-LABEL: @ByVal dso_preemptable{{$}} 422 ; CHECK-NEXT: args uses: 423 ; CHECK-NEXT: allocas uses: 424 ; CHECK-NOT: ]: 425entry: 426 ret void 427} 428 429define void @TestByVal() { 430; CHECK-LABEL: @TestByVal dso_preemptable{{$}} 431; CHECK-NEXT: args uses: 432; CHECK-NEXT: allocas uses: 433; CHECK-NEXT: x[2]: [0,2) 434; CHECK-NEXT: y[8]: [0,2) 435; CHECK-NOT: ]: 436entry: 437 %x = alloca i16, align 4 438 call void @ByVal(i16* byval %x) 439 440 %y = alloca i64, align 4 441 %y1 = bitcast i64* %y to i16* 442 call void @ByVal(i16* byval %y1) 443 444 ret void 445} 446 447declare void @ByValArray([100000 x i64]* byval %p) 448 449define void @TestByValArray() { 450; CHECK-LABEL: @TestByValArray dso_preemptable{{$}} 451; CHECK-NEXT: args uses: 452; CHECK-NEXT: allocas uses: 453; CHECK-NEXT: z[800000]: [500000,1300000) 454; CHECK-NOT: ]: 455entry: 456 %z = alloca [100000 x i64], align 4 457 %z1 = bitcast [100000 x i64]* %z to i8* 458 %z2 = getelementptr i8, i8* %z1, i64 500000 459 %z3 = bitcast i8* %z2 to [100000 x i64]* 460 call void @ByValArray([100000 x i64]* byval %z3) 461 ret void 462} 463 464define dso_local i8 @LoadMinInt64(i8* %p) { 465 ; CHECK-LABEL: @LoadMinInt64{{$}} 466 ; CHECK-NEXT: args uses: 467 ; CHECK-NEXT: p[]: [-9223372036854775808,-9223372036854775807){{$}} 468 ; CHECK-NEXT: allocas uses: 469 ; CHECK-NOT: ]: 470 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775808 471 %v = load i8, i8* %p2, align 1 472 ret i8 %v 473} 474 475define void @Overflow() { 476; CHECK-LABEL: @Overflow dso_preemptable{{$}} 477; CHECK-NEXT: args uses: 478; CHECK-NEXT: allocas uses: 479; LOCAL-NEXT: x[1]: empty-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}} 480; GLOBAL-NEXT: x[1]: full-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}} 481; CHECK-NOT: ]: 482entry: 483 %x = alloca i8, align 4 484 %x2 = getelementptr i8, i8* %x, i64 -9223372036854775808 485 %v = call i8 @LoadMinInt64(i8* %x2) 486 ret void 487} 488 489define void @DeadBlock(i64* %p) { 490; CHECK-LABEL: @DeadBlock dso_preemptable{{$}} 491; CHECK-NEXT: args uses: 492; CHECK-NEXT: p[]: empty-set{{$}} 493; CHECK-NEXT: allocas uses: 494; CHECK-NEXT: x[1]: empty-set{{$}} 495; CHECK-NOT: ]: 496entry: 497 %x = alloca i8, align 4 498 br label %end 499 500dead: 501 store i8 5, i8* %x 502 store i64 -5, i64* %p 503 br label %end 504 505end: 506 ret void 507} 508 509define void @LifeNotStarted() { 510; CHECK-LABEL: @LifeNotStarted dso_preemptable{{$}} 511; CHECK-NEXT: args uses: 512; CHECK-NEXT: allocas uses: 513; CHECK: x[1]: full-set{{$}} 514; CHECK: y[1]: full-set{{$}} 515; CHECK: z[1]: full-set{{$}} 516; CHECK-NOT: ]: 517entry: 518 %x = alloca i8, align 4 519 %y = alloca i8, align 4 520 %z = alloca i8, align 4 521 522 store i8 5, i8* %x 523 %n = load i8, i8* %y 524 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 525 526 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) 527 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) 528 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z) 529 530 ret void 531} 532 533define void @LifeOK() { 534; CHECK-LABEL: @LifeOK dso_preemptable{{$}} 535; CHECK-NEXT: args uses: 536; CHECK-NEXT: allocas uses: 537; CHECK: x[1]: [0,1){{$}} 538; CHECK: y[1]: [0,1){{$}} 539; CHECK: z[1]: [0,1){{$}} 540; CHECK-NOT: ]: 541entry: 542 %x = alloca i8, align 4 543 %y = alloca i8, align 4 544 %z = alloca i8, align 4 545 546 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) 547 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) 548 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z) 549 550 store i8 5, i8* %x 551 %n = load i8, i8* %y 552 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 553 554 ret void 555} 556 557define void @LifeEnded() { 558; CHECK-LABEL: @LifeEnded dso_preemptable{{$}} 559; CHECK-NEXT: args uses: 560; CHECK-NEXT: allocas uses: 561; CHECK: x[1]: full-set{{$}} 562; CHECK: y[1]: full-set{{$}} 563; CHECK: z[1]: full-set{{$}} 564; CHECK-NOT: ]: 565entry: 566 %x = alloca i8, align 4 567 %y = alloca i8, align 4 568 %z = alloca i8, align 4 569 570 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) 571 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) 572 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z) 573 574 call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) 575 call void @llvm.lifetime.end.p0i8(i64 1, i8* %y) 576 call void @llvm.lifetime.end.p0i8(i64 1, i8* %z) 577 578 store i8 5, i8* %x 579 %n = load i8, i8* %y 580 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 581 582 ret void 583} 584 585declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) 586declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)