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