1 ; RUN: opt -S -analyze -stack-safety-local < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,LOCAL
2 ; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,LOCAL
3 ; RUN: opt -S -analyze -stack-safety < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,GLOBAL
4 ; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL
6 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 target triple = "x86_64-unknown-linux-gnu"
9 @sink = global i8* null, align 8
11 declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
12 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
13 declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
14 declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile)
17 define void @LeakAddress() {
18 ; CHECK-LABEL: @LeakAddress dso_preemptable{{$}}
19 ; CHECK-NEXT: args uses:
20 ; CHECK-NEXT: allocas uses:
21 ; CHECK-NEXT: x[4]: full-set{{$}}
24 %x = alloca i32, align 4
25 %x1 = bitcast i32* %x to i8*
26 store i8* %x1, i8** @sink, align 8
30 define void @StoreInBounds() {
31 ; CHECK-LABEL: @StoreInBounds dso_preemptable{{$}}
32 ; CHECK-NEXT: args uses:
33 ; CHECK-NEXT: allocas uses:
34 ; CHECK-NEXT: x[4]: [0,1){{$}}
37 %x = alloca i32, align 4
38 %x1 = bitcast i32* %x to i8*
39 store i8 0, i8* %x1, align 1
43 define void @StoreInBounds2() {
44 ; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}}
45 ; CHECK-NEXT: args uses:
46 ; CHECK-NEXT: allocas uses:
47 ; CHECK-NEXT: x[4]: [0,4){{$}}
50 %x = alloca i32, align 4
51 store i32 0, i32* %x, align 4
55 define void @StoreInBounds3() {
56 ; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}}
57 ; CHECK-NEXT: args uses:
58 ; CHECK-NEXT: allocas uses:
59 ; CHECK-NEXT: x[4]: [2,3){{$}}
62 %x = alloca i32, align 4
63 %x1 = bitcast i32* %x to i8*
64 %x2 = getelementptr i8, i8* %x1, i64 2
65 store i8 0, i8* %x2, align 1
69 ; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.
70 define void @StoreInBounds4() {
71 ; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}}
72 ; CHECK-NEXT: args uses:
73 ; CHECK-NEXT: allocas uses:
74 ; CHECK-NEXT: x[4]: full-set{{$}}
77 %x = alloca i32, align 4
78 %x1 = ptrtoint i32* %x to i64
80 %x3 = inttoptr i64 %x2 to i8*
81 store i8 0, i8* %x3, align 1
85 define dso_local void @WriteMinMax(i8* %p) {
86 ; CHECK-LABEL: @WriteMinMax{{$}}
87 ; CHECK-NEXT: args uses:
88 ; CHECK-NEXT: p[]: full-set
89 ; CHECK-NEXT: allocas uses:
92 %p1 = getelementptr i8, i8* %p, i64 9223372036854775805
93 store i8 0, i8* %p1, align 1
94 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775805
95 store i8 0, i8* %p2, align 1
99 define dso_local void @WriteMax(i8* %p) {
100 ; CHECK-LABEL: @WriteMax{{$}}
101 ; CHECK-NEXT: args uses:
102 ; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806)
103 ; CHECK-NEXT: allocas uses:
106 call void @llvm.memset.p0i8.i64(i8* %p, i8 1, i64 9223372036854775806, i1 0)
107 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775807
108 call void @llvm.memset.p0i8.i64(i8* %p2, i8 1, i64 9223372036854775806, i1 0)
112 define void @StoreOutOfBounds() {
113 ; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}
114 ; CHECK-NEXT: args uses:
115 ; CHECK-NEXT: allocas uses:
116 ; CHECK-NEXT: x[4]: [2,6){{$}}
119 %x = alloca i32, align 4
120 %x1 = bitcast i32* %x to i8*
121 %x2 = getelementptr i8, i8* %x1, i64 2
122 %x3 = bitcast i8* %x2 to i32*
123 store i32 0, i32* %x3, align 1
127 ; There is no difference in load vs store handling.
128 define void @LoadInBounds() {
129 ; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}}
130 ; CHECK-NEXT: args uses:
131 ; CHECK-NEXT: allocas uses:
132 ; CHECK-NEXT: x[4]: [0,1){{$}}
135 %x = alloca i32, align 4
136 %x1 = bitcast i32* %x to i8*
137 %v = load i8, i8* %x1, align 1
141 define void @LoadOutOfBounds() {
142 ; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}}
143 ; CHECK-NEXT: args uses:
144 ; CHECK-NEXT: allocas uses:
145 ; CHECK-NEXT: x[4]: [2,6){{$}}
148 %x = alloca i32, align 4
149 %x1 = bitcast i32* %x to i8*
150 %x2 = getelementptr i8, i8* %x1, i64 2
151 %x3 = bitcast i8* %x2 to i32*
152 %v = load i32, i32* %x3, align 1
158 ; CHECK-LABEL: @Ret dso_preemptable{{$}}
159 ; CHECK-NEXT: args uses:
160 ; CHECK-NEXT: allocas uses:
161 ; CHECK-NEXT: x[4]: full-set{{$}}
164 %x = alloca i32, align 4
165 %x1 = bitcast i32* %x to i8*
166 %x2 = getelementptr i8, i8* %x1, i64 2
170 declare void @Foo(i16* %p)
172 define void @DirectCall() {
173 ; CHECK-LABEL: @DirectCall dso_preemptable{{$}}
174 ; CHECK-NEXT: args uses:
175 ; CHECK-NEXT: allocas uses:
176 ; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}}
177 ; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}}
180 %x = alloca i64, align 4
181 %x1 = bitcast i64* %x to i16*
182 %x2 = getelementptr i16, i16* %x1, i64 1
183 call void @Foo(i16* %x2);
187 ; Indirect calls can not be analyzed (yet).
188 ; FIXME: %p[]: full-set looks invalid
189 define void @IndirectCall(void (i8*)* %p) {
190 ; CHECK-LABEL: @IndirectCall dso_preemptable{{$}}
191 ; CHECK-NEXT: args uses:
192 ; CHECK-NEXT: p[]: full-set{{$}}
193 ; CHECK-NEXT: allocas uses:
194 ; CHECK-NEXT: x[4]: full-set{{$}}
197 %x = alloca i32, align 4
198 %x1 = bitcast i32* %x to i8*
199 call void %p(i8* %x1);
203 define void @NonConstantOffset(i1 zeroext %z) {
204 ; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}}
205 ; CHECK-NEXT: args uses:
206 ; CHECK-NEXT: allocas uses:
207 ; FIXME: SCEV can't look through selects.
208 ; CHECK-NEXT: x[4]: [0,4){{$}}
211 %x = alloca i32, align 4
212 %x1 = bitcast i32* %x to i8*
213 %idx = select i1 %z, i64 1, i64 2
214 %x2 = getelementptr i8, i8* %x1, i64 %idx
215 store i8 0, i8* %x2, align 1
219 define void @NegativeOffset() {
220 ; CHECK-LABEL: @NegativeOffset dso_preemptable{{$}}
221 ; CHECK-NEXT: args uses:
222 ; CHECK-NEXT: allocas uses:
223 ; CHECK-NEXT: x[40]: [-1600000000000,-1599999999996){{$}}
226 %x = alloca i32, i32 10, align 4
227 %x2 = getelementptr i32, i32* %x, i64 -400000000000
228 store i32 0, i32* %x2, align 1
232 define void @PossiblyNegativeOffset(i16 %z) {
233 ; CHECK-LABEL: @PossiblyNegativeOffset dso_preemptable{{$}}
234 ; CHECK-NEXT: args uses:
235 ; CHECK-NEXT: allocas uses:
236 ; CHECK-NEXT: x[40]: [-131072,131072){{$}}
239 %x = alloca i32, i32 10, align 4
240 %x2 = getelementptr i32, i32* %x, i16 %z
241 store i32 0, i32* %x2, align 1
245 define void @NonConstantOffsetOOB(i1 zeroext %z) {
246 ; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}}
247 ; CHECK-NEXT: args uses:
248 ; CHECK-NEXT: allocas uses:
249 ; CHECK-NEXT: x[4]: [0,6){{$}}
252 %x = alloca i32, align 4
253 %x1 = bitcast i32* %x to i8*
254 %idx = select i1 %z, i64 1, i64 4
255 %x2 = getelementptr i8, i8* %x1, i64 %idx
256 store i8 0, i8* %x2, align 1
260 define void @ArrayAlloca() {
261 ; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}}
262 ; CHECK-NEXT: args uses:
263 ; CHECK-NEXT: allocas uses:
264 ; CHECK-NEXT: x[40]: [36,40){{$}}
267 %x = alloca i32, i32 10, align 4
268 %x1 = bitcast i32* %x to i8*
269 %x2 = getelementptr i8, i8* %x1, i64 36
270 %x3 = bitcast i8* %x2 to i32*
271 store i32 0, i32* %x3, align 1
275 define void @ArrayAllocaOOB() {
276 ; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}}
277 ; CHECK-NEXT: args uses:
278 ; CHECK-NEXT: allocas uses:
279 ; CHECK-NEXT: x[40]: [37,41){{$}}
282 %x = alloca i32, i32 10, align 4
283 %x1 = bitcast i32* %x to i8*
284 %x2 = getelementptr i8, i8* %x1, i64 37
285 %x3 = bitcast i8* %x2 to i32*
286 store i32 0, i32* %x3, align 1
290 define void @DynamicAllocaUnused(i64 %size) {
291 ; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}}
292 ; CHECK-NEXT: args uses:
293 ; CHECK-NEXT: allocas uses:
294 ; CHECK-NEXT: x[0]: empty-set{{$}}
297 %x = alloca i32, i64 %size, align 16
301 ; Dynamic alloca with unknown size.
302 define void @DynamicAlloca(i64 %size) {
303 ; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}}
304 ; CHECK-NEXT: args uses:
305 ; CHECK-NEXT: allocas uses:
306 ; CHECK-NEXT: x[0]: [0,4){{$}}
309 %x = alloca i32, i64 %size, align 16
310 store i32 0, i32* %x, align 1
314 ; Dynamic alloca with limited size.
315 ; FIXME: could be proved safe. Implement.
316 define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) {
317 ; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}}
318 ; CHECK-NEXT: args uses:
319 ; CHECK-NEXT: allocas uses:
320 ; CHECK-NEXT: x[0]: [0,4){{$}}
323 %size = select i1 %z, i64 3, i64 5
324 %x = alloca i32, i64 %size, align 16
325 store i32 0, i32* %x, align 1
329 define signext i8 @SimpleLoop() {
330 ; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}}
331 ; CHECK-NEXT: args uses:
332 ; CHECK-NEXT: allocas uses:
333 ; CHECK-NEXT: x[10]: [0,10){{$}}
336 %x = alloca [10 x i8], align 1
337 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
338 %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 10
342 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
343 %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ]
344 %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1
345 %1 = load volatile i8, i8* %p.09, align 1
346 %add = add i8 %1, %sum.010
347 %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit
348 br i1 %exitcond, label %for.cond.cleanup, label %for.body
355 define signext i8 @SimpleLoopOOB() {
356 ; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}}
357 ; CHECK-NEXT: args uses:
358 ; CHECK-NEXT: allocas uses:
359 ; CHECK-NEXT: x[10]: [0,11){{$}}
362 %x = alloca [10 x i8], align 1
363 %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
365 %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 11
369 %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
370 %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ]
371 %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1
372 %1 = load volatile i8, i8* %p.09, align 1
373 %add = add i8 %1, %sum.010
374 %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit
375 br i1 %exitcond, label %for.cond.cleanup, label %for.body
381 define dso_local void @SizeCheck(i32 %sz) {
382 ; CHECK-LABEL: @SizeCheck{{$}}
383 ; CHECK-NEXT: args uses:
384 ; CHECK-NEXT: allocas uses:
385 ; CHECK-NEXT: x1[128]: [0,4294967295){{$}}
388 %x1 = alloca [128 x i8], align 16
389 %x1.sub = getelementptr inbounds [128 x i8], [128 x i8]* %x1, i64 0, i64 0
390 %cmp = icmp slt i32 %sz, 129
391 br i1 %cmp, label %if.then, label %if.end
394 call void @llvm.memset.p0i8.i32(i8* nonnull align 16 %x1.sub, i8 0, i32 %sz, i1 false)
401 ; FIXME: scalable allocas are considered to be of size zero, and scalable accesses to be full-range.
402 ; This effectively disables safety analysis for scalable allocations.
403 define void @Scalable(<vscale x 4 x i32>* %p, <vscale x 4 x i32>* %unused, <vscale x 4 x i32> %v) {
404 ; CHECK-LABEL: @Scalable dso_preemptable{{$}}
405 ; CHECK-NEXT: args uses:
406 ; CHECK-NEXT: p[]: full-set
407 ; CHECK-NEXT: unused[]: empty-set
408 ; CHECK-NEXT: allocas uses:
409 ; CHECK-NEXT: x[0]: [0,1){{$}}
412 %x = alloca <vscale x 4 x i32>, align 4
413 %x1 = bitcast <vscale x 4 x i32>* %x to i8*
414 store i8 0, i8* %x1, align 1
415 store <vscale x 4 x i32> %v, <vscale x 4 x i32>* %p, align 4
419 %zerosize_type = type {}
421 define void @ZeroSize(%zerosize_type *%p) {
422 ; CHECK-LABEL: @ZeroSize dso_preemptable{{$}}
423 ; CHECK-NEXT: args uses:
424 ; CHECK-NEXT: p[]: empty-set
425 ; CHECK-NEXT: allocas uses:
426 ; CHECK-NEXT: x[0]: empty-set
429 %x = alloca %zerosize_type, align 4
430 store %zerosize_type undef, %zerosize_type* %x, align 4
431 store %zerosize_type undef, %zerosize_type* undef, align 4
432 %val = load %zerosize_type, %zerosize_type* %p, align 4
436 define void @OperandBundle() {
437 ; CHECK-LABEL: @OperandBundle dso_preemptable{{$}}
438 ; CHECK-NEXT: args uses:
439 ; CHECK-NEXT: allocas uses:
440 ; CHECK-NEXT: a[4]: full-set
443 %a = alloca i32, align 4
444 call void @LeakAddress() ["unknown"(i32* %a)]
448 define void @ByVal(i16* byval(i16) %p) {
449 ; CHECK-LABEL: @ByVal dso_preemptable{{$}}
450 ; CHECK-NEXT: args uses:
451 ; CHECK-NEXT: allocas uses:
457 define void @TestByVal() {
458 ; CHECK-LABEL: @TestByVal dso_preemptable{{$}}
459 ; CHECK-NEXT: args uses:
460 ; CHECK-NEXT: allocas uses:
461 ; CHECK-NEXT: x[2]: [0,2)
462 ; CHECK-NEXT: y[8]: [0,2)
465 %x = alloca i16, align 4
466 call void @ByVal(i16* byval(i16) %x)
468 %y = alloca i64, align 4
469 %y1 = bitcast i64* %y to i16*
470 call void @ByVal(i16* byval(i16) %y1)
475 declare void @ByValArray([100000 x i64]* byval([100000 x i64]) %p)
477 define void @TestByValArray() {
478 ; CHECK-LABEL: @TestByValArray dso_preemptable{{$}}
479 ; CHECK-NEXT: args uses:
480 ; CHECK-NEXT: allocas uses:
481 ; CHECK-NEXT: z[800000]: [500000,1300000)
484 %z = alloca [100000 x i64], align 4
485 %z1 = bitcast [100000 x i64]* %z to i8*
486 %z2 = getelementptr i8, i8* %z1, i64 500000
487 %z3 = bitcast i8* %z2 to [100000 x i64]*
488 call void @ByValArray([100000 x i64]* byval([100000 x i64]) %z3)
492 define dso_local i8 @LoadMinInt64(i8* %p) {
493 ; CHECK-LABEL: @LoadMinInt64{{$}}
494 ; CHECK-NEXT: args uses:
495 ; CHECK-NEXT: p[]: [-9223372036854775808,-9223372036854775807){{$}}
496 ; CHECK-NEXT: allocas uses:
498 %p2 = getelementptr i8, i8* %p, i64 -9223372036854775808
499 %v = load i8, i8* %p2, align 1
503 define void @Overflow() {
504 ; CHECK-LABEL: @Overflow dso_preemptable{{$}}
505 ; CHECK-NEXT: args uses:
506 ; CHECK-NEXT: allocas uses:
507 ; LOCAL-NEXT: x[1]: empty-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}
508 ; GLOBAL-NEXT: x[1]: full-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}
511 %x = alloca i8, align 4
512 %x2 = getelementptr i8, i8* %x, i64 -9223372036854775808
513 %v = call i8 @LoadMinInt64(i8* %x2)
517 define void @DeadBlock(i64* %p) {
518 ; CHECK-LABEL: @DeadBlock dso_preemptable{{$}}
519 ; CHECK-NEXT: args uses:
520 ; CHECK-NEXT: p[]: empty-set{{$}}
521 ; CHECK-NEXT: allocas uses:
522 ; CHECK-NEXT: x[1]: empty-set{{$}}
525 %x = alloca i8, align 4
530 store i64 -5, i64* %p
537 define void @LifeNotStarted() {
538 ; CHECK-LABEL: @LifeNotStarted dso_preemptable{{$}}
539 ; CHECK-NEXT: args uses:
540 ; CHECK-NEXT: allocas uses:
541 ; CHECK: x[1]: full-set{{$}}
542 ; CHECK: y[1]: full-set{{$}}
543 ; CHECK: z[1]: full-set{{$}}
546 %x = alloca i8, align 4
547 %y = alloca i8, align 4
548 %z = alloca i8, align 4
552 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
554 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x)
555 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y)
556 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z)
561 define void @LifeOK() {
562 ; CHECK-LABEL: @LifeOK dso_preemptable{{$}}
563 ; CHECK-NEXT: args uses:
564 ; CHECK-NEXT: allocas uses:
565 ; CHECK: x[1]: [0,1){{$}}
566 ; CHECK: y[1]: [0,1){{$}}
567 ; CHECK: z[1]: [0,1){{$}}
570 %x = alloca i8, align 4
571 %y = alloca i8, align 4
572 %z = alloca i8, align 4
574 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x)
575 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y)
576 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z)
580 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
585 define void @LifeEnded() {
586 ; CHECK-LABEL: @LifeEnded dso_preemptable{{$}}
587 ; CHECK-NEXT: args uses:
588 ; CHECK-NEXT: allocas uses:
589 ; CHECK: x[1]: full-set{{$}}
590 ; CHECK: y[1]: full-set{{$}}
591 ; CHECK: z[1]: full-set{{$}}
594 %x = alloca i8, align 4
595 %y = alloca i8, align 4
596 %z = alloca i8, align 4
598 call void @llvm.lifetime.start.p0i8(i64 1, i8* %x)
599 call void @llvm.lifetime.start.p0i8(i64 1, i8* %y)
600 call void @llvm.lifetime.start.p0i8(i64 1, i8* %z)
602 call void @llvm.lifetime.end.p0i8(i64 1, i8* %x)
603 call void @llvm.lifetime.end.p0i8(i64 1, i8* %y)
604 call void @llvm.lifetime.end.p0i8(i64 1, i8* %z)
608 call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
613 declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
614 declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)