1; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL 2; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL 3 4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7@sink = global i8* null, align 8 8 9declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile) 10declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 11declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 12declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile) 13 14declare void @unknown_call(i8* %dest) 15declare i8* @retptr(i8* returned) 16 17; Address leaked. 18define void @LeakAddress() { 19; CHECK-LABEL: @LeakAddress dso_preemptable{{$}} 20; CHECK-NEXT: args uses: 21; CHECK-NEXT: allocas uses: 22; CHECK-NEXT: x[4]: full-set{{$}} 23; GLOBAL-NEXT: safe accesses: 24; CHECK-EMPTY: 25entry: 26 %x = alloca i32, align 4 27 %x1 = bitcast i32* %x to i8* 28 store i8* %x1, i8** @sink, align 8 29 ret void 30} 31 32define void @StoreInBounds() { 33; CHECK-LABEL: @StoreInBounds dso_preemptable{{$}} 34; CHECK-NEXT: args uses: 35; CHECK-NEXT: allocas uses: 36; CHECK-NEXT: x[4]: [0,1){{$}} 37; GLOBAL-NEXT: safe accesses: 38; GLOBAL-NEXT: store i8 0, i8* %x1, align 1 39; CHECK-EMPTY: 40entry: 41 %x = alloca i32, align 4 42 %x1 = bitcast i32* %x to i8* 43 store i8 0, i8* %x1, align 1 44 ret void 45} 46 47define void @StoreInBounds2() { 48; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}} 49; CHECK-NEXT: args uses: 50; CHECK-NEXT: allocas uses: 51; CHECK-NEXT: x[4]: [0,4){{$}} 52; GLOBAL-NEXT: safe accesses: 53; GLOBAL-NEXT: store i32 0, i32* %x, align 4 54; CHECK-EMPTY: 55entry: 56 %x = alloca i32, align 4 57 store i32 0, i32* %x, align 4 58 ret void 59} 60 61define void @StoreInBounds3() { 62; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}} 63; CHECK-NEXT: args uses: 64; CHECK-NEXT: allocas uses: 65; CHECK-NEXT: x[4]: [2,3){{$}} 66; GLOBAL-NEXT: safe accesses: 67; GLOBAL-NEXT: store i8 0, i8* %x2, align 1 68; CHECK-EMPTY: 69entry: 70 %x = alloca i32, align 4 71 %x1 = bitcast i32* %x to i8* 72 %x2 = getelementptr i8, i8* %x1, i64 2 73 store i8 0, i8* %x2, align 1 74 ret void 75} 76 77; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr. 78define void @StoreInBounds4() { 79; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}} 80; CHECK-NEXT: args uses: 81; CHECK-NEXT: allocas uses: 82; CHECK-NEXT: x[4]: full-set{{$}} 83; GLOBAL-NEXT: safe accesses: 84; CHECK-EMPTY: 85entry: 86 %x = alloca i32, align 4 87 %x1 = ptrtoint i32* %x to i64 88 %x2 = add i64 %x1, 2 89 %x3 = inttoptr i64 %x2 to i8* 90 store i8 0, i8* %x3, align 1 91 ret void 92} 93 94define void @StoreInBounds6() { 95; CHECK-LABEL: @StoreInBounds6 dso_preemptable{{$}} 96; CHECK-NEXT: args uses: 97; CHECK-NEXT: allocas uses: 98; GLOBAL-NEXT: x[4]: full-set, @retptr(arg0, [0,1)){{$}} 99; LOCAL-NEXT: x[4]: [0,1), @retptr(arg0, [0,1)){{$}} 100; GLOBAL-NEXT: safe accesses: 101; GLOBAL-NEXT: store i8 0, i8* %x2, align 1 102; CHECK-EMPTY: 103entry: 104 %x = alloca i32, align 4 105 %x1 = bitcast i32* %x to i8* 106 %x2 = call i8* @retptr(i8* %x1) 107 store i8 0, i8* %x2, align 1 108 ret void 109} 110 111define dso_local void @WriteMinMax(i8* %p) { 112; CHECK-LABEL: @WriteMinMax{{$}} 113; CHECK-NEXT: args uses: 114; CHECK-NEXT: p[]: full-set 115; CHECK-NEXT: allocas uses: 116; GLOBAL-NEXT: safe accesses: 117; GLOBAL-NEXT: store i8 0, i8* %p1, align 1 118; GLOBAL-NEXT: store i8 0, i8* %p2, align 1 119; CHECK-EMPTY: 120entry: 121 %p1 = getelementptr i8, i8* %p, i64 9223372036854775805 122 store i8 0, i8* %p1, align 1 123 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775805 124 store i8 0, i8* %p2, align 1 125 ret void 126} 127 128define dso_local void @WriteMax(i8* %p) { 129; CHECK-LABEL: @WriteMax{{$}} 130; CHECK-NEXT: args uses: 131; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806) 132; CHECK-NEXT: allocas uses: 133; GLOBAL-NEXT: safe accesses: 134; GLOBAL-NEXT: call void @llvm.memset.p0i8.i64(i8* %p, i8 1, i64 9223372036854775806, i1 false) 135; GLOBAL-NEXT: call void @llvm.memset.p0i8.i64(i8* %p2, i8 1, i64 9223372036854775806, i1 false) 136; CHECK-EMPTY: 137entry: 138 call void @llvm.memset.p0i8.i64(i8* %p, i8 1, i64 9223372036854775806, i1 0) 139 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775807 140 call void @llvm.memset.p0i8.i64(i8* %p2, i8 1, i64 9223372036854775806, i1 0) 141 ret void 142} 143 144define void @StoreOutOfBounds() { 145; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}} 146; CHECK-NEXT: args uses: 147; CHECK-NEXT: allocas uses: 148; CHECK-NEXT: x[4]: [2,6){{$}} 149; GLOBAL-NEXT: safe accesses: 150; CHECK-EMPTY: 151entry: 152 %x = alloca i32, align 4 153 %x1 = bitcast i32* %x to i8* 154 %x2 = getelementptr i8, i8* %x1, i64 2 155 %x3 = bitcast i8* %x2 to i32* 156 store i32 0, i32* %x3, align 1 157 ret void 158} 159 160define void @StoreOutOfBounds2() { 161; CHECK-LABEL: @StoreOutOfBounds2 dso_preemptable{{$}} 162; CHECK-NEXT: args uses: 163; CHECK-NEXT: allocas uses: 164; GLOBAL-NEXT: x[4]: full-set, @retptr(arg0, [2,3)){{$}} 165; LOCAL-NEXT: x[4]: [2,6), @retptr(arg0, [2,3)){{$}} 166; GLOBAL-NEXT: safe accesses: 167; CHECK-EMPTY: 168entry: 169 %x = alloca i32, align 4 170 %x1 = bitcast i32* %x to i8* 171 %x2 = getelementptr i8, i8* %x1, i64 2 172 %x3 = call i8* @retptr(i8* %x2) 173 %x4 = bitcast i8* %x3 to i32* 174 store i32 0, i32* %x4, align 1 175 ret void 176} 177 178; There is no difference in load vs store handling. 179define void @LoadInBounds() { 180; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}} 181; CHECK-NEXT: args uses: 182; CHECK-NEXT: allocas uses: 183; CHECK-NEXT: x[4]: [0,1){{$}} 184; GLOBAL-NEXT: safe accesses: 185; GLOBAL-NEXT: %v = load i8, i8* %x1, align 1 186; CHECK-EMPTY: 187entry: 188 %x = alloca i32, align 4 189 %x1 = bitcast i32* %x to i8* 190 %v = load i8, i8* %x1, align 1 191 ret void 192} 193 194define void @LoadOutOfBounds() { 195; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}} 196; CHECK-NEXT: args uses: 197; CHECK-NEXT: allocas uses: 198; CHECK-NEXT: x[4]: [2,6){{$}} 199; GLOBAL-NEXT: safe accesses: 200; CHECK-EMPTY: 201entry: 202 %x = alloca i32, align 4 203 %x1 = bitcast i32* %x to i8* 204 %x2 = getelementptr i8, i8* %x1, i64 2 205 %x3 = bitcast i8* %x2 to i32* 206 %v = load i32, i32* %x3, align 1 207 ret void 208} 209 210; Leak through ret. 211define i8* @Ret() { 212; CHECK-LABEL: @Ret dso_preemptable{{$}} 213; CHECK-NEXT: args uses: 214; CHECK-NEXT: allocas uses: 215; CHECK-NEXT: x[4]: full-set{{$}} 216; GLOBAL-NEXT: safe accesses: 217; CHECK-EMPTY: 218entry: 219 %x = alloca i32, align 4 220 %x1 = bitcast i32* %x to i8* 221 %x2 = getelementptr i8, i8* %x1, i64 2 222 ret i8* %x2 223} 224 225declare void @Foo(i16* %p) 226 227define void @DirectCall() { 228; CHECK-LABEL: @DirectCall dso_preemptable{{$}} 229; CHECK-NEXT: args uses: 230; CHECK-NEXT: allocas uses: 231; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}} 232; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}} 233; GLOBAL-NEXT: safe accesses: 234; CHECK-EMPTY: 235entry: 236 %x = alloca i64, align 4 237 %x1 = bitcast i64* %x to i16* 238 %x2 = getelementptr i16, i16* %x1, i64 1 239 call void @Foo(i16* %x2); 240 ret void 241} 242 243; Indirect calls can not be analyzed (yet). 244; FIXME: %p[]: full-set looks invalid 245define void @IndirectCall(void (i8*)* %p) { 246; CHECK-LABEL: @IndirectCall dso_preemptable{{$}} 247; CHECK-NEXT: args uses: 248; CHECK-NEXT: p[]: full-set{{$}} 249; CHECK-NEXT: allocas uses: 250; CHECK-NEXT: x[4]: full-set{{$}} 251; GLOBAL-NEXT: safe accesses: 252; CHECK-EMPTY: 253entry: 254 %x = alloca i32, align 4 255 %x1 = bitcast i32* %x to i8* 256 call void %p(i8* %x1); 257 ret void 258} 259 260define void @NonConstantOffset(i1 zeroext %z) { 261; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}} 262; CHECK-NEXT: args uses: 263; CHECK-NEXT: allocas uses: 264; FIXME: SCEV can't look through selects. 265; CHECK-NEXT: x[4]: [0,4){{$}} 266; GLOBAL-NEXT: safe accesses: 267; GLOBAL-NEXT: store i8 0, i8* %x2, align 1 268; CHECK-EMPTY: 269entry: 270 %x = alloca i32, align 4 271 %x1 = bitcast i32* %x to i8* 272 %idx = select i1 %z, i64 1, i64 2 273 %x2 = getelementptr i8, i8* %x1, i64 %idx 274 store i8 0, i8* %x2, align 1 275 ret void 276} 277 278define void @NegativeOffset() { 279; CHECK-LABEL: @NegativeOffset dso_preemptable{{$}} 280; CHECK-NEXT: args uses: 281; CHECK-NEXT: allocas uses: 282; CHECK-NEXT: x[40]: [-1600000000000,-1599999999996){{$}} 283; GLOBAL-NEXT: safe accesses: 284; CHECK-EMPTY: 285entry: 286 %x = alloca i32, i32 10, align 4 287 %x2 = getelementptr i32, i32* %x, i64 -400000000000 288 store i32 0, i32* %x2, align 1 289 ret void 290} 291 292define void @PossiblyNegativeOffset(i16 %z) { 293; CHECK-LABEL: @PossiblyNegativeOffset dso_preemptable{{$}} 294; CHECK-NEXT: args uses: 295; CHECK-NEXT: allocas uses: 296; CHECK-NEXT: x[40]: [-131072,131072){{$}} 297; GLOBAL-NEXT: safe accesses: 298; CHECK-EMPTY: 299entry: 300 %x = alloca i32, i32 10, align 4 301 %x2 = getelementptr i32, i32* %x, i16 %z 302 store i32 0, i32* %x2, align 1 303 ret void 304} 305 306define void @NonConstantOffsetOOB(i1 zeroext %z) { 307; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}} 308; CHECK-NEXT: args uses: 309; CHECK-NEXT: allocas uses: 310; CHECK-NEXT: x[4]: [0,6){{$}} 311; GLOBAL-NEXT: safe accesses: 312; CHECK-EMPTY: 313entry: 314 %x = alloca i32, align 4 315 %x1 = bitcast i32* %x to i8* 316 %idx = select i1 %z, i64 1, i64 4 317 %x2 = getelementptr i8, i8* %x1, i64 %idx 318 store i8 0, i8* %x2, align 1 319 ret void 320} 321 322define void @ArrayAlloca() { 323; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}} 324; CHECK-NEXT: args uses: 325; CHECK-NEXT: allocas uses: 326; CHECK-NEXT: x[40]: [36,40){{$}} 327; GLOBAL-NEXT: safe accesses: 328; GLOBAL-NEXT: store i32 0, i32* %x3, align 1 329; CHECK-EMPTY: 330entry: 331 %x = alloca i32, i32 10, align 4 332 %x1 = bitcast i32* %x to i8* 333 %x2 = getelementptr i8, i8* %x1, i64 36 334 %x3 = bitcast i8* %x2 to i32* 335 store i32 0, i32* %x3, align 1 336 ret void 337} 338 339define void @ArrayAllocaOOB() { 340; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}} 341; CHECK-NEXT: args uses: 342; CHECK-NEXT: allocas uses: 343; CHECK-NEXT: x[40]: [37,41){{$}} 344; GLOBAL-NEXT: safe accesses: 345; CHECK-EMPTY: 346entry: 347 %x = alloca i32, i32 10, align 4 348 %x1 = bitcast i32* %x to i8* 349 %x2 = getelementptr i8, i8* %x1, i64 37 350 %x3 = bitcast i8* %x2 to i32* 351 store i32 0, i32* %x3, align 1 352 ret void 353} 354 355define void @DynamicAllocaUnused(i64 %size) { 356; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}} 357; CHECK-NEXT: args uses: 358; CHECK-NEXT: allocas uses: 359; CHECK-NEXT: x[0]: empty-set{{$}} 360; GLOBAL-NEXT: safe accesses: 361; CHECK-EMPTY: 362entry: 363 %x = alloca i32, i64 %size, align 16 364 ret void 365} 366 367; Dynamic alloca with unknown size. 368define void @DynamicAlloca(i64 %size) { 369; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}} 370; CHECK-NEXT: args uses: 371; CHECK-NEXT: allocas uses: 372; CHECK-NEXT: x[0]: [0,4){{$}} 373; GLOBAL-NEXT: safe accesses: 374; CHECK-EMPTY: 375entry: 376 %x = alloca i32, i64 %size, align 16 377 store i32 0, i32* %x, align 1 378 ret void 379} 380 381; Dynamic alloca with limited size. 382; FIXME: could be proved safe. Implement. 383define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) { 384; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}} 385; CHECK-NEXT: args uses: 386; CHECK-NEXT: allocas uses: 387; CHECK-NEXT: x[0]: [0,4){{$}} 388; GLOBAL-NEXT: safe accesses: 389; CHECK-EMPTY: 390entry: 391 %size = select i1 %z, i64 3, i64 5 392 %x = alloca i32, i64 %size, align 16 393 store i32 0, i32* %x, align 1 394 ret void 395} 396 397define signext i8 @SimpleLoop() { 398; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}} 399; CHECK-NEXT: args uses: 400; CHECK-NEXT: allocas uses: 401; CHECK-NEXT: x[10]: [0,10){{$}} 402; GLOBAL-NEXT: safe accesses: 403; GLOBAL-NEXT: %1 = load volatile i8, i8* %p.09, align 1 404; CHECK-EMPTY: 405entry: 406 %x = alloca [10 x i8], align 1 407 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0 408 %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 10 409 br label %for.body 410 411for.body: 412 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ] 413 %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ] 414 %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1 415 %1 = load volatile i8, i8* %p.09, align 1 416 %add = add i8 %1, %sum.010 417 %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit 418 br i1 %exitcond, label %for.cond.cleanup, label %for.body 419 420for.cond.cleanup: 421 ret i8 %add 422} 423 424; OOB in a loop. 425define signext i8 @SimpleLoopOOB() { 426; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}} 427; CHECK-NEXT: args uses: 428; CHECK-NEXT: allocas uses: 429; CHECK-NEXT: x[10]: [0,11){{$}} 430; GLOBAL-NEXT: safe accesses: 431; CHECK-EMPTY: 432entry: 433 %x = alloca [10 x i8], align 1 434 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0 435 ; 11 iterations 436 %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 11 437 br label %for.body 438 439for.body: 440 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ] 441 %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ] 442 %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1 443 %1 = load volatile i8, i8* %p.09, align 1 444 %add = add i8 %1, %sum.010 445 %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit 446 br i1 %exitcond, label %for.cond.cleanup, label %for.body 447 448for.cond.cleanup: 449 ret i8 %add 450} 451 452define dso_local void @SizeCheck(i32 %sz) { 453; CHECK-LABEL: @SizeCheck{{$}} 454; CHECK-NEXT: args uses: 455; CHECK-NEXT: allocas uses: 456; CHECK-NEXT: x1[128]: [0,4294967295){{$}} 457; GLOBAL-NEXT: safe accesses: 458; CHECK-EMPTY: 459entry: 460 %x1 = alloca [128 x i8], align 16 461 %x1.sub = getelementptr inbounds [128 x i8], [128 x i8]* %x1, i64 0, i64 0 462 %cmp = icmp slt i32 %sz, 129 463 br i1 %cmp, label %if.then, label %if.end 464 465if.then: 466 call void @llvm.memset.p0i8.i32(i8* nonnull align 16 %x1.sub, i8 0, i32 %sz, i1 false) 467 br label %if.end 468 469if.end: 470 ret void 471} 472 473; FIXME: scalable allocas are considered to be of size zero, and scalable accesses to be full-range. 474; This effectively disables safety analysis for scalable allocations. 475define void @Scalable(<vscale x 4 x i32>* %p, <vscale x 4 x i32>* %unused, <vscale x 4 x i32> %v) { 476; CHECK-LABEL: @Scalable dso_preemptable{{$}} 477; CHECK-NEXT: args uses: 478; CHECK-NEXT: p[]: full-set 479; CHECK-NEXT: unused[]: empty-set 480; CHECK-NEXT: allocas uses: 481; CHECK-NEXT: x[0]: [0,1){{$}} 482; GLOBAL-NEXT: safe accesses: 483; GLOBAL-NEXT: store <vscale x 4 x i32> %v, <vscale x 4 x i32>* %p, align 4 484; CHECK-EMPTY: 485entry: 486 %x = alloca <vscale x 4 x i32>, align 4 487 %x1 = bitcast <vscale x 4 x i32>* %x to i8* 488 store i8 0, i8* %x1, align 1 489 store <vscale x 4 x i32> %v, <vscale x 4 x i32>* %p, align 4 490 ret void 491} 492 493%zerosize_type = type {} 494 495define void @ZeroSize(%zerosize_type *%p) { 496; CHECK-LABEL: @ZeroSize dso_preemptable{{$}} 497; CHECK-NEXT: args uses: 498; CHECK-NEXT: p[]: empty-set 499; CHECK-NEXT: allocas uses: 500; CHECK-NEXT: x[0]: empty-set 501; GLOBAL-NEXT: safe accesses: 502; GLOBAL-NEXT: store %zerosize_type undef, %zerosize_type* %x, align 4 503; GLOBAL-NEXT: store %zerosize_type undef, %zerosize_type* undef, align 4 504; GLOBAL-NEXT: load %zerosize_type, %zerosize_type* %p, align 505; CHECK-EMPTY: 506entry: 507 %x = alloca %zerosize_type, align 4 508 store %zerosize_type undef, %zerosize_type* %x, align 4 509 store %zerosize_type undef, %zerosize_type* undef, align 4 510 %val = load %zerosize_type, %zerosize_type* %p, align 4 511 ret void 512} 513 514define void @OperandBundle() { 515; CHECK-LABEL: @OperandBundle dso_preemptable{{$}} 516; CHECK-NEXT: args uses: 517; CHECK-NEXT: allocas uses: 518; CHECK-NEXT: a[4]: full-set 519; GLOBAL-NEXT: safe accesses: 520; CHECK-EMPTY: 521entry: 522 %a = alloca i32, align 4 523 call void @LeakAddress() ["unknown"(i32* %a)] 524 ret void 525} 526 527define void @ByVal(i16* byval(i16) %p) { 528 ; CHECK-LABEL: @ByVal dso_preemptable{{$}} 529 ; CHECK-NEXT: args uses: 530 ; CHECK-NEXT: allocas uses: 531 ; GLOBAL-NEXT: safe accesses: 532 ; CHECK-EMPTY: 533entry: 534 ret void 535} 536 537define void @TestByVal() { 538; CHECK-LABEL: @TestByVal dso_preemptable{{$}} 539; CHECK-NEXT: args uses: 540; CHECK-NEXT: allocas uses: 541; CHECK-NEXT: x[2]: [0,2) 542; CHECK-NEXT: y[8]: [0,2) 543; GLOBAL-NEXT: safe accesses: 544; GLOBAL-NEXT: call void @ByVal(i16* byval(i16) %x) 545; GLOBAL-NEXT: call void @ByVal(i16* byval(i16) %y1) 546; CHECK-EMPTY: 547entry: 548 %x = alloca i16, align 4 549 call void @ByVal(i16* byval(i16) %x) 550 551 %y = alloca i64, align 4 552 %y1 = bitcast i64* %y to i16* 553 call void @ByVal(i16* byval(i16) %y1) 554 555 ret void 556} 557 558declare void @ByValArray([100000 x i64]* byval([100000 x i64]) %p) 559 560define void @TestByValArray() { 561; CHECK-LABEL: @TestByValArray dso_preemptable{{$}} 562; CHECK-NEXT: args uses: 563; CHECK-NEXT: allocas uses: 564; CHECK-NEXT: z[800000]: [500000,1300000) 565; GLOBAL-NEXT: safe accesses: 566; CHECK-EMPTY: 567entry: 568 %z = alloca [100000 x i64], align 4 569 %z1 = bitcast [100000 x i64]* %z to i8* 570 %z2 = getelementptr i8, i8* %z1, i64 500000 571 %z3 = bitcast i8* %z2 to [100000 x i64]* 572 call void @ByValArray([100000 x i64]* byval([100000 x i64]) %z3) 573 ret void 574} 575 576define dso_local i8 @LoadMinInt64(i8* %p) { 577 ; CHECK-LABEL: @LoadMinInt64{{$}} 578 ; CHECK-NEXT: args uses: 579 ; CHECK-NEXT: p[]: [-9223372036854775808,-9223372036854775807){{$}} 580 ; CHECK-NEXT: allocas uses: 581 ; GLOBAL-NEXT: safe accesses: 582 ; GLOBAL-NEXT: load i8, i8* %p2, align 1 583 ; CHECK-EMPTY: 584 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775808 585 %v = load i8, i8* %p2, align 1 586 ret i8 %v 587} 588 589define void @Overflow() { 590; CHECK-LABEL: @Overflow dso_preemptable{{$}} 591; CHECK-NEXT: args uses: 592; CHECK-NEXT: allocas uses: 593; LOCAL-NEXT: x[1]: empty-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}} 594; GLOBAL-NEXT: x[1]: full-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}} 595; GLOBAL-NEXT: safe accesses: 596; CHECK-EMPTY: 597entry: 598 %x = alloca i8, align 4 599 %x2 = getelementptr i8, i8* %x, i64 -9223372036854775808 600 %v = call i8 @LoadMinInt64(i8* %x2) 601 ret void 602} 603 604define void @DeadBlock(i64* %p) { 605; CHECK-LABEL: @DeadBlock dso_preemptable{{$}} 606; CHECK-NEXT: args uses: 607; CHECK-NEXT: p[]: empty-set{{$}} 608; CHECK-NEXT: allocas uses: 609; CHECK-NEXT: x[1]: empty-set{{$}} 610; GLOBAL-NEXT: safe accesses: 611; GLOBAL-NEXT: store i8 5, i8* %x 612; GLOBAL-NEXT: store i64 -5, i64* %p 613; CHECK-EMPTY: 614entry: 615 %x = alloca i8, align 4 616 br label %end 617 618dead: 619 store i8 5, i8* %x 620 store i64 -5, i64* %p 621 br label %end 622 623end: 624 ret void 625} 626 627define void @LifeNotStarted() { 628; CHECK-LABEL: @LifeNotStarted dso_preemptable{{$}} 629; CHECK-NEXT: args uses: 630; CHECK-NEXT: allocas uses: 631; CHECK: x[1]: full-set{{$}} 632; CHECK: y[1]: full-set{{$}} 633; CHECK: z[1]: full-set{{$}} 634; GLOBAL-NEXT: safe accesses: 635; CHECK-EMPTY: 636entry: 637 %x = alloca i8, align 4 638 %y = alloca i8, align 4 639 %z = alloca i8, align 4 640 641 store i8 5, i8* %x 642 %n = load i8, i8* %y 643 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 644 645 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) 646 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) 647 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z) 648 649 ret void 650} 651 652define void @LifeOK() { 653; CHECK-LABEL: @LifeOK dso_preemptable{{$}} 654; CHECK-NEXT: args uses: 655; CHECK-NEXT: allocas uses: 656; CHECK: x[1]: [0,1){{$}} 657; CHECK: y[1]: [0,1){{$}} 658; CHECK: z[1]: [0,1){{$}} 659; GLOBAL-NEXT: safe accesses: 660; GLOBAL-NEXT: store i8 5, i8* %x 661; GLOBAL-NEXT: %n = load i8, i8* %y 662; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 663; CHECK-EMPTY: 664entry: 665 %x = alloca i8, align 4 666 %y = alloca i8, align 4 667 %z = alloca i8, align 4 668 669 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) 670 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) 671 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z) 672 673 store i8 5, i8* %x 674 %n = load i8, i8* %y 675 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 676 677 ret void 678} 679 680define void @LifeEnded() { 681; CHECK-LABEL: @LifeEnded dso_preemptable{{$}} 682; CHECK-NEXT: args uses: 683; CHECK-NEXT: allocas uses: 684; CHECK: x[1]: full-set{{$}} 685; CHECK: y[1]: full-set{{$}} 686; CHECK: z[1]: full-set{{$}} 687; GLOBAL-NEXT: safe accesses: 688; CHECK-EMPTY: 689entry: 690 %x = alloca i8, align 4 691 %y = alloca i8, align 4 692 %z = alloca i8, align 4 693 694 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x) 695 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y) 696 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z) 697 698 call void @llvm.lifetime.end.p0i8(i64 1, i8* %x) 699 call void @llvm.lifetime.end.p0i8(i64 1, i8* %y) 700 call void @llvm.lifetime.end.p0i8(i64 1, i8* %z) 701 702 store i8 5, i8* %x 703 %n = load i8, i8* %y 704 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false) 705 706 ret void 707} 708 709define void @TwoAllocasOK() { 710; CHECK-LABEL: @TwoAllocasOK 711; CHECK-NEXT: args uses: 712; CHECK-NEXT: allocas uses: 713; CHECK: a[4]: [0,1){{$}} 714; CHECK: y[1]: [0,1){{$}} 715; GLOBAL-NEXT: safe accesses: 716; GLOBAL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %y, i8* %x, i32 1, i1 false) 717; CHECK-EMPTY: 718entry: 719 %a = alloca i32, align 4 720 %x = bitcast i32* %a to i8* 721 %y = alloca i8, align 4 722 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %y, i8* %x, i32 1, i1 false) 723 ret void 724} 725 726define void @TwoAllocasOOBDest() { 727; CHECK-LABEL: @TwoAllocasOOBDest 728; CHECK-NEXT: args uses: 729; CHECK-NEXT: allocas uses: 730; CHECK: a[4]: [0,4){{$}} 731; CHECK: y[1]: [0,4){{$}} 732; GLOBAL-NEXT: safe accesses: 733; CHECK-EMPTY: 734entry: 735 %a = alloca i32, align 4 736 %x = bitcast i32* %a to i8* 737 %y = alloca i8, align 4 738 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %y, i8* %x, i32 4, i1 false) 739 ret void 740} 741 742define void @TwoAllocasOOBSource() { 743; CHECK-LABEL: @TwoAllocasOOBSource 744; CHECK-NEXT: args uses: 745; CHECK-NEXT: allocas uses: 746; CHECK: a[4]: [0,4){{$}} 747; CHECK: y[1]: [0,4){{$}} 748; GLOBAL-NEXT: safe accesses: 749; CHECK-EMPTY: 750entry: 751 %a = alloca i32, align 4 752 %x = bitcast i32* %a to i8* 753 %y = alloca i8, align 4 754 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x, i8* %y, i32 4, i1 false) 755 ret void 756} 757 758define void @TwoAllocasOOBBoth() { 759; CHECK-LABEL: @TwoAllocasOOBBoth 760; CHECK-NEXT: args uses: 761; CHECK-NEXT: allocas uses: 762; CHECK: a[4]: [0,5){{$}} 763; CHECK: y[1]: [0,5){{$}} 764; GLOBAL-NEXT: safe accesses: 765; CHECK-EMPTY: 766entry: 767 %a = alloca i32, align 4 768 %x = bitcast i32* %a to i8* 769 %y = alloca i8, align 4 770 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %y, i8* %x, i32 5, i1 false) 771 ret void 772} 773 774define void @MixedAccesses() { 775; CHECK-LABEL: @MixedAccesses 776; CHECK-NEXT: args uses: 777; CHECK-NEXT: allocas uses: 778; CHECK: a[4]: [0,5){{$}} 779; GLOBAL-NEXT: safe accesses: 780; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 781; CHECK-EMPTY: 782entry: 783 %a = alloca i32, align 4 784 %x = bitcast i32* %a to i8* 785 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 5, i1 false) 786 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 787 ret void 788} 789 790define void @MixedAccesses2() { 791; CHECK-LABEL: @MixedAccesses2 792; CHECK-NEXT: args uses: 793; CHECK-NEXT: allocas uses: 794; CHECK: a[4]: [0,8){{$}} 795; GLOBAL-NEXT: safe accesses: 796; GLOBAL-NEXT: load i32, i32* %a, align 4 797; CHECK-EMPTY: 798entry: 799 %a = alloca i32, align 4 800 %a1 = bitcast i32* %a to i64* 801 %n1 = load i64, i64* %a1, align 4 802 %n2 = load i32, i32* %a, align 4 803 ret void 804} 805 806define void @MixedAccesses3(void (i8*)* %func) { 807; CHECK-LABEL: @MixedAccesses3 808; CHECK-NEXT: args uses: 809; CHECK-NEXT: func[]: full-set 810; CHECK-NEXT: allocas uses: 811; CHECK: a[4]: full-set{{$}} 812; GLOBAL-NEXT: safe accesses: 813; GLOBAL-NEXT: load i32, i32* %a, align 4 814; CHECK-EMPTY: 815entry: 816 %a = alloca i32, align 4 817 %x = bitcast i32* %a to i8* 818 %n2 = load i32, i32* %a, align 4 819 call void %func(i8* %x) 820 ret void 821} 822 823define void @MixedAccesses4() { 824; CHECK-LABEL: @MixedAccesses4 825; CHECK-NEXT: args uses: 826; CHECK-NEXT: allocas uses: 827; CHECK: a[4]: full-set{{$}} 828; CHECK: a1[8]: [0,8){{$}} 829; GLOBAL-NEXT: safe accesses: 830; GLOBAL-NEXT: load i32, i32* %a, align 4 831; CHECK-EMPTY: 832entry: 833 %a = alloca i32, align 4 834 %a1 = alloca i32*, align 4 835 %n2 = load i32, i32* %a, align 4 836 store i32* %a, i32** %a1 837 ret void 838} 839 840define i32* @MixedAccesses5(i1 %x, i32* %y) { 841; CHECK-LABEL: @MixedAccesses5 842; CHECK-NEXT: args uses: 843; CHECK: y[]: full-set 844; CHECK-NEXT: allocas uses: 845; CHECK: a[4]: full-set{{$}} 846; GLOBAL-NEXT: safe accesses: 847; GLOBAL-NEXT: load i32, i32* %a, align 4 848; CHECK-EMPTY: 849entry: 850 %a = alloca i32, align 4 851 br i1 %x, label %tlabel, label %flabel 852flabel: 853 %n = load i32, i32* %a, align 4 854 ret i32* %y 855tlabel: 856 ret i32* %a 857} 858 859define void @MixedAccesses6(i8* %arg) { 860; CHECK-LABEL: @MixedAccesses6 861; CHECK-NEXT: args uses: 862; CHECK-NEXT: arg[]: [0,4) 863; CHECK-NEXT: allocas uses: 864; CHECK: a[4]: [0,4) 865; GLOBAL-NEXT: safe accesses: 866; GLOBAL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x, i8* %arg, i32 4, i1 false) 867; CHECK-EMPTY: 868entry: 869 %a = alloca i32, align 4 870 %x = bitcast i32* %a to i8* 871 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x, i8* %arg, i32 4, i1 false) 872 ret void 873} 874 875define void @MixedAccesses7(i1 %cond, i8* %arg) { 876; SECV doesn't support select, so we consider this non-stack-safe, even through 877; it is. 878; 879; CHECK-LABEL: @MixedAccesses7 880; CHECK-NEXT: args uses: 881; CHECK-NEXT: arg[]: full-set 882; CHECK-NEXT: allocas uses: 883; CHECK: a[4]: full-set 884; GLOBAL-NEXT: safe accesses: 885; CHECK-EMPTY: 886entry: 887 %a = alloca i32, align 4 888 %x = bitcast i32* %a to i8* 889 %x1 = select i1 %cond, i8* %arg, i8* %x 890 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %arg, i32 4, i1 false) 891 ret void 892} 893 894define void @NoStackAccess(i8* %arg1, i8* %arg2) { 895; CHECK-LABEL: @NoStackAccess 896; CHECK-NEXT: args uses: 897; CHECK-NEXT: arg1[]: [0,4) 898; CHECK-NEXT: arg2[]: [0,4) 899; CHECK-NEXT: allocas uses: 900; CHECK: a[4]: empty-set{{$}} 901; GLOBAL-NEXT: safe accesses: 902; GLOBAL-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %arg1, i8* %arg2, i32 4, i1 false) 903; CHECK-EMPTY: 904entry: 905 %a = alloca i32, align 4 906 %x = bitcast i32* %a to i8* 907 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %arg1, i8* %arg2, i32 4, i1 false) 908 ret void 909} 910 911define void @DoubleLifetime() { 912; CHECK-LABEL: @DoubleLifetime 913; CHECK-NEXT: args uses: 914; CHECK-NEXT: allocas uses: 915; CHECK: a[4]: full-set{{$}} 916; GLOBAL-NEXT: safe accesses: 917; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 918; CHECK-EMPTY: 919entry: 920 %a = alloca i32, align 4 921 %x = bitcast i32* %a to i8* 922 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 923 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 924 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 true) 925 926 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 927 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 928 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 929 ret void 930} 931 932define void @DoubleLifetime2() { 933; CHECK-LABEL: @DoubleLifetime2 934; CHECK-NEXT: args uses: 935; CHECK-NEXT: allocas uses: 936; CHECK: a[4]: full-set{{$}} 937; GLOBAL-NEXT: safe accesses: 938; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 939; CHECK-EMPTY: 940entry: 941 %a = alloca i32, align 4 942 %x = bitcast i32* %a to i8* 943 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 944 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 945 %n = load i32, i32* %a 946 947 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 948 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 949 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 950 ret void 951} 952 953define void @DoubleLifetime3() { 954; CHECK-LABEL: @DoubleLifetime3 955; CHECK-NEXT: args uses: 956; CHECK-NEXT: allocas uses: 957; CHECK: a[4]: full-set{{$}} 958; GLOBAL-NEXT: safe accesses: 959; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 960; CHECK-EMPTY: 961entry: 962 %a = alloca i32, align 4 963 %x = bitcast i32* %a to i8* 964 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 965 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 966 store i32 5, i32* %a 967 968 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 969 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 970 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 971 ret void 972} 973 974define void @DoubleLifetime4() { 975; CHECK-LABEL: @DoubleLifetime4 976; CHECK-NEXT: args uses: 977; CHECK-NEXT: allocas uses: 978; CHECK: a[4]: full-set{{$}} 979; GLOBAL-NEXT: safe accesses: 980; GLOBAL-NEXT: call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 981; CHECK-EMPTY: 982entry: 983 %a = alloca i32, align 4 984 %x = bitcast i32* %a to i8* 985 call void @llvm.lifetime.start.p0i8(i64 4, i8* %x) 986 call void @llvm.memset.p0i8.i32(i8* %x, i8 1, i32 4, i1 false) 987 call void @llvm.lifetime.end.p0i8(i64 4, i8* %x) 988 call void @unknown_call(i8* %x) 989 ret void 990} 991 992declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) 993declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) 994