brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.6 KiB · 6944f38 Raw
1141 lines · plain
1; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL2; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL3 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 ptr null, align 88 9declare void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 %len, i1 %isvolatile)10declare void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)11declare void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)12declare void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 %len, i1 %isvolatile)13 14declare void @unknown_call(ptr %dest)15declare void @unknown_call_int(i64 %i)16declare ptr @retptr(ptr returned)17 18; Address leaked.19define void @LeakAddress() {20; CHECK-LABEL: @LeakAddress dso_preemptable{{$}}21; CHECK-NEXT: args uses:22; CHECK-NEXT: allocas uses:23; CHECK-NEXT: x[4]: full-set{{$}}24; GLOBAL-NEXT: safe accesses:25; CHECK-EMPTY:26entry:27  %x = alloca i32, align 428  store ptr %x, ptr @sink, align 829  ret void30}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, ptr %x, align 139; CHECK-EMPTY:40entry:41  %x = alloca i32, align 442  store i8 0, ptr %x, align 143  ret void44}45 46define void @StoreInBoundsCond(i64 %i) {47; CHECK-LABEL: @StoreInBoundsCond dso_preemptable{{$}}48; CHECK-NEXT: args uses:49; CHECK-NEXT: allocas uses:50; CHECK-NEXT: x[4]: full-set{{$}}51; GLOBAL-NEXT: safe accesses:52; GLOBAL-NEXT: store i8 0, ptr %x2, align 153; CHECK-EMPTY:54entry:55  %x = alloca i32, align 456  %c1 = icmp sge i64 %i, 057  %c2 = icmp slt i64 %i, 458  br i1 %c1, label %c1.true, label %false59 60c1.true:61  br i1 %c2, label %c2.true, label %false62 63c2.true:64  %x2 = getelementptr i8, ptr %x, i64 %i65  store i8 0, ptr %x2, align 166  br label %false67 68false:69  ret void70}71 72define void @StoreInBoundsMinMax(i64 %i) {73; CHECK-LABEL: @StoreInBoundsMinMax dso_preemptable{{$}}74; CHECK-NEXT: args uses:75; CHECK-NEXT: allocas uses:76; CHECK-NEXT: x[4]: [0,4){{$}}77; GLOBAL-NEXT: safe accesses:78; GLOBAL-NEXT: store i8 0, ptr %x2, align 179; CHECK-EMPTY:80entry:81  %x = alloca i32, align 482  %c1 = icmp sge i64 %i, 083  %i1 = select i1 %c1, i64 %i, i64 084  %c2 = icmp slt i64 %i1, 385  %i2 = select i1 %c2, i64 %i1, i64 386  %x2 = getelementptr i8, ptr %x, i64 %i287  store i8 0, ptr %x2, align 188  ret void89}90 91define void @StoreInBounds2() {92; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}}93; CHECK-NEXT: args uses:94; CHECK-NEXT: allocas uses:95; CHECK-NEXT: x[4]: [0,4){{$}}96; GLOBAL-NEXT: safe accesses:97; GLOBAL-NEXT: store i32 0, ptr %x, align 498; CHECK-EMPTY:99entry:100  %x = alloca i32, align 4101  store i32 0, ptr %x, align 4102  ret void103}104 105define void @StoreInBounds3() {106; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}}107; CHECK-NEXT: args uses:108; CHECK-NEXT: allocas uses:109; CHECK-NEXT: x[4]: [2,3){{$}}110; GLOBAL-NEXT: safe accesses:111; GLOBAL-NEXT: store i8 0, ptr %x2, align 1112; CHECK-EMPTY:113entry:114  %x = alloca i32, align 4115  %x2 = getelementptr i8, ptr %x, i64 2116  store i8 0, ptr %x2, align 1117  ret void118}119 120; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.121define void @StoreInBounds4() {122; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}}123; CHECK-NEXT: args uses:124; CHECK-NEXT: allocas uses:125; CHECK-NEXT: x[4]: full-set{{$}}126; GLOBAL-NEXT: safe accesses:127; CHECK-EMPTY:128entry:129  %x = alloca i32, align 4130  %x1 = ptrtoint ptr %x to i64131  %x2 = add i64 %x1, 2132  %x3 = inttoptr i64 %x2 to ptr133  store i8 0, ptr %x3, align 1134  ret void135}136 137define void @StoreInBounds6() {138; CHECK-LABEL: @StoreInBounds6 dso_preemptable{{$}}139; CHECK-NEXT: args uses:140; CHECK-NEXT: allocas uses:141; GLOBAL-NEXT: x[4]: full-set, @retptr(arg0, [0,1)){{$}}142; LOCAL-NEXT: x[4]: [0,1), @retptr(arg0, [0,1)){{$}}143; GLOBAL-NEXT: safe accesses:144; GLOBAL-NEXT: store i8 0, ptr %x2, align 1145; CHECK-EMPTY:146entry:147  %x = alloca i32, align 4148  %x2 = call ptr @retptr(ptr %x)149  store i8 0, ptr %x2, align 1150  ret void151}152 153define dso_local void @WriteMinMax(ptr %p) {154; CHECK-LABEL: @WriteMinMax{{$}}155; CHECK-NEXT: args uses:156; CHECK-NEXT: p[]: full-set157; CHECK-NEXT: allocas uses:158; GLOBAL-NEXT: safe accesses:159; GLOBAL-NEXT: store i8 0, ptr %p1, align 1160; GLOBAL-NEXT: store i8 0, ptr %p2, align 1161; CHECK-EMPTY:162entry:163  %p1 = getelementptr i8, ptr %p, i64 9223372036854775805164  store i8 0, ptr %p1, align 1165  %p2 = getelementptr i8, ptr %p, i64 -9223372036854775805166  store i8 0, ptr %p2, align 1167  ret void168}169 170define dso_local void @WriteMax(ptr %p) {171; CHECK-LABEL: @WriteMax{{$}}172; CHECK-NEXT: args uses:173; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806)174; CHECK-NEXT: allocas uses:175; GLOBAL-NEXT: safe accesses:176; GLOBAL-NEXT: call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 9223372036854775806, i1 false)177; GLOBAL-NEXT: call void @llvm.memset.p0.i64(ptr %p2, i8 1, i64 9223372036854775806, i1 false)178; CHECK-EMPTY:179entry:180  call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 9223372036854775806, i1 0)181  %p2 = getelementptr i8, ptr %p, i64 -9223372036854775807182  call void @llvm.memset.p0.i64(ptr %p2, i8 1, i64 9223372036854775806, i1 0)183  ret void184}185 186define void @StoreOutOfBounds() {187; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}188; CHECK-NEXT: args uses:189; CHECK-NEXT: allocas uses:190; CHECK-NEXT: x[4]: [2,6){{$}}191; GLOBAL-NEXT: safe accesses:192; CHECK-EMPTY:193entry:194  %x = alloca i32, align 4195  %x2 = getelementptr i8, ptr %x, i64 2196  store i32 0, ptr %x2, align 1197  ret void198}199 200define void @StoreOutOfBoundsCond(i64 %i) {201; CHECK-LABEL: @StoreOutOfBoundsCond dso_preemptable{{$}}202; CHECK-NEXT: args uses:203; CHECK-NEXT: allocas uses:204; CHECK-NEXT: x[4]: full-set{{$}}205; GLOBAL-NEXT: safe accesses:206; CHECK-EMPTY:207entry:208  %x = alloca i32, align 4209  %c1 = icmp sge i64 %i, 0210  %c2 = icmp slt i64 %i, 5211  br i1 %c1, label %c1.true, label %false212 213c1.true:214  br i1 %c2, label %c2.true, label %false215 216c2.true:217  %x2 = getelementptr i8, ptr %x, i64 %i218  store i8 0, ptr %x2, align 1219  br label %false220 221false:222  ret void223}224 225define void @StoreOutOfBoundsCond2(i64 %i) {226; CHECK-LABEL: @StoreOutOfBoundsCond2 dso_preemptable{{$}}227; CHECK-NEXT: args uses:228; CHECK-NEXT: allocas uses:229; CHECK-NEXT: x[4]: full-set{{$}}230; GLOBAL-NEXT: safe accesses:231; CHECK-EMPTY:232entry:233  %x = alloca i32, align 4234  %c2 = icmp slt i64 %i, 5235  br i1 %c2, label %c2.true, label %false236 237c2.true:238  %x2 = getelementptr i8, ptr %x, i64 %i239  store i8 0, ptr %x2, align 1240  br label %false241 242false:243  ret void244}245 246define void @StoreOutOfBounds2() {247; CHECK-LABEL: @StoreOutOfBounds2 dso_preemptable{{$}}248; CHECK-NEXT: args uses:249; CHECK-NEXT: allocas uses:250; GLOBAL-NEXT: x[4]: full-set, @retptr(arg0, [2,3)){{$}}251; LOCAL-NEXT: x[4]: [2,6), @retptr(arg0, [2,3)){{$}}252; GLOBAL-NEXT: safe accesses:253; CHECK-EMPTY:254entry:255  %x = alloca i32, align 4256  %x2 = getelementptr i8, ptr %x, i64 2257  %x3 = call ptr @retptr(ptr %x2)258  store i32 0, ptr %x3, align 1259  ret void260}261 262; There is no difference in load vs store handling.263define void @LoadInBounds() {264; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}}265; CHECK-NEXT: args uses:266; CHECK-NEXT: allocas uses:267; CHECK-NEXT: x[4]: [0,1){{$}}268; GLOBAL-NEXT: safe accesses:269; GLOBAL-NEXT: %v = load i8, ptr %x, align 1270; CHECK-EMPTY:271entry:272  %x = alloca i32, align 4273  %v = load i8, ptr %x, align 1274  ret void275}276 277define void @LoadOutOfBounds() {278; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}}279; CHECK-NEXT: args uses:280; CHECK-NEXT: allocas uses:281; CHECK-NEXT: x[4]: [2,6){{$}}282; GLOBAL-NEXT: safe accesses:283; CHECK-EMPTY:284entry:285  %x = alloca i32, align 4286  %x2 = getelementptr i8, ptr %x, i64 2287  %v = load i32, ptr %x2, align 1288  ret void289}290 291; Leak through ret.292define ptr @Ret() {293; CHECK-LABEL: @Ret dso_preemptable{{$}}294; CHECK-NEXT: args uses:295; CHECK-NEXT: allocas uses:296; CHECK-NEXT: x[4]: full-set{{$}}297; GLOBAL-NEXT: safe accesses:298; CHECK-EMPTY:299entry:300  %x = alloca i32, align 4301  %x2 = getelementptr i8, ptr %x, i64 2302  ret ptr %x2303}304 305declare void @Foo(ptr %p)306 307define void @DirectCall() {308; CHECK-LABEL: @DirectCall dso_preemptable{{$}}309; CHECK-NEXT: args uses:310; CHECK-NEXT: allocas uses:311; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}}312; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}}313; GLOBAL-NEXT: safe accesses:314; CHECK-EMPTY:315entry:316  %x = alloca i64, align 4317  %x2 = getelementptr i16, ptr %x, i64 1318  call void @Foo(ptr %x2);319  ret void320}321 322; Indirect calls can not be analyzed (yet).323; FIXME: %p[]: full-set looks invalid324define void @IndirectCall(ptr %p) {325; CHECK-LABEL: @IndirectCall dso_preemptable{{$}}326; CHECK-NEXT: args uses:327; CHECK-NEXT: p[]: full-set{{$}}328; CHECK-NEXT: allocas uses:329; CHECK-NEXT: x[4]: full-set{{$}}330; GLOBAL-NEXT: safe accesses:331; CHECK-EMPTY:332entry:333  %x = alloca i32, align 4334  call void %p(ptr %x);335  ret void336}337 338define void @NonConstantOffset(i1 zeroext %z) {339; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}}340; CHECK-NEXT: args uses:341; CHECK-NEXT: allocas uses:342; FIXME: SCEV can't look through selects.343; CHECK-NEXT: x[4]: [0,4){{$}}344; GLOBAL-NEXT: safe accesses:345; GLOBAL-NEXT: store i8 0, ptr %x2, align 1346; CHECK-EMPTY:347entry:348  %x = alloca i32, align 4349  %idx = select i1 %z, i64 1, i64 2350  %x2 = getelementptr i8, ptr %x, i64 %idx351  store i8 0, ptr %x2, align 1352  ret void353}354 355define void @NegativeOffset() {356; CHECK-LABEL: @NegativeOffset dso_preemptable{{$}}357; CHECK-NEXT: args uses:358; CHECK-NEXT: allocas uses:359; CHECK-NEXT: x[40]: [-1600000000000,-1599999999996){{$}}360; GLOBAL-NEXT: safe accesses:361; CHECK-EMPTY:362entry:363  %x = alloca i32, i32 10, align 4364  %x2 = getelementptr i32, ptr %x, i64 -400000000000365  store i32 0, ptr %x2, align 1366  ret void367}368 369define void @PossiblyNegativeOffset(i16 %z) {370; CHECK-LABEL: @PossiblyNegativeOffset dso_preemptable{{$}}371; CHECK-NEXT: args uses:372; CHECK-NEXT: allocas uses:373; CHECK-NEXT: x[40]: [-131072,131072){{$}}374; GLOBAL-NEXT: safe accesses:375; CHECK-EMPTY:376entry:377  %x = alloca i32, i32 10, align 4378  %x2 = getelementptr i32, ptr %x, i16 %z379  store i32 0, ptr %x2, align 1380  ret void381}382 383define void @NonConstantOffsetOOB(i1 zeroext %z) {384; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}}385; CHECK-NEXT: args uses:386; CHECK-NEXT: allocas uses:387; CHECK-NEXT: x[4]: [0,6){{$}}388; GLOBAL-NEXT: safe accesses:389; CHECK-EMPTY:390entry:391  %x = alloca i32, align 4392  %idx = select i1 %z, i64 1, i64 4393  %x2 = getelementptr i8, ptr %x, i64 %idx394  store i8 0, ptr %x2, align 1395  ret void396}397 398define void @ArrayAlloca() {399; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}}400; CHECK-NEXT: args uses:401; CHECK-NEXT: allocas uses:402; CHECK-NEXT: x[40]: [36,40){{$}}403; GLOBAL-NEXT: safe accesses:404; GLOBAL-NEXT: store i32 0, ptr %x2, align 1405; CHECK-EMPTY:406entry:407  %x = alloca i32, i32 10, align 4408  %x2 = getelementptr i8, ptr %x, i64 36409  store i32 0, ptr %x2, align 1410  ret void411}412 413define void @ArrayAllocaOOB() {414; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}}415; CHECK-NEXT: args uses:416; CHECK-NEXT: allocas uses:417; CHECK-NEXT: x[40]: [37,41){{$}}418; GLOBAL-NEXT: safe accesses:419; CHECK-EMPTY:420entry:421  %x = alloca i32, i32 10, align 4422  %x2 = getelementptr i8, ptr %x, i64 37423  store i32 0, ptr %x2, align 1424  ret void425}426 427define void @DynamicAllocaUnused(i64 %size) {428; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}}429; CHECK-NEXT: args uses:430; CHECK-NEXT: allocas uses:431; CHECK-NEXT: x[0]: empty-set{{$}}432; GLOBAL-NEXT: safe accesses:433; CHECK-EMPTY:434entry:435  %x = alloca i32, i64 %size, align 16436  ret void437}438 439; Dynamic alloca with unknown size.440define void @DynamicAlloca(i64 %size) {441; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}}442; CHECK-NEXT: args uses:443; CHECK-NEXT: allocas uses:444; CHECK-NEXT: x[0]: [0,4){{$}}445; GLOBAL-NEXT: safe accesses:446; CHECK-EMPTY:447entry:448  %x = alloca i32, i64 %size, align 16449  store i32 0, ptr %x, align 1450  ret void451}452 453; Dynamic alloca with limited size.454; FIXME: could be proved safe. Implement.455define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) {456; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}}457; CHECK-NEXT: args uses:458; CHECK-NEXT: allocas uses:459; CHECK-NEXT: x[0]: [0,4){{$}}460; GLOBAL-NEXT: safe accesses:461; CHECK-EMPTY:462entry:463  %size = select i1 %z, i64 3, i64 5464  %x = alloca i32, i64 %size, align 16465  store i32 0, ptr %x, align 1466  ret void467}468 469define signext i8 @SimpleLoop() {470; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}}471; CHECK-NEXT: args uses:472; CHECK-NEXT: allocas uses:473; CHECK-NEXT: x[10]: [0,10){{$}}474; GLOBAL-NEXT: safe accesses:475; GLOBAL-NEXT: %load = load volatile i8, ptr %p.09, align 1476; CHECK-EMPTY:477entry:478  %x = alloca [10 x i8], align 1479  %lftr.limit = getelementptr inbounds [10 x i8], ptr %x, i64 0, i64 10480  br label %for.body481 482for.body:483  %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]484  %p.09 = phi ptr [ %x, %entry ], [ %incdec.ptr, %for.body ]485  %incdec.ptr = getelementptr inbounds i8, ptr %p.09, i64 1486  %load = load volatile i8, ptr %p.09, align 1487  %add = add i8 %load, %sum.010488  %exitcond = icmp eq ptr %incdec.ptr, %lftr.limit489  br i1 %exitcond, label %for.cond.cleanup, label %for.body490 491for.cond.cleanup:492  ret i8 %add493}494 495; OOB in a loop.496define signext i8 @SimpleLoopOOB() {497; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}}498; CHECK-NEXT: args uses:499; CHECK-NEXT: allocas uses:500; CHECK-NEXT: x[10]: [0,11){{$}}501; GLOBAL-NEXT: safe accesses:502; CHECK-EMPTY:503entry:504  %x = alloca [10 x i8], align 1505 ; 11 iterations506  %lftr.limit = getelementptr inbounds [10 x i8], ptr %x, i64 0, i64 11507  br label %for.body508 509for.body:510  %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]511  %p.09 = phi ptr [ %x, %entry ], [ %incdec.ptr, %for.body ]512  %incdec.ptr = getelementptr inbounds i8, ptr %p.09, i64 1513  %load = load volatile i8, ptr %p.09, align 1514  %add = add i8 %load, %sum.010515  %exitcond = icmp eq ptr %incdec.ptr, %lftr.limit516  br i1 %exitcond, label %for.cond.cleanup, label %for.body517 518for.cond.cleanup:519  ret i8 %add520}521 522define dso_local void @SizeCheck(i32 %sz) {523; CHECK-LABEL: @SizeCheck{{$}}524; CHECK-NEXT: args uses:525; CHECK-NEXT: allocas uses:526; CHECK-NEXT: x1[128]: [0,4294967295){{$}}527; GLOBAL-NEXT: safe accesses:528; CHECK-EMPTY:529entry:530  %x1 = alloca [128 x i8], align 16531  %cmp = icmp slt i32 %sz, 129532  br i1 %cmp, label %if.then, label %if.end533 534if.then:535  call void @llvm.memset.p0.i32(ptr nonnull align 16 %x1, i8 0, i32 %sz, i1 false)536  br label %if.end537 538if.end:539  ret void540}541 542; FIXME: scalable allocas are considered to be of size zero, and scalable accesses to be full-range.543; This effectively disables safety analysis for scalable allocations.544define void @Scalable(ptr %p, ptr %unused, <vscale x 4 x i32> %v) {545; CHECK-LABEL: @Scalable dso_preemptable{{$}}546; CHECK-NEXT: args uses:547; CHECK-NEXT:   p[]: full-set548; CHECK-NEXT:   unused[]: empty-set549; CHECK-NEXT: allocas uses:550; CHECK-NEXT:   x[0]: [0,1){{$}}551; GLOBAL-NEXT: safe accesses:552; GLOBAL-NEXT: store <vscale x 4 x i32> %v, ptr %p, align 4553; CHECK-EMPTY:554entry:555  %x = alloca <vscale x 4 x i32>, align 4556  store i8 0, ptr %x, align 1557  store <vscale x 4 x i32> %v, ptr %p, align 4558  ret void559}560 561%zerosize_type = type {}562 563define void @ZeroSize(ptr %p)  {564; CHECK-LABEL: @ZeroSize dso_preemptable{{$}}565; CHECK-NEXT: args uses:566; CHECK-NEXT:   p[]: empty-set567; CHECK-NEXT: allocas uses:568; CHECK-NEXT:   x[0]: empty-set569; GLOBAL-NEXT: safe accesses:570; GLOBAL-NEXT: store %zerosize_type undef, ptr %x, align 4571; GLOBAL-NEXT: store %zerosize_type undef, ptr undef, align 4572; GLOBAL-NEXT: load %zerosize_type, ptr %p, align573; CHECK-EMPTY:574entry:575  %x = alloca %zerosize_type, align 4576  store %zerosize_type undef, ptr %x, align 4577  store %zerosize_type undef, ptr undef, align 4578  %val = load %zerosize_type, ptr %p, align 4579  ret void580}581 582define void @OperandBundle() {583; CHECK-LABEL: @OperandBundle dso_preemptable{{$}}584; CHECK-NEXT: args uses:585; CHECK-NEXT: allocas uses:586; CHECK-NEXT:   a[4]: full-set587; GLOBAL-NEXT: safe accesses:588; CHECK-EMPTY:589entry:590  %a = alloca i32, align 4591  call void @LeakAddress() ["unknown"(ptr %a)]592  ret void593}594 595define void @ByVal(ptr byval(i16) %p) {596  ; CHECK-LABEL: @ByVal dso_preemptable{{$}}597  ; CHECK-NEXT: args uses:598  ; CHECK-NEXT: allocas uses:599  ; GLOBAL-NEXT: safe accesses:600  ; CHECK-EMPTY:601entry:602  ret void603}604 605define void @TestByVal() {606; CHECK-LABEL: @TestByVal dso_preemptable{{$}}607; CHECK-NEXT: args uses:608; CHECK-NEXT: allocas uses:609; CHECK-NEXT: x[2]: [0,2)610; CHECK-NEXT: y[8]: [0,2)611; GLOBAL-NEXT: safe accesses:612; GLOBAL-NEXT: call void @ByVal(ptr byval(i16) %x)613; GLOBAL-NEXT: call void @ByVal(ptr byval(i16) %y)614; CHECK-EMPTY:615entry:616  %x = alloca i16, align 4617  call void @ByVal(ptr byval(i16) %x)618 619  %y = alloca i64, align 4620  call void @ByVal(ptr byval(i16) %y)621 622  ret void623}624 625declare void @ByValArray(ptr byval([100000 x i64]) %p)626 627define void @TestByValArray() {628; CHECK-LABEL: @TestByValArray dso_preemptable{{$}}629; CHECK-NEXT: args uses:630; CHECK-NEXT: allocas uses:631; CHECK-NEXT: z[800000]: [500000,1300000)632; GLOBAL-NEXT: safe accesses:633; CHECK-EMPTY:634entry:635  %z = alloca [100000 x i64], align 4636  %z2 = getelementptr i8, ptr %z, i64 500000637  call void @ByValArray(ptr byval([100000 x i64]) %z2)638  ret void639}640 641define dso_local i8 @LoadMinInt64(ptr %p) {642  ; CHECK-LABEL: @LoadMinInt64{{$}}643  ; CHECK-NEXT: args uses:644  ; CHECK-NEXT: p[]: [-9223372036854775808,-9223372036854775807){{$}}645  ; CHECK-NEXT: allocas uses:646  ; GLOBAL-NEXT: safe accesses:647  ; GLOBAL-NEXT: load i8, ptr %p2, align 1648  ; CHECK-EMPTY:649  %p2 = getelementptr i8, ptr %p, i64 -9223372036854775808650  %v = load i8, ptr %p2, align 1651  ret i8 %v652}653 654define void @Overflow() {655; CHECK-LABEL: @Overflow dso_preemptable{{$}}656; CHECK-NEXT: args uses:657; CHECK-NEXT: allocas uses:658; LOCAL-NEXT: x[1]: empty-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}659; GLOBAL-NEXT: x[1]: full-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}660; GLOBAL-NEXT: safe accesses:661; CHECK-EMPTY:662entry:663  %x = alloca i8, align 4664  %x2 = getelementptr i8, ptr %x, i64 -9223372036854775808665  %v = call i8 @LoadMinInt64(ptr %x2)666  ret void667}668 669define void @DeadBlock(ptr %p) {670; CHECK-LABEL: @DeadBlock dso_preemptable{{$}}671; CHECK-NEXT: args uses:672; CHECK-NEXT: p[]: empty-set{{$}}673; CHECK-NEXT: allocas uses:674; CHECK-NEXT: x[1]: empty-set{{$}}675; GLOBAL-NEXT: safe accesses:676; GLOBAL-NEXT: store i8 5, ptr %x677; GLOBAL-NEXT: store i64 -5, ptr %p678; CHECK-EMPTY:679entry:680  %x = alloca i8, align 4681  br label %end682 683dead:684  store i8 5, ptr %x685  store i64 -5, ptr %p686  br label %end687 688end:689  ret void690}691 692define void @LifeNotStarted() {693; CHECK-LABEL: @LifeNotStarted dso_preemptable{{$}}694; CHECK-NEXT: args uses:695; CHECK-NEXT: allocas uses:696; CHECK: x[1]: full-set{{$}}697; CHECK: y[1]: full-set{{$}}698; CHECK: z[1]: full-set{{$}}699; GLOBAL-NEXT: safe accesses:700; CHECK-EMPTY:701entry:702  %x = alloca i8, align 4703  %y = alloca i8, align 4704  %z = alloca i8, align 4705 706  store i8 5, ptr %x707  %n = load i8, ptr %y708  call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)709 710  call void @llvm.lifetime.start.p0(ptr %x)711  call void @llvm.lifetime.start.p0(ptr %y)712  call void @llvm.lifetime.start.p0(ptr %z)713 714  ret void715}716 717define void @LifeOK() {718; CHECK-LABEL: @LifeOK dso_preemptable{{$}}719; CHECK-NEXT: args uses:720; CHECK-NEXT: allocas uses:721; CHECK: x[1]: [0,1){{$}}722; CHECK: y[1]: [0,1){{$}}723; CHECK: z[1]: [0,1){{$}}724; GLOBAL-NEXT: safe accesses:725; GLOBAL-NEXT: store i8 5, ptr %x726; GLOBAL-NEXT: %n = load i8, ptr %y727; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)728; CHECK-EMPTY:729entry:730  %x = alloca i8, align 4731  %y = alloca i8, align 4732  %z = alloca i8, align 4733 734  call void @llvm.lifetime.start.p0(ptr %x)735  call void @llvm.lifetime.start.p0(ptr %y)736  call void @llvm.lifetime.start.p0(ptr %z)737 738  store i8 5, ptr %x739  %n = load i8, ptr %y740  call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)741 742  ret void743}744 745define void @LifeEnded() {746; CHECK-LABEL: @LifeEnded dso_preemptable{{$}}747; CHECK-NEXT: args uses:748; CHECK-NEXT: allocas uses:749; CHECK: x[1]: full-set{{$}}750; CHECK: y[1]: full-set{{$}}751; CHECK: z[1]: full-set{{$}}752; GLOBAL-NEXT: safe accesses:753; CHECK-EMPTY:754entry:755  %x = alloca i8, align 4756  %y = alloca i8, align 4757  %z = alloca i8, align 4758 759  call void @llvm.lifetime.start.p0(ptr %x)760  call void @llvm.lifetime.start.p0(ptr %y)761  call void @llvm.lifetime.start.p0(ptr %z)762 763  call void @llvm.lifetime.end.p0(ptr %x)764  call void @llvm.lifetime.end.p0(ptr %y)765  call void @llvm.lifetime.end.p0(ptr %z)766 767  store i8 5, ptr %x768  %n = load i8, ptr %y769  call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)770 771  ret void772}773 774define void @TwoAllocasOK() {775; CHECK-LABEL: @TwoAllocasOK776; CHECK-NEXT: args uses:777; CHECK-NEXT: allocas uses:778; CHECK: a[4]: [0,1){{$}}779; CHECK: y[1]: [0,1){{$}}780; GLOBAL-NEXT: safe accesses:781; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 1, i1 false)782; CHECK-EMPTY:783entry:784  %a = alloca i32, align 4785  %y = alloca i8, align 4786  call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 1, i1 false)787  ret void788}789 790define void @TwoAllocasOOBDest() {791; CHECK-LABEL: @TwoAllocasOOBDest792; CHECK-NEXT: args uses:793; CHECK-NEXT: allocas uses:794; CHECK: a[4]: [0,4){{$}}795; CHECK: y[1]: [0,4){{$}}796; GLOBAL-NEXT: safe accesses:797; CHECK-EMPTY:798entry:799  %a = alloca i32, align 4800  %y = alloca i8, align 4801  call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 4, i1 false)802  ret void803}804 805define void @TwoAllocasOOBSource() {806; CHECK-LABEL: @TwoAllocasOOBSource807; CHECK-NEXT: args uses:808; CHECK-NEXT: allocas uses:809; CHECK: a[4]: [0,4){{$}}810; CHECK: y[1]: [0,4){{$}}811; GLOBAL-NEXT: safe accesses:812; CHECK-EMPTY:813entry:814  %a = alloca i32, align 4815  %y = alloca i8, align 4816  call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %y, i32 4, i1 false)817  ret void818}819 820define void @TwoAllocasOOBBoth() {821; CHECK-LABEL: @TwoAllocasOOBBoth822; CHECK-NEXT: args uses:823; CHECK-NEXT: allocas uses:824; CHECK: a[4]: [0,5){{$}}825; CHECK: y[1]: [0,5){{$}}826; GLOBAL-NEXT: safe accesses:827; CHECK-EMPTY:828entry:829  %a = alloca i32, align 4830  %y = alloca i8, align 4831  call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 5, i1 false)832  ret void833}834 835define void @MixedAccesses() {836; CHECK-LABEL: @MixedAccesses837; CHECK-NEXT: args uses:838; CHECK-NEXT: allocas uses:839; CHECK: a[4]: [0,5){{$}}840; GLOBAL-NEXT: safe accesses:841; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)842; CHECK-EMPTY:843entry:844  %a = alloca i32, align 4845  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 5, i1 false)846  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)847  ret void848}849 850define void @MixedAccesses2() {851; CHECK-LABEL: @MixedAccesses2852; CHECK-NEXT: args uses:853; CHECK-NEXT: allocas uses:854; CHECK: a[4]: [0,8){{$}}855; GLOBAL-NEXT: safe accesses:856; GLOBAL-NEXT: load i32, ptr %a, align 4857; CHECK-EMPTY:858entry:859  %a = alloca i32, align 4860  %n1 = load i64, ptr %a, align 4861  %n2 = load i32, ptr %a, align 4862  ret void863}864 865define void @MixedAccesses3(ptr %func) {866; CHECK-LABEL: @MixedAccesses3867; CHECK-NEXT: args uses:868; CHECK-NEXT: func[]: full-set869; CHECK-NEXT: allocas uses:870; CHECK: a[4]: full-set{{$}}871; GLOBAL-NEXT: safe accesses:872; GLOBAL-NEXT: load i32, ptr %a, align 4873; CHECK-EMPTY:874entry:875  %a = alloca i32, align 4876  %n2 = load i32, ptr %a, align 4877  call void %func(ptr %a)878  ret void879}880 881define void @MixedAccesses4() {882; CHECK-LABEL: @MixedAccesses4883; CHECK-NEXT: args uses:884; CHECK-NEXT: allocas uses:885; CHECK: a[4]: full-set{{$}}886; CHECK: a1[8]: [0,8){{$}}887; GLOBAL-NEXT: safe accesses:888; GLOBAL-NEXT: load i32, ptr %a, align 4889; CHECK-EMPTY:890entry:891  %a = alloca i32, align 4892  %a1 = alloca ptr, align 4893  %n2 = load i32, ptr %a, align 4894  store ptr %a, ptr %a1895  ret void896}897 898define ptr @MixedAccesses5(i1 %x, ptr %y) {899; CHECK-LABEL: @MixedAccesses5900; CHECK-NEXT: args uses:901; CHECK: y[]: full-set902; CHECK-NEXT: allocas uses:903; CHECK: a[4]: full-set{{$}}904; GLOBAL-NEXT: safe accesses:905; GLOBAL-NEXT: load i32, ptr %a, align 4906; CHECK-EMPTY:907entry:908  %a = alloca i32, align 4909  br i1 %x, label %tlabel, label %flabel910flabel:911  %n = load i32, ptr %a, align 4912  ret ptr %y913tlabel:914  ret ptr %a915}916 917define void @MixedAccesses6(ptr %arg) {918; CHECK-LABEL: @MixedAccesses6919; CHECK-NEXT: args uses:920; CHECK-NEXT: arg[]: [0,4)921; CHECK-NEXT: allocas uses:922; CHECK: a[4]: [0,4)923; GLOBAL-NEXT: safe accesses:924; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %arg, i32 4, i1 false)925; CHECK-EMPTY:926entry:927  %a = alloca i32, align 4928  call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %arg, i32 4, i1 false)929  ret void930}931 932define void @MixedAccesses7(i1 %cond, ptr %arg) {933; SECV doesn't support select, so we consider this non-stack-safe, even through934; it is.935;936; CHECK-LABEL: @MixedAccesses7937; CHECK-NEXT: args uses:938; CHECK-NEXT: arg[]: full-set939; CHECK-NEXT: allocas uses:940; CHECK: a[4]: full-set941; GLOBAL-NEXT: safe accesses:942; CHECK-EMPTY:943entry:944  %a = alloca i32, align 4945  %x1 = select i1 %cond, ptr %arg, ptr %a946  call void @llvm.memcpy.p0.p0.i32(ptr %x1, ptr %arg, i32 4, i1 false)947  ret void948}949 950define void @NoStackAccess(ptr %arg1, ptr %arg2) {951; CHECK-LABEL: @NoStackAccess952; CHECK-NEXT: args uses:953; CHECK-NEXT: arg1[]: [0,4)954; CHECK-NEXT: arg2[]: [0,4)955; CHECK-NEXT: allocas uses:956; CHECK: a[4]: empty-set{{$}}957; GLOBAL-NEXT: safe accesses:958; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg2, i32 4, i1 false)959; CHECK-EMPTY:960entry:961  %a = alloca i32, align 4962  call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg2, i32 4, i1 false)963  ret void964}965 966define void @DoubleLifetime() {967; CHECK-LABEL: @DoubleLifetime968; CHECK-NEXT: args uses:969; CHECK-NEXT: allocas uses:970; CHECK: a[4]: full-set{{$}}971; GLOBAL-NEXT: safe accesses:972; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)973; CHECK-EMPTY:974entry:975  %a = alloca i32, align 4976  call void @llvm.lifetime.start.p0(ptr %a)977  call void @llvm.lifetime.end.p0(ptr %a)978  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 true)979 980  call void @llvm.lifetime.start.p0(ptr %a)981  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)982  call void @llvm.lifetime.end.p0(ptr %a)983  ret void984}985 986define void @DoubleLifetime2() {987; CHECK-LABEL: @DoubleLifetime2988; CHECK-NEXT: args uses:989; CHECK-NEXT: allocas uses:990; CHECK: a[4]: full-set{{$}}991; GLOBAL-NEXT: safe accesses:992; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)993; CHECK-EMPTY:994entry:995  %a = alloca i32, align 4996  call void @llvm.lifetime.start.p0(ptr %a)997  call void @llvm.lifetime.end.p0(ptr %a)998  %n = load i32, ptr %a999 1000  call void @llvm.lifetime.start.p0(ptr %a)1001  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)1002  call void @llvm.lifetime.end.p0(ptr %a)1003  ret void1004}1005 1006define void @DoubleLifetime3() {1007; CHECK-LABEL: @DoubleLifetime31008; CHECK-NEXT: args uses:1009; CHECK-NEXT: allocas uses:1010; CHECK: a[4]: full-set{{$}}1011; GLOBAL-NEXT: safe accesses:1012; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)1013; CHECK-EMPTY:1014entry:1015  %a = alloca i32, align 41016  call void @llvm.lifetime.start.p0(ptr %a)1017  call void @llvm.lifetime.end.p0(ptr %a)1018  store i32 5, ptr %a1019 1020  call void @llvm.lifetime.start.p0(ptr %a)1021  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)1022  call void @llvm.lifetime.end.p0(ptr %a)1023  ret void1024}1025 1026define void @DoubleLifetime4() {1027; CHECK-LABEL: @DoubleLifetime41028; CHECK-NEXT: args uses:1029; CHECK-NEXT: allocas uses:1030; CHECK: a[4]: full-set{{$}}1031; GLOBAL-NEXT: safe accesses:1032; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)1033; CHECK-EMPTY:1034entry:1035  %a = alloca i32, align 41036  call void @llvm.lifetime.start.p0(ptr %a)1037  call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)1038  call void @llvm.lifetime.end.p0(ptr %a)1039  call void @unknown_call(ptr %a)1040  ret void1041}1042 1043define void @Cmpxchg4Arg(ptr %p) {1044; CHECK-LABEL: @Cmpxchg4Arg1045; CHECK-NEXT: args uses:1046; CHECK-NEXT: p[]: [0,4){{$}}1047; CHECK-NEXT: allocas uses:1048; GLOBAL-NEXT: safe accesses:1049; GLOBAL-NEXT: cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 11050; CHECK-EMPTY:1051entry:1052  cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 11053  ret void1054}1055 1056define void @AtomicRMW4Arg(ptr %p) {1057; CHECK-LABEL: @AtomicRMW4Arg1058; CHECK-NEXT: args uses:1059; CHECK-NEXT: p[]: [0,4){{$}}1060; CHECK-NEXT: allocas uses:1061; GLOBAL-NEXT: safe accesses:1062; GLOBAL-NEXT: atomicrmw add ptr %p, i32 1 monotonic, align 11063; CHECK-EMPTY:1064entry:1065  atomicrmw add ptr %p, i32 1 monotonic, align 11066  ret void1067}1068 1069define void @Cmpxchg4Alloca() {1070; CHECK-LABEL: @Cmpxchg4Alloca1071; CHECK-NEXT: args uses:1072; CHECK-NEXT: allocas uses:1073; CHECK-NEXT: x[4]: [0,4){{$}}1074; GLOBAL-NEXT: safe accesses:1075; GLOBAL-NEXT: cmpxchg ptr %x, i32 0, i32 1 monotonic monotonic, align 11076; CHECK-EMPTY:1077entry:1078  %x = alloca i32, align 41079  cmpxchg ptr %x, i32 0, i32 1 monotonic monotonic, align 11080  ret void1081}1082 1083define void @AtomicRMW4Alloca() {1084; CHECK-LABEL: @AtomicRMW4Alloca1085; CHECK-NEXT: args uses:1086; CHECK-NEXT: allocas uses:1087; CHECK-NEXT: x[4]: [0,4){{$}}1088; GLOBAL-NEXT: safe accesses:1089; GLOBAL-NEXT: atomicrmw add ptr %x, i32 1 monotonic, align 11090; CHECK-EMPTY:1091entry:1092  %x = alloca i32, align 41093  atomicrmw add ptr %x, i32 1 monotonic, align 11094  ret void1095}1096 1097define void @StoreArg(ptr %p) {1098; CHECK-LABEL: @StoreArg1099; CHECK-NEXT: args uses:1100; CHECK-NEXT: p[]: [0,4){{$}}1101; CHECK-NEXT: allocas uses:1102; GLOBAL-NEXT: safe accesses:1103; GLOBAL-NEXT: store i32 1, ptr %p1104; CHECK-EMPTY:1105entry:1106  store i32 1, ptr %p1107  ret void1108}1109 1110define void @NonPointer(ptr %p) {1111; CHECK-LABEL: @NonPointer1112; CHECK-NEXT: args uses:1113; LOCAL-NEXT: p[]: empty-set, @unknown_call_int(arg0, full-set)1114; GLOBAL-NEXT: p[]: full-set, @unknown_call_int(arg0, full-set)1115; CHECK-NEXT: allocas uses:1116; GLOBAL-NEXT: safe accesses:1117; CHECK-EMPTY:1118  %int = ptrtoint ptr %p to i641119  call void @unknown_call_int(i64 %int)1120  ret void1121}1122 1123@ifunc = dso_local ifunc i64 (ptr), ptr @ifunc_resolver1124 1125define dso_local void @CallIfunc(ptr noundef %uaddr) local_unnamed_addr {1126; CHECK-LABEL: @CallIfunc1127; CHECK-NEXT:  args uses:1128; CHECK-NEXT:    uaddr[]: full-set1129entry:1130  tail call i64 @ifunc(ptr noundef %uaddr)1131  ret void1132}1133 1134define dso_local ptr @ifunc_resolver() {1135entry:1136  ret ptr null1137}1138 1139declare void @llvm.lifetime.start.p0(ptr nocapture)1140declare void @llvm.lifetime.end.p0(ptr nocapture)1141