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
4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-unknown-linux-gnu"
7 @sink = global ptr null, align 8
9 declare void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 %len, i1 %isvolatile)
10 declare void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)
11 declare void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 %isvolatile)
12 declare void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 %len, i1 %isvolatile)
14 declare void @unknown_call(ptr %dest)
15 declare ptr @retptr(ptr returned)
18 define 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:
26 %x = alloca i32, align 4
27 store ptr %x, ptr @sink, align 8
31 define void @StoreInBounds() {
32 ; CHECK-LABEL: @StoreInBounds dso_preemptable{{$}}
33 ; CHECK-NEXT: args uses:
34 ; CHECK-NEXT: allocas uses:
35 ; CHECK-NEXT: x[4]: [0,1){{$}}
36 ; GLOBAL-NEXT: safe accesses:
37 ; GLOBAL-NEXT: store i8 0, ptr %x, align 1
40 %x = alloca i32, align 4
41 store i8 0, ptr %x, align 1
45 define void @StoreInBoundsCond(i64 %i) {
46 ; CHECK-LABEL: @StoreInBoundsCond dso_preemptable{{$}}
47 ; CHECK-NEXT: args uses:
48 ; CHECK-NEXT: allocas uses:
49 ; CHECK-NEXT: x[4]: full-set{{$}}
50 ; GLOBAL-NEXT: safe accesses:
51 ; GLOBAL-NEXT: store i8 0, ptr %x2, align 1
54 %x = alloca i32, align 4
55 %c1 = icmp sge i64 %i, 0
56 %c2 = icmp slt i64 %i, 4
57 br i1 %c1, label %c1.true, label %false
60 br i1 %c2, label %c2.true, label %false
63 %x2 = getelementptr i8, ptr %x, i64 %i
64 store i8 0, ptr %x2, align 1
71 define void @StoreInBoundsMinMax(i64 %i) {
72 ; CHECK-LABEL: @StoreInBoundsMinMax dso_preemptable{{$}}
73 ; CHECK-NEXT: args uses:
74 ; CHECK-NEXT: allocas uses:
75 ; CHECK-NEXT: x[4]: [0,4){{$}}
76 ; GLOBAL-NEXT: safe accesses:
77 ; GLOBAL-NEXT: store i8 0, ptr %x2, align 1
80 %x = alloca i32, align 4
81 %c1 = icmp sge i64 %i, 0
82 %i1 = select i1 %c1, i64 %i, i64 0
83 %c2 = icmp slt i64 %i1, 3
84 %i2 = select i1 %c2, i64 %i1, i64 3
85 %x2 = getelementptr i8, ptr %x, i64 %i2
86 store i8 0, ptr %x2, align 1
90 define void @StoreInBounds2() {
91 ; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}}
92 ; CHECK-NEXT: args uses:
93 ; CHECK-NEXT: allocas uses:
94 ; CHECK-NEXT: x[4]: [0,4){{$}}
95 ; GLOBAL-NEXT: safe accesses:
96 ; GLOBAL-NEXT: store i32 0, ptr %x, align 4
99 %x = alloca i32, align 4
100 store i32 0, ptr %x, align 4
104 define void @StoreInBounds3() {
105 ; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}}
106 ; CHECK-NEXT: args uses:
107 ; CHECK-NEXT: allocas uses:
108 ; CHECK-NEXT: x[4]: [2,3){{$}}
109 ; GLOBAL-NEXT: safe accesses:
110 ; GLOBAL-NEXT: store i8 0, ptr %x2, align 1
113 %x = alloca i32, align 4
114 %x2 = getelementptr i8, ptr %x, i64 2
115 store i8 0, ptr %x2, align 1
119 ; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.
120 define void @StoreInBounds4() {
121 ; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}}
122 ; CHECK-NEXT: args uses:
123 ; CHECK-NEXT: allocas uses:
124 ; CHECK-NEXT: x[4]: full-set{{$}}
125 ; GLOBAL-NEXT: safe accesses:
128 %x = alloca i32, align 4
129 %x1 = ptrtoint ptr %x to i64
131 %x3 = inttoptr i64 %x2 to ptr
132 store i8 0, ptr %x3, align 1
136 define void @StoreInBounds6() {
137 ; CHECK-LABEL: @StoreInBounds6 dso_preemptable{{$}}
138 ; CHECK-NEXT: args uses:
139 ; CHECK-NEXT: allocas uses:
140 ; GLOBAL-NEXT: x[4]: full-set, @retptr(arg0, [0,1)){{$}}
141 ; LOCAL-NEXT: x[4]: [0,1), @retptr(arg0, [0,1)){{$}}
142 ; GLOBAL-NEXT: safe accesses:
143 ; GLOBAL-NEXT: store i8 0, ptr %x2, align 1
146 %x = alloca i32, align 4
147 %x2 = call ptr @retptr(ptr %x)
148 store i8 0, ptr %x2, align 1
152 define dso_local void @WriteMinMax(ptr %p) {
153 ; CHECK-LABEL: @WriteMinMax{{$}}
154 ; CHECK-NEXT: args uses:
155 ; CHECK-NEXT: p[]: full-set
156 ; CHECK-NEXT: allocas uses:
157 ; GLOBAL-NEXT: safe accesses:
158 ; GLOBAL-NEXT: store i8 0, ptr %p1, align 1
159 ; GLOBAL-NEXT: store i8 0, ptr %p2, align 1
162 %p1 = getelementptr i8, ptr %p, i64 9223372036854775805
163 store i8 0, ptr %p1, align 1
164 %p2 = getelementptr i8, ptr %p, i64 -9223372036854775805
165 store i8 0, ptr %p2, align 1
169 define dso_local void @WriteMax(ptr %p) {
170 ; CHECK-LABEL: @WriteMax{{$}}
171 ; CHECK-NEXT: args uses:
172 ; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806)
173 ; CHECK-NEXT: allocas uses:
174 ; GLOBAL-NEXT: safe accesses:
175 ; GLOBAL-NEXT: call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 9223372036854775806, i1 false)
176 ; GLOBAL-NEXT: call void @llvm.memset.p0.i64(ptr %p2, i8 1, i64 9223372036854775806, i1 false)
179 call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 9223372036854775806, i1 0)
180 %p2 = getelementptr i8, ptr %p, i64 -9223372036854775807
181 call void @llvm.memset.p0.i64(ptr %p2, i8 1, i64 9223372036854775806, i1 0)
185 define void @StoreOutOfBounds() {
186 ; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}
187 ; CHECK-NEXT: args uses:
188 ; CHECK-NEXT: allocas uses:
189 ; CHECK-NEXT: x[4]: [2,6){{$}}
190 ; GLOBAL-NEXT: safe accesses:
193 %x = alloca i32, align 4
194 %x2 = getelementptr i8, ptr %x, i64 2
195 store i32 0, ptr %x2, align 1
199 define void @StoreOutOfBoundsCond(i64 %i) {
200 ; CHECK-LABEL: @StoreOutOfBoundsCond dso_preemptable{{$}}
201 ; CHECK-NEXT: args uses:
202 ; CHECK-NEXT: allocas uses:
203 ; CHECK-NEXT: x[4]: full-set{{$}}
204 ; GLOBAL-NEXT: safe accesses:
207 %x = alloca i32, align 4
208 %c1 = icmp sge i64 %i, 0
209 %c2 = icmp slt i64 %i, 5
210 br i1 %c1, label %c1.true, label %false
213 br i1 %c2, label %c2.true, label %false
216 %x2 = getelementptr i8, ptr %x, i64 %i
217 store i8 0, ptr %x2, align 1
224 define void @StoreOutOfBoundsCond2(i64 %i) {
225 ; CHECK-LABEL: @StoreOutOfBoundsCond2 dso_preemptable{{$}}
226 ; CHECK-NEXT: args uses:
227 ; CHECK-NEXT: allocas uses:
228 ; CHECK-NEXT: x[4]: full-set{{$}}
229 ; GLOBAL-NEXT: safe accesses:
232 %x = alloca i32, align 4
233 %c2 = icmp slt i64 %i, 5
234 br i1 %c2, label %c2.true, label %false
237 %x2 = getelementptr i8, ptr %x, i64 %i
238 store i8 0, ptr %x2, align 1
245 define void @StoreOutOfBounds2() {
246 ; CHECK-LABEL: @StoreOutOfBounds2 dso_preemptable{{$}}
247 ; CHECK-NEXT: args uses:
248 ; CHECK-NEXT: allocas uses:
249 ; GLOBAL-NEXT: x[4]: full-set, @retptr(arg0, [2,3)){{$}}
250 ; LOCAL-NEXT: x[4]: [2,6), @retptr(arg0, [2,3)){{$}}
251 ; GLOBAL-NEXT: safe accesses:
254 %x = alloca i32, align 4
255 %x2 = getelementptr i8, ptr %x, i64 2
256 %x3 = call ptr @retptr(ptr %x2)
257 store i32 0, ptr %x3, align 1
261 ; There is no difference in load vs store handling.
262 define void @LoadInBounds() {
263 ; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}}
264 ; CHECK-NEXT: args uses:
265 ; CHECK-NEXT: allocas uses:
266 ; CHECK-NEXT: x[4]: [0,1){{$}}
267 ; GLOBAL-NEXT: safe accesses:
268 ; GLOBAL-NEXT: %v = load i8, ptr %x, align 1
271 %x = alloca i32, align 4
272 %v = load i8, ptr %x, align 1
276 define void @LoadOutOfBounds() {
277 ; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}}
278 ; CHECK-NEXT: args uses:
279 ; CHECK-NEXT: allocas uses:
280 ; CHECK-NEXT: x[4]: [2,6){{$}}
281 ; GLOBAL-NEXT: safe accesses:
284 %x = alloca i32, align 4
285 %x2 = getelementptr i8, ptr %x, i64 2
286 %v = load i32, ptr %x2, align 1
292 ; CHECK-LABEL: @Ret dso_preemptable{{$}}
293 ; CHECK-NEXT: args uses:
294 ; CHECK-NEXT: allocas uses:
295 ; CHECK-NEXT: x[4]: full-set{{$}}
296 ; GLOBAL-NEXT: safe accesses:
299 %x = alloca i32, align 4
300 %x2 = getelementptr i8, ptr %x, i64 2
304 declare void @Foo(ptr %p)
306 define void @DirectCall() {
307 ; CHECK-LABEL: @DirectCall dso_preemptable{{$}}
308 ; CHECK-NEXT: args uses:
309 ; CHECK-NEXT: allocas uses:
310 ; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}}
311 ; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}}
312 ; GLOBAL-NEXT: safe accesses:
315 %x = alloca i64, align 4
316 %x2 = getelementptr i16, ptr %x, i64 1
317 call void @Foo(ptr %x2);
321 ; Indirect calls can not be analyzed (yet).
322 ; FIXME: %p[]: full-set looks invalid
323 define void @IndirectCall(ptr %p) {
324 ; CHECK-LABEL: @IndirectCall dso_preemptable{{$}}
325 ; CHECK-NEXT: args uses:
326 ; CHECK-NEXT: p[]: full-set{{$}}
327 ; CHECK-NEXT: allocas uses:
328 ; CHECK-NEXT: x[4]: full-set{{$}}
329 ; GLOBAL-NEXT: safe accesses:
332 %x = alloca i32, align 4
333 call void %p(ptr %x);
337 define void @NonConstantOffset(i1 zeroext %z) {
338 ; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}}
339 ; CHECK-NEXT: args uses:
340 ; CHECK-NEXT: allocas uses:
341 ; FIXME: SCEV can't look through selects.
342 ; CHECK-NEXT: x[4]: [0,4){{$}}
343 ; GLOBAL-NEXT: safe accesses:
344 ; GLOBAL-NEXT: store i8 0, ptr %x2, align 1
347 %x = alloca i32, align 4
348 %idx = select i1 %z, i64 1, i64 2
349 %x2 = getelementptr i8, ptr %x, i64 %idx
350 store i8 0, ptr %x2, align 1
354 define void @NegativeOffset() {
355 ; CHECK-LABEL: @NegativeOffset dso_preemptable{{$}}
356 ; CHECK-NEXT: args uses:
357 ; CHECK-NEXT: allocas uses:
358 ; CHECK-NEXT: x[40]: [-1600000000000,-1599999999996){{$}}
359 ; GLOBAL-NEXT: safe accesses:
362 %x = alloca i32, i32 10, align 4
363 %x2 = getelementptr i32, ptr %x, i64 -400000000000
364 store i32 0, ptr %x2, align 1
368 define void @PossiblyNegativeOffset(i16 %z) {
369 ; CHECK-LABEL: @PossiblyNegativeOffset dso_preemptable{{$}}
370 ; CHECK-NEXT: args uses:
371 ; CHECK-NEXT: allocas uses:
372 ; CHECK-NEXT: x[40]: [-131072,131072){{$}}
373 ; GLOBAL-NEXT: safe accesses:
376 %x = alloca i32, i32 10, align 4
377 %x2 = getelementptr i32, ptr %x, i16 %z
378 store i32 0, ptr %x2, align 1
382 define void @NonConstantOffsetOOB(i1 zeroext %z) {
383 ; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}}
384 ; CHECK-NEXT: args uses:
385 ; CHECK-NEXT: allocas uses:
386 ; CHECK-NEXT: x[4]: [0,6){{$}}
387 ; GLOBAL-NEXT: safe accesses:
390 %x = alloca i32, align 4
391 %idx = select i1 %z, i64 1, i64 4
392 %x2 = getelementptr i8, ptr %x, i64 %idx
393 store i8 0, ptr %x2, align 1
397 define void @ArrayAlloca() {
398 ; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}}
399 ; CHECK-NEXT: args uses:
400 ; CHECK-NEXT: allocas uses:
401 ; CHECK-NEXT: x[40]: [36,40){{$}}
402 ; GLOBAL-NEXT: safe accesses:
403 ; GLOBAL-NEXT: store i32 0, ptr %x2, align 1
406 %x = alloca i32, i32 10, align 4
407 %x2 = getelementptr i8, ptr %x, i64 36
408 store i32 0, ptr %x2, align 1
412 define void @ArrayAllocaOOB() {
413 ; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}}
414 ; CHECK-NEXT: args uses:
415 ; CHECK-NEXT: allocas uses:
416 ; CHECK-NEXT: x[40]: [37,41){{$}}
417 ; GLOBAL-NEXT: safe accesses:
420 %x = alloca i32, i32 10, align 4
421 %x2 = getelementptr i8, ptr %x, i64 37
422 store i32 0, ptr %x2, align 1
426 define void @DynamicAllocaUnused(i64 %size) {
427 ; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}}
428 ; CHECK-NEXT: args uses:
429 ; CHECK-NEXT: allocas uses:
430 ; CHECK-NEXT: x[0]: empty-set{{$}}
431 ; GLOBAL-NEXT: safe accesses:
434 %x = alloca i32, i64 %size, align 16
438 ; Dynamic alloca with unknown size.
439 define void @DynamicAlloca(i64 %size) {
440 ; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}}
441 ; CHECK-NEXT: args uses:
442 ; CHECK-NEXT: allocas uses:
443 ; CHECK-NEXT: x[0]: [0,4){{$}}
444 ; GLOBAL-NEXT: safe accesses:
447 %x = alloca i32, i64 %size, align 16
448 store i32 0, ptr %x, align 1
452 ; Dynamic alloca with limited size.
453 ; FIXME: could be proved safe. Implement.
454 define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) {
455 ; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}}
456 ; CHECK-NEXT: args uses:
457 ; CHECK-NEXT: allocas uses:
458 ; CHECK-NEXT: x[0]: [0,4){{$}}
459 ; GLOBAL-NEXT: safe accesses:
462 %size = select i1 %z, i64 3, i64 5
463 %x = alloca i32, i64 %size, align 16
464 store i32 0, ptr %x, align 1
468 define signext i8 @SimpleLoop() {
469 ; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}}
470 ; CHECK-NEXT: args uses:
471 ; CHECK-NEXT: allocas uses:
472 ; CHECK-NEXT: x[10]: [0,10){{$}}
473 ; GLOBAL-NEXT: safe accesses:
474 ; GLOBAL-NEXT: %load = load volatile i8, ptr %p.09, align 1
477 %x = alloca [10 x i8], align 1
478 %lftr.limit = getelementptr inbounds [10 x i8], ptr %x, i64 0, i64 10
482 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
483 %p.09 = phi ptr [ %x, %entry ], [ %incdec.ptr, %for.body ]
484 %incdec.ptr = getelementptr inbounds i8, ptr %p.09, i64 1
485 %load = load volatile i8, ptr %p.09, align 1
486 %add = add i8 %load, %sum.010
487 %exitcond = icmp eq ptr %incdec.ptr, %lftr.limit
488 br i1 %exitcond, label %for.cond.cleanup, label %for.body
495 define signext i8 @SimpleLoopOOB() {
496 ; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}}
497 ; CHECK-NEXT: args uses:
498 ; CHECK-NEXT: allocas uses:
499 ; CHECK-NEXT: x[10]: [0,11){{$}}
500 ; GLOBAL-NEXT: safe accesses:
503 %x = alloca [10 x i8], align 1
505 %lftr.limit = getelementptr inbounds [10 x i8], ptr %x, i64 0, i64 11
509 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
510 %p.09 = phi ptr [ %x, %entry ], [ %incdec.ptr, %for.body ]
511 %incdec.ptr = getelementptr inbounds i8, ptr %p.09, i64 1
512 %load = load volatile i8, ptr %p.09, align 1
513 %add = add i8 %load, %sum.010
514 %exitcond = icmp eq ptr %incdec.ptr, %lftr.limit
515 br i1 %exitcond, label %for.cond.cleanup, label %for.body
521 define dso_local void @SizeCheck(i32 %sz) {
522 ; CHECK-LABEL: @SizeCheck{{$}}
523 ; CHECK-NEXT: args uses:
524 ; CHECK-NEXT: allocas uses:
525 ; CHECK-NEXT: x1[128]: [0,4294967295){{$}}
526 ; GLOBAL-NEXT: safe accesses:
529 %x1 = alloca [128 x i8], align 16
530 %cmp = icmp slt i32 %sz, 129
531 br i1 %cmp, label %if.then, label %if.end
534 call void @llvm.memset.p0.i32(ptr nonnull align 16 %x1, i8 0, i32 %sz, i1 false)
541 ; FIXME: scalable allocas are considered to be of size zero, and scalable accesses to be full-range.
542 ; This effectively disables safety analysis for scalable allocations.
543 define void @Scalable(ptr %p, ptr %unused, <vscale x 4 x i32> %v) {
544 ; CHECK-LABEL: @Scalable dso_preemptable{{$}}
545 ; CHECK-NEXT: args uses:
546 ; CHECK-NEXT: p[]: full-set
547 ; CHECK-NEXT: unused[]: empty-set
548 ; CHECK-NEXT: allocas uses:
549 ; CHECK-NEXT: x[0]: [0,1){{$}}
550 ; GLOBAL-NEXT: safe accesses:
551 ; GLOBAL-NEXT: store <vscale x 4 x i32> %v, ptr %p, align 4
554 %x = alloca <vscale x 4 x i32>, align 4
555 store i8 0, ptr %x, align 1
556 store <vscale x 4 x i32> %v, ptr %p, align 4
560 %zerosize_type = type {}
562 define void @ZeroSize(ptr %p) {
563 ; CHECK-LABEL: @ZeroSize dso_preemptable{{$}}
564 ; CHECK-NEXT: args uses:
565 ; CHECK-NEXT: p[]: empty-set
566 ; CHECK-NEXT: allocas uses:
567 ; CHECK-NEXT: x[0]: empty-set
568 ; GLOBAL-NEXT: safe accesses:
569 ; GLOBAL-NEXT: store %zerosize_type undef, ptr %x, align 4
570 ; GLOBAL-NEXT: store %zerosize_type undef, ptr undef, align 4
571 ; GLOBAL-NEXT: load %zerosize_type, ptr %p, align
574 %x = alloca %zerosize_type, align 4
575 store %zerosize_type undef, ptr %x, align 4
576 store %zerosize_type undef, ptr undef, align 4
577 %val = load %zerosize_type, ptr %p, align 4
581 define void @OperandBundle() {
582 ; CHECK-LABEL: @OperandBundle dso_preemptable{{$}}
583 ; CHECK-NEXT: args uses:
584 ; CHECK-NEXT: allocas uses:
585 ; CHECK-NEXT: a[4]: full-set
586 ; GLOBAL-NEXT: safe accesses:
589 %a = alloca i32, align 4
590 call void @LeakAddress() ["unknown"(ptr %a)]
594 define void @ByVal(ptr byval(i16) %p) {
595 ; CHECK-LABEL: @ByVal dso_preemptable{{$}}
596 ; CHECK-NEXT: args uses:
597 ; CHECK-NEXT: allocas uses:
598 ; GLOBAL-NEXT: safe accesses:
604 define void @TestByVal() {
605 ; CHECK-LABEL: @TestByVal dso_preemptable{{$}}
606 ; CHECK-NEXT: args uses:
607 ; CHECK-NEXT: allocas uses:
608 ; CHECK-NEXT: x[2]: [0,2)
609 ; CHECK-NEXT: y[8]: [0,2)
610 ; GLOBAL-NEXT: safe accesses:
611 ; GLOBAL-NEXT: call void @ByVal(ptr byval(i16) %x)
612 ; GLOBAL-NEXT: call void @ByVal(ptr byval(i16) %y)
615 %x = alloca i16, align 4
616 call void @ByVal(ptr byval(i16) %x)
618 %y = alloca i64, align 4
619 call void @ByVal(ptr byval(i16) %y)
624 declare void @ByValArray(ptr byval([100000 x i64]) %p)
626 define void @TestByValArray() {
627 ; CHECK-LABEL: @TestByValArray dso_preemptable{{$}}
628 ; CHECK-NEXT: args uses:
629 ; CHECK-NEXT: allocas uses:
630 ; CHECK-NEXT: z[800000]: [500000,1300000)
631 ; GLOBAL-NEXT: safe accesses:
634 %z = alloca [100000 x i64], align 4
635 %z2 = getelementptr i8, ptr %z, i64 500000
636 call void @ByValArray(ptr byval([100000 x i64]) %z2)
640 define dso_local i8 @LoadMinInt64(ptr %p) {
641 ; CHECK-LABEL: @LoadMinInt64{{$}}
642 ; CHECK-NEXT: args uses:
643 ; CHECK-NEXT: p[]: [-9223372036854775808,-9223372036854775807){{$}}
644 ; CHECK-NEXT: allocas uses:
645 ; GLOBAL-NEXT: safe accesses:
646 ; GLOBAL-NEXT: load i8, ptr %p2, align 1
648 %p2 = getelementptr i8, ptr %p, i64 -9223372036854775808
649 %v = load i8, ptr %p2, align 1
653 define void @Overflow() {
654 ; CHECK-LABEL: @Overflow dso_preemptable{{$}}
655 ; CHECK-NEXT: args uses:
656 ; CHECK-NEXT: allocas uses:
657 ; LOCAL-NEXT: x[1]: empty-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}
658 ; GLOBAL-NEXT: x[1]: full-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}
659 ; GLOBAL-NEXT: safe accesses:
662 %x = alloca i8, align 4
663 %x2 = getelementptr i8, ptr %x, i64 -9223372036854775808
664 %v = call i8 @LoadMinInt64(ptr %x2)
668 define void @DeadBlock(ptr %p) {
669 ; CHECK-LABEL: @DeadBlock dso_preemptable{{$}}
670 ; CHECK-NEXT: args uses:
671 ; CHECK-NEXT: p[]: empty-set{{$}}
672 ; CHECK-NEXT: allocas uses:
673 ; CHECK-NEXT: x[1]: empty-set{{$}}
674 ; GLOBAL-NEXT: safe accesses:
675 ; GLOBAL-NEXT: store i8 5, ptr %x
676 ; GLOBAL-NEXT: store i64 -5, ptr %p
679 %x = alloca i8, align 4
691 define void @LifeNotStarted() {
692 ; CHECK-LABEL: @LifeNotStarted dso_preemptable{{$}}
693 ; CHECK-NEXT: args uses:
694 ; CHECK-NEXT: allocas uses:
695 ; CHECK: x[1]: full-set{{$}}
696 ; CHECK: y[1]: full-set{{$}}
697 ; CHECK: z[1]: full-set{{$}}
698 ; GLOBAL-NEXT: safe accesses:
701 %x = alloca i8, align 4
702 %y = alloca i8, align 4
703 %z = alloca i8, align 4
707 call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
709 call void @llvm.lifetime.start.p0(i64 1, ptr %x)
710 call void @llvm.lifetime.start.p0(i64 1, ptr %y)
711 call void @llvm.lifetime.start.p0(i64 1, ptr %z)
716 define void @LifeOK() {
717 ; CHECK-LABEL: @LifeOK dso_preemptable{{$}}
718 ; CHECK-NEXT: args uses:
719 ; CHECK-NEXT: allocas uses:
720 ; CHECK: x[1]: [0,1){{$}}
721 ; CHECK: y[1]: [0,1){{$}}
722 ; CHECK: z[1]: [0,1){{$}}
723 ; GLOBAL-NEXT: safe accesses:
724 ; GLOBAL-NEXT: store i8 5, ptr %x
725 ; GLOBAL-NEXT: %n = load i8, ptr %y
726 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
729 %x = alloca i8, align 4
730 %y = alloca i8, align 4
731 %z = alloca i8, align 4
733 call void @llvm.lifetime.start.p0(i64 1, ptr %x)
734 call void @llvm.lifetime.start.p0(i64 1, ptr %y)
735 call void @llvm.lifetime.start.p0(i64 1, ptr %z)
739 call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
744 define void @LifeEnded() {
745 ; CHECK-LABEL: @LifeEnded dso_preemptable{{$}}
746 ; CHECK-NEXT: args uses:
747 ; CHECK-NEXT: allocas uses:
748 ; CHECK: x[1]: full-set{{$}}
749 ; CHECK: y[1]: full-set{{$}}
750 ; CHECK: z[1]: full-set{{$}}
751 ; GLOBAL-NEXT: safe accesses:
754 %x = alloca i8, align 4
755 %y = alloca i8, align 4
756 %z = alloca i8, align 4
758 call void @llvm.lifetime.start.p0(i64 1, ptr %x)
759 call void @llvm.lifetime.start.p0(i64 1, ptr %y)
760 call void @llvm.lifetime.start.p0(i64 1, ptr %z)
762 call void @llvm.lifetime.end.p0(i64 1, ptr %x)
763 call void @llvm.lifetime.end.p0(i64 1, ptr %y)
764 call void @llvm.lifetime.end.p0(i64 1, ptr %z)
768 call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
773 define void @TwoAllocasOK() {
774 ; CHECK-LABEL: @TwoAllocasOK
775 ; CHECK-NEXT: args uses:
776 ; CHECK-NEXT: allocas uses:
777 ; CHECK: a[4]: [0,1){{$}}
778 ; CHECK: y[1]: [0,1){{$}}
779 ; GLOBAL-NEXT: safe accesses:
780 ; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 1, i1 false)
783 %a = alloca i32, align 4
784 %y = alloca i8, align 4
785 call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 1, i1 false)
789 define void @TwoAllocasOOBDest() {
790 ; CHECK-LABEL: @TwoAllocasOOBDest
791 ; CHECK-NEXT: args uses:
792 ; CHECK-NEXT: allocas uses:
793 ; CHECK: a[4]: [0,4){{$}}
794 ; CHECK: y[1]: [0,4){{$}}
795 ; GLOBAL-NEXT: safe accesses:
798 %a = alloca i32, align 4
799 %y = alloca i8, align 4
800 call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 4, i1 false)
804 define void @TwoAllocasOOBSource() {
805 ; CHECK-LABEL: @TwoAllocasOOBSource
806 ; CHECK-NEXT: args uses:
807 ; CHECK-NEXT: allocas uses:
808 ; CHECK: a[4]: [0,4){{$}}
809 ; CHECK: y[1]: [0,4){{$}}
810 ; GLOBAL-NEXT: safe accesses:
813 %a = alloca i32, align 4
814 %y = alloca i8, align 4
815 call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %y, i32 4, i1 false)
819 define void @TwoAllocasOOBBoth() {
820 ; CHECK-LABEL: @TwoAllocasOOBBoth
821 ; CHECK-NEXT: args uses:
822 ; CHECK-NEXT: allocas uses:
823 ; CHECK: a[4]: [0,5){{$}}
824 ; CHECK: y[1]: [0,5){{$}}
825 ; GLOBAL-NEXT: safe accesses:
828 %a = alloca i32, align 4
829 %y = alloca i8, align 4
830 call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 5, i1 false)
834 define void @MixedAccesses() {
835 ; CHECK-LABEL: @MixedAccesses
836 ; CHECK-NEXT: args uses:
837 ; CHECK-NEXT: allocas uses:
838 ; CHECK: a[4]: [0,5){{$}}
839 ; GLOBAL-NEXT: safe accesses:
840 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
843 %a = alloca i32, align 4
844 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 5, i1 false)
845 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
849 define void @MixedAccesses2() {
850 ; CHECK-LABEL: @MixedAccesses2
851 ; CHECK-NEXT: args uses:
852 ; CHECK-NEXT: allocas uses:
853 ; CHECK: a[4]: [0,8){{$}}
854 ; GLOBAL-NEXT: safe accesses:
855 ; GLOBAL-NEXT: load i32, ptr %a, align 4
858 %a = alloca i32, align 4
859 %n1 = load i64, ptr %a, align 4
860 %n2 = load i32, ptr %a, align 4
864 define void @MixedAccesses3(ptr %func) {
865 ; CHECK-LABEL: @MixedAccesses3
866 ; CHECK-NEXT: args uses:
867 ; CHECK-NEXT: func[]: full-set
868 ; CHECK-NEXT: allocas uses:
869 ; CHECK: a[4]: full-set{{$}}
870 ; GLOBAL-NEXT: safe accesses:
871 ; GLOBAL-NEXT: load i32, ptr %a, align 4
874 %a = alloca i32, align 4
875 %n2 = load i32, ptr %a, align 4
876 call void %func(ptr %a)
880 define void @MixedAccesses4() {
881 ; CHECK-LABEL: @MixedAccesses4
882 ; CHECK-NEXT: args uses:
883 ; CHECK-NEXT: allocas uses:
884 ; CHECK: a[4]: full-set{{$}}
885 ; CHECK: a1[8]: [0,8){{$}}
886 ; GLOBAL-NEXT: safe accesses:
887 ; GLOBAL-NEXT: load i32, ptr %a, align 4
890 %a = alloca i32, align 4
891 %a1 = alloca ptr, align 4
892 %n2 = load i32, ptr %a, align 4
893 store ptr %a, ptr %a1
897 define ptr @MixedAccesses5(i1 %x, ptr %y) {
898 ; CHECK-LABEL: @MixedAccesses5
899 ; CHECK-NEXT: args uses:
900 ; CHECK: y[]: full-set
901 ; CHECK-NEXT: allocas uses:
902 ; CHECK: a[4]: full-set{{$}}
903 ; GLOBAL-NEXT: safe accesses:
904 ; GLOBAL-NEXT: load i32, ptr %a, align 4
907 %a = alloca i32, align 4
908 br i1 %x, label %tlabel, label %flabel
910 %n = load i32, ptr %a, align 4
916 define void @MixedAccesses6(ptr %arg) {
917 ; CHECK-LABEL: @MixedAccesses6
918 ; CHECK-NEXT: args uses:
919 ; CHECK-NEXT: arg[]: [0,4)
920 ; CHECK-NEXT: allocas uses:
922 ; GLOBAL-NEXT: safe accesses:
923 ; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %arg, i32 4, i1 false)
926 %a = alloca i32, align 4
927 call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %arg, i32 4, i1 false)
931 define void @MixedAccesses7(i1 %cond, ptr %arg) {
932 ; SECV doesn't support select, so we consider this non-stack-safe, even through
935 ; CHECK-LABEL: @MixedAccesses7
936 ; CHECK-NEXT: args uses:
937 ; CHECK-NEXT: arg[]: full-set
938 ; CHECK-NEXT: allocas uses:
939 ; CHECK: a[4]: full-set
940 ; GLOBAL-NEXT: safe accesses:
943 %a = alloca i32, align 4
944 %x1 = select i1 %cond, ptr %arg, ptr %a
945 call void @llvm.memcpy.p0.p0.i32(ptr %x1, ptr %arg, i32 4, i1 false)
949 define void @NoStackAccess(ptr %arg1, ptr %arg2) {
950 ; CHECK-LABEL: @NoStackAccess
951 ; CHECK-NEXT: args uses:
952 ; CHECK-NEXT: arg1[]: [0,4)
953 ; CHECK-NEXT: arg2[]: [0,4)
954 ; CHECK-NEXT: allocas uses:
955 ; CHECK: a[4]: empty-set{{$}}
956 ; GLOBAL-NEXT: safe accesses:
957 ; GLOBAL-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg2, i32 4, i1 false)
960 %a = alloca i32, align 4
961 call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg2, i32 4, i1 false)
965 define void @DoubleLifetime() {
966 ; CHECK-LABEL: @DoubleLifetime
967 ; CHECK-NEXT: args uses:
968 ; CHECK-NEXT: allocas uses:
969 ; CHECK: a[4]: full-set{{$}}
970 ; GLOBAL-NEXT: safe accesses:
971 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
974 %a = alloca i32, align 4
975 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
976 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
977 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 true)
979 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
980 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
981 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
985 define void @DoubleLifetime2() {
986 ; CHECK-LABEL: @DoubleLifetime2
987 ; CHECK-NEXT: args uses:
988 ; CHECK-NEXT: allocas uses:
989 ; CHECK: a[4]: full-set{{$}}
990 ; GLOBAL-NEXT: safe accesses:
991 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
994 %a = alloca i32, align 4
995 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
996 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
997 %n = load i32, ptr %a
999 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1000 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1001 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1005 define void @DoubleLifetime3() {
1006 ; CHECK-LABEL: @DoubleLifetime3
1007 ; CHECK-NEXT: args uses:
1008 ; CHECK-NEXT: allocas uses:
1009 ; CHECK: a[4]: full-set{{$}}
1010 ; GLOBAL-NEXT: safe accesses:
1011 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1014 %a = alloca i32, align 4
1015 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1016 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1019 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1020 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1021 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1025 define void @DoubleLifetime4() {
1026 ; CHECK-LABEL: @DoubleLifetime4
1027 ; CHECK-NEXT: args uses:
1028 ; CHECK-NEXT: allocas uses:
1029 ; CHECK: a[4]: full-set{{$}}
1030 ; GLOBAL-NEXT: safe accesses:
1031 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1034 %a = alloca i32, align 4
1035 call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1036 call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1037 call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1038 call void @unknown_call(ptr %a)
1042 define void @Cmpxchg4Arg(ptr %p) {
1043 ; CHECK-LABEL: @Cmpxchg4Arg
1044 ; CHECK-NEXT: args uses:
1045 ; CHECK-NEXT: p[]: [0,4){{$}}
1046 ; CHECK-NEXT: allocas uses:
1047 ; GLOBAL-NEXT: safe accesses:
1048 ; GLOBAL-NEXT: cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 1
1051 cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 1
1055 define void @AtomicRMW4Arg(ptr %p) {
1056 ; CHECK-LABEL: @AtomicRMW4Arg
1057 ; CHECK-NEXT: args uses:
1058 ; CHECK-NEXT: p[]: [0,4){{$}}
1059 ; CHECK-NEXT: allocas uses:
1060 ; GLOBAL-NEXT: safe accesses:
1061 ; GLOBAL-NEXT: atomicrmw add ptr %p, i32 1 monotonic, align 1
1064 atomicrmw add ptr %p, i32 1 monotonic, align 1
1068 define void @Cmpxchg4Alloca() {
1069 ; CHECK-LABEL: @Cmpxchg4Alloca
1070 ; CHECK-NEXT: args uses:
1071 ; CHECK-NEXT: allocas uses:
1072 ; CHECK-NEXT: x[4]: [0,4){{$}}
1073 ; GLOBAL-NEXT: safe accesses:
1074 ; GLOBAL-NEXT: cmpxchg ptr %x, i32 0, i32 1 monotonic monotonic, align 1
1077 %x = alloca i32, align 4
1078 cmpxchg ptr %x, i32 0, i32 1 monotonic monotonic, align 1
1082 define void @AtomicRMW4Alloca() {
1083 ; CHECK-LABEL: @AtomicRMW4Alloca
1084 ; CHECK-NEXT: args uses:
1085 ; CHECK-NEXT: allocas uses:
1086 ; CHECK-NEXT: x[4]: [0,4){{$}}
1087 ; GLOBAL-NEXT: safe accesses:
1088 ; GLOBAL-NEXT: atomicrmw add ptr %x, i32 1 monotonic, align 1
1091 %x = alloca i32, align 4
1092 atomicrmw add ptr %x, i32 1 monotonic, align 1
1096 define void @StoreArg(ptr %p) {
1097 ; CHECK-LABEL: @StoreArg
1098 ; CHECK-NEXT: args uses:
1099 ; CHECK-NEXT: p[]: [0,4){{$}}
1100 ; CHECK-NEXT: allocas uses:
1101 ; GLOBAL-NEXT: safe accesses:
1102 ; GLOBAL-NEXT: store i32 1, ptr %p
1109 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
1110 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)