[IRBuilder] Add Align argument for CreateMaskedExpandLoad and CreateMaskedCompressSto...
[llvm-project.git] / llvm / test / Analysis / StackSafetyAnalysis / local.ll
blob02d46c8449bae531e45409d3c4af4e0b10d7db47
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 void @unknown_call_int(i64 %i)
16 declare ptr @retptr(ptr returned)
18 ; Address leaked.
19 define 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:
26 entry:
27   %x = alloca i32, align 4
28   store ptr %x, ptr @sink, align 8
29   ret void
32 define 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 1
39 ; CHECK-EMPTY:
40 entry:
41   %x = alloca i32, align 4
42   store i8 0, ptr %x, align 1
43   ret void
46 define 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 1
53 ; CHECK-EMPTY:
54 entry:
55   %x = alloca i32, align 4
56   %c1 = icmp sge i64 %i, 0
57   %c2 = icmp slt i64 %i, 4
58   br i1 %c1, label %c1.true, label %false
60 c1.true:
61   br i1 %c2, label %c2.true, label %false
63 c2.true:
64   %x2 = getelementptr i8, ptr %x, i64 %i
65   store i8 0, ptr %x2, align 1
66   br label %false
68 false:
69   ret void
72 define 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 1
79 ; CHECK-EMPTY:
80 entry:
81   %x = alloca i32, align 4
82   %c1 = icmp sge i64 %i, 0
83   %i1 = select i1 %c1, i64 %i, i64 0
84   %c2 = icmp slt i64 %i1, 3
85   %i2 = select i1 %c2, i64 %i1, i64 3
86   %x2 = getelementptr i8, ptr %x, i64 %i2
87   store i8 0, ptr %x2, align 1
88   ret void
91 define 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 4
98 ; CHECK-EMPTY:
99 entry:
100   %x = alloca i32, align 4
101   store i32 0, ptr %x, align 4
102   ret void
105 define 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 1
112 ; CHECK-EMPTY:
113 entry:
114   %x = alloca i32, align 4
115   %x2 = getelementptr i8, ptr %x, i64 2
116   store i8 0, ptr %x2, align 1
117   ret void
120 ; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.
121 define 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:
128 entry:
129   %x = alloca i32, align 4
130   %x1 = ptrtoint ptr %x to i64
131   %x2 = add i64 %x1, 2
132   %x3 = inttoptr i64 %x2 to ptr
133   store i8 0, ptr %x3, align 1
134   ret void
137 define 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 1
145 ; CHECK-EMPTY:
146 entry:
147   %x = alloca i32, align 4
148   %x2 = call ptr @retptr(ptr %x)
149   store i8 0, ptr %x2, align 1
150   ret void
153 define dso_local void @WriteMinMax(ptr %p) {
154 ; CHECK-LABEL: @WriteMinMax{{$}}
155 ; CHECK-NEXT: args uses:
156 ; CHECK-NEXT: p[]: full-set
157 ; CHECK-NEXT: allocas uses:
158 ; GLOBAL-NEXT: safe accesses:
159 ; GLOBAL-NEXT: store i8 0, ptr %p1, align 1
160 ; GLOBAL-NEXT: store i8 0, ptr %p2, align 1
161 ; CHECK-EMPTY:
162 entry:
163   %p1 = getelementptr i8, ptr %p, i64 9223372036854775805
164   store i8 0, ptr %p1, align 1
165   %p2 = getelementptr i8, ptr %p, i64 -9223372036854775805
166   store i8 0, ptr %p2, align 1
167   ret void
170 define 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:
179 entry:
180   call void @llvm.memset.p0.i64(ptr %p, i8 1, i64 9223372036854775806, i1 0)
181   %p2 = getelementptr i8, ptr %p, i64 -9223372036854775807
182   call void @llvm.memset.p0.i64(ptr %p2, i8 1, i64 9223372036854775806, i1 0)
183   ret void
186 define 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:
193 entry:
194   %x = alloca i32, align 4
195   %x2 = getelementptr i8, ptr %x, i64 2
196   store i32 0, ptr %x2, align 1
197   ret void
200 define 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:
207 entry:
208   %x = alloca i32, align 4
209   %c1 = icmp sge i64 %i, 0
210   %c2 = icmp slt i64 %i, 5
211   br i1 %c1, label %c1.true, label %false
213 c1.true:
214   br i1 %c2, label %c2.true, label %false
216 c2.true:
217   %x2 = getelementptr i8, ptr %x, i64 %i
218   store i8 0, ptr %x2, align 1
219   br label %false
221 false:
222   ret void
225 define 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:
232 entry:
233   %x = alloca i32, align 4
234   %c2 = icmp slt i64 %i, 5
235   br i1 %c2, label %c2.true, label %false
237 c2.true:
238   %x2 = getelementptr i8, ptr %x, i64 %i
239   store i8 0, ptr %x2, align 1
240   br label %false
242 false:
243   ret void
246 define 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:
254 entry:
255   %x = alloca i32, align 4
256   %x2 = getelementptr i8, ptr %x, i64 2
257   %x3 = call ptr @retptr(ptr %x2)
258   store i32 0, ptr %x3, align 1
259   ret void
262 ; There is no difference in load vs store handling.
263 define 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 1
270 ; CHECK-EMPTY:
271 entry:
272   %x = alloca i32, align 4
273   %v = load i8, ptr %x, align 1
274   ret void
277 define 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:
284 entry:
285   %x = alloca i32, align 4
286   %x2 = getelementptr i8, ptr %x, i64 2
287   %v = load i32, ptr %x2, align 1
288   ret void
291 ; Leak through ret.
292 define 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:
299 entry:
300   %x = alloca i32, align 4
301   %x2 = getelementptr i8, ptr %x, i64 2
302   ret ptr %x2
305 declare void @Foo(ptr %p)
307 define 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:
315 entry:
316   %x = alloca i64, align 4
317   %x2 = getelementptr i16, ptr %x, i64 1
318   call void @Foo(ptr %x2);
319   ret void
322 ; Indirect calls can not be analyzed (yet).
323 ; FIXME: %p[]: full-set looks invalid
324 define 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:
332 entry:
333   %x = alloca i32, align 4
334   call void %p(ptr %x);
335   ret void
338 define 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 1
346 ; CHECK-EMPTY:
347 entry:
348   %x = alloca i32, align 4
349   %idx = select i1 %z, i64 1, i64 2
350   %x2 = getelementptr i8, ptr %x, i64 %idx
351   store i8 0, ptr %x2, align 1
352   ret void
355 define 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:
362 entry:
363   %x = alloca i32, i32 10, align 4
364   %x2 = getelementptr i32, ptr %x, i64 -400000000000
365   store i32 0, ptr %x2, align 1
366   ret void
369 define 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:
376 entry:
377   %x = alloca i32, i32 10, align 4
378   %x2 = getelementptr i32, ptr %x, i16 %z
379   store i32 0, ptr %x2, align 1
380   ret void
383 define 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:
390 entry:
391   %x = alloca i32, align 4
392   %idx = select i1 %z, i64 1, i64 4
393   %x2 = getelementptr i8, ptr %x, i64 %idx
394   store i8 0, ptr %x2, align 1
395   ret void
398 define 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 1
405 ; CHECK-EMPTY:
406 entry:
407   %x = alloca i32, i32 10, align 4
408   %x2 = getelementptr i8, ptr %x, i64 36
409   store i32 0, ptr %x2, align 1
410   ret void
413 define 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:
420 entry:
421   %x = alloca i32, i32 10, align 4
422   %x2 = getelementptr i8, ptr %x, i64 37
423   store i32 0, ptr %x2, align 1
424   ret void
427 define 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:
434 entry:
435   %x = alloca i32, i64 %size, align 16
436   ret void
439 ; Dynamic alloca with unknown size.
440 define 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:
447 entry:
448   %x = alloca i32, i64 %size, align 16
449   store i32 0, ptr %x, align 1
450   ret void
453 ; Dynamic alloca with limited size.
454 ; FIXME: could be proved safe. Implement.
455 define 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:
462 entry:
463   %size = select i1 %z, i64 3, i64 5
464   %x = alloca i32, i64 %size, align 16
465   store i32 0, ptr %x, align 1
466   ret void
469 define 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 1
476 ; CHECK-EMPTY:
477 entry:
478   %x = alloca [10 x i8], align 1
479   %lftr.limit = getelementptr inbounds [10 x i8], ptr %x, i64 0, i64 10
480   br label %for.body
482 for.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 1
486   %load = load volatile i8, ptr %p.09, align 1
487   %add = add i8 %load, %sum.010
488   %exitcond = icmp eq ptr %incdec.ptr, %lftr.limit
489   br i1 %exitcond, label %for.cond.cleanup, label %for.body
491 for.cond.cleanup:
492   ret i8 %add
495 ; OOB in a loop.
496 define 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:
503 entry:
504   %x = alloca [10 x i8], align 1
505  ; 11 iterations
506   %lftr.limit = getelementptr inbounds [10 x i8], ptr %x, i64 0, i64 11
507   br label %for.body
509 for.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 1
513   %load = load volatile i8, ptr %p.09, align 1
514   %add = add i8 %load, %sum.010
515   %exitcond = icmp eq ptr %incdec.ptr, %lftr.limit
516   br i1 %exitcond, label %for.cond.cleanup, label %for.body
518 for.cond.cleanup:
519   ret i8 %add
522 define 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:
529 entry:
530   %x1 = alloca [128 x i8], align 16
531   %cmp = icmp slt i32 %sz, 129
532   br i1 %cmp, label %if.then, label %if.end
534 if.then:
535   call void @llvm.memset.p0.i32(ptr nonnull align 16 %x1, i8 0, i32 %sz, i1 false)
536   br label %if.end
538 if.end:
539   ret void
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.
544 define 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-set
548 ; CHECK-NEXT:   unused[]: empty-set
549 ; 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 4
553 ; CHECK-EMPTY:
554 entry:
555   %x = alloca <vscale x 4 x i32>, align 4
556   store i8 0, ptr %x, align 1
557   store <vscale x 4 x i32> %v, ptr %p, align 4
558   ret void
561 %zerosize_type = type {}
563 define void @ZeroSize(ptr %p)  {
564 ; CHECK-LABEL: @ZeroSize dso_preemptable{{$}}
565 ; CHECK-NEXT: args uses:
566 ; CHECK-NEXT:   p[]: empty-set
567 ; CHECK-NEXT: allocas uses:
568 ; CHECK-NEXT:   x[0]: empty-set
569 ; GLOBAL-NEXT: safe accesses:
570 ; GLOBAL-NEXT: store %zerosize_type undef, ptr %x, align 4
571 ; GLOBAL-NEXT: store %zerosize_type undef, ptr undef, align 4
572 ; GLOBAL-NEXT: load %zerosize_type, ptr %p, align
573 ; CHECK-EMPTY:
574 entry:
575   %x = alloca %zerosize_type, align 4
576   store %zerosize_type undef, ptr %x, align 4
577   store %zerosize_type undef, ptr undef, align 4
578   %val = load %zerosize_type, ptr %p, align 4
579   ret void
582 define void @OperandBundle() {
583 ; CHECK-LABEL: @OperandBundle dso_preemptable{{$}}
584 ; CHECK-NEXT: args uses:
585 ; CHECK-NEXT: allocas uses:
586 ; CHECK-NEXT:   a[4]: full-set
587 ; GLOBAL-NEXT: safe accesses:
588 ; CHECK-EMPTY:
589 entry:
590   %a = alloca i32, align 4
591   call void @LeakAddress() ["unknown"(ptr %a)]
592   ret void
595 define 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:
601 entry:
602   ret void
605 define 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:
615 entry:
616   %x = alloca i16, align 4
617   call void @ByVal(ptr byval(i16) %x)
619   %y = alloca i64, align 4
620   call void @ByVal(ptr byval(i16) %y)
622   ret void
625 declare void @ByValArray(ptr byval([100000 x i64]) %p)
627 define 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:
634 entry:
635   %z = alloca [100000 x i64], align 4
636   %z2 = getelementptr i8, ptr %z, i64 500000
637   call void @ByValArray(ptr byval([100000 x i64]) %z2)
638   ret void
641 define 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 1
648   ; CHECK-EMPTY:
649   %p2 = getelementptr i8, ptr %p, i64 -9223372036854775808
650   %v = load i8, ptr %p2, align 1
651   ret i8 %v
654 define 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:
662 entry:
663   %x = alloca i8, align 4
664   %x2 = getelementptr i8, ptr %x, i64 -9223372036854775808
665   %v = call i8 @LoadMinInt64(ptr %x2)
666   ret void
669 define 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 %x
677 ; GLOBAL-NEXT: store i64 -5, ptr %p
678 ; CHECK-EMPTY:
679 entry:
680   %x = alloca i8, align 4
681   br label %end
683 dead:
684   store i8 5, ptr %x
685   store i64 -5, ptr %p
686   br label %end
688 end:
689   ret void
692 define 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:
701 entry:
702   %x = alloca i8, align 4
703   %y = alloca i8, align 4
704   %z = alloca i8, align 4
706   store i8 5, ptr %x
707   %n = load i8, ptr %y
708   call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
710   call void @llvm.lifetime.start.p0(i64 1, ptr %x)
711   call void @llvm.lifetime.start.p0(i64 1, ptr %y)
712   call void @llvm.lifetime.start.p0(i64 1, ptr %z)
714   ret void
717 define 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 %x
726 ; GLOBAL-NEXT: %n = load i8, ptr %y
727 ; GLOBAL-NEXT: call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
728 ; CHECK-EMPTY:
729 entry:
730   %x = alloca i8, align 4
731   %y = alloca i8, align 4
732   %z = alloca i8, align 4
734   call void @llvm.lifetime.start.p0(i64 1, ptr %x)
735   call void @llvm.lifetime.start.p0(i64 1, ptr %y)
736   call void @llvm.lifetime.start.p0(i64 1, ptr %z)
738   store i8 5, ptr %x
739   %n = load i8, ptr %y
740   call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
742   ret void
745 define 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:
754 entry:
755   %x = alloca i8, align 4
756   %y = alloca i8, align 4
757   %z = alloca i8, align 4
759   call void @llvm.lifetime.start.p0(i64 1, ptr %x)
760   call void @llvm.lifetime.start.p0(i64 1, ptr %y)
761   call void @llvm.lifetime.start.p0(i64 1, ptr %z)
763   call void @llvm.lifetime.end.p0(i64 1, ptr %x)
764   call void @llvm.lifetime.end.p0(i64 1, ptr %y)
765   call void @llvm.lifetime.end.p0(i64 1, ptr %z)
767   store i8 5, ptr %x
768   %n = load i8, ptr %y
769   call void @llvm.memset.p0.i32(ptr nonnull %z, i8 0, i32 1, i1 false)
771   ret void
774 define void @TwoAllocasOK() {
775 ; CHECK-LABEL: @TwoAllocasOK
776 ; 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:
783 entry:
784   %a = alloca i32, align 4
785   %y = alloca i8, align 4
786   call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 1, i1 false)
787   ret void
790 define void @TwoAllocasOOBDest() {
791 ; CHECK-LABEL: @TwoAllocasOOBDest
792 ; 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:
798 entry:
799   %a = alloca i32, align 4
800   %y = alloca i8, align 4
801   call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 4, i1 false)
802   ret void
805 define void @TwoAllocasOOBSource() {
806 ; CHECK-LABEL: @TwoAllocasOOBSource
807 ; 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:
813 entry:
814   %a = alloca i32, align 4
815   %y = alloca i8, align 4
816   call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %y, i32 4, i1 false)
817   ret void
820 define void @TwoAllocasOOBBoth() {
821 ; CHECK-LABEL: @TwoAllocasOOBBoth
822 ; 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:
828 entry:
829   %a = alloca i32, align 4
830   %y = alloca i8, align 4
831   call void @llvm.memcpy.p0.p0.i32(ptr %y, ptr %a, i32 5, i1 false)
832   ret void
835 define void @MixedAccesses() {
836 ; CHECK-LABEL: @MixedAccesses
837 ; 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:
843 entry:
844   %a = alloca i32, align 4
845   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 void
850 define void @MixedAccesses2() {
851 ; CHECK-LABEL: @MixedAccesses2
852 ; 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 4
857 ; CHECK-EMPTY:
858 entry:
859   %a = alloca i32, align 4
860   %n1 = load i64, ptr %a, align 4
861   %n2 = load i32, ptr %a, align 4
862   ret void
865 define void @MixedAccesses3(ptr %func) {
866 ; CHECK-LABEL: @MixedAccesses3
867 ; CHECK-NEXT: args uses:
868 ; CHECK-NEXT: func[]: full-set
869 ; CHECK-NEXT: allocas uses:
870 ; CHECK: a[4]: full-set{{$}}
871 ; GLOBAL-NEXT: safe accesses:
872 ; GLOBAL-NEXT: load i32, ptr %a, align 4
873 ; CHECK-EMPTY:
874 entry:
875   %a = alloca i32, align 4
876   %n2 = load i32, ptr %a, align 4
877   call void %func(ptr %a)
878   ret void
881 define void @MixedAccesses4() {
882 ; CHECK-LABEL: @MixedAccesses4
883 ; 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 4
889 ; CHECK-EMPTY:
890 entry:
891   %a = alloca i32, align 4
892   %a1 = alloca ptr, align 4
893   %n2 = load i32, ptr %a, align 4
894   store ptr %a, ptr %a1
895   ret void
898 define ptr @MixedAccesses5(i1 %x, ptr %y) {
899 ; CHECK-LABEL: @MixedAccesses5
900 ; CHECK-NEXT: args uses:
901 ; CHECK: y[]: full-set
902 ; CHECK-NEXT: allocas uses:
903 ; CHECK: a[4]: full-set{{$}}
904 ; GLOBAL-NEXT: safe accesses:
905 ; GLOBAL-NEXT: load i32, ptr %a, align 4
906 ; CHECK-EMPTY:
907 entry:
908   %a = alloca i32, align 4
909   br i1 %x, label %tlabel, label %flabel
910 flabel:
911   %n = load i32, ptr %a, align 4
912   ret ptr %y
913 tlabel:
914   ret ptr %a
917 define void @MixedAccesses6(ptr %arg) {
918 ; CHECK-LABEL: @MixedAccesses6
919 ; 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:
926 entry:
927   %a = alloca i32, align 4
928   call void @llvm.memcpy.p0.p0.i32(ptr %a, ptr %arg, i32 4, i1 false)
929   ret void
932 define void @MixedAccesses7(i1 %cond, ptr %arg) {
933 ; SECV doesn't support select, so we consider this non-stack-safe, even through
934 ; it is.
936 ; CHECK-LABEL: @MixedAccesses7
937 ; CHECK-NEXT: args uses:
938 ; CHECK-NEXT: arg[]: full-set
939 ; CHECK-NEXT: allocas uses:
940 ; CHECK: a[4]: full-set
941 ; GLOBAL-NEXT: safe accesses:
942 ; CHECK-EMPTY:
943 entry:
944   %a = alloca i32, align 4
945   %x1 = select i1 %cond, ptr %arg, ptr %a
946   call void @llvm.memcpy.p0.p0.i32(ptr %x1, ptr %arg, i32 4, i1 false)
947   ret void
950 define void @NoStackAccess(ptr %arg1, ptr %arg2) {
951 ; CHECK-LABEL: @NoStackAccess
952 ; 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:
960 entry:
961   %a = alloca i32, align 4
962   call void @llvm.memcpy.p0.p0.i32(ptr %arg1, ptr %arg2, i32 4, i1 false)
963   ret void
966 define void @DoubleLifetime() {
967 ; CHECK-LABEL: @DoubleLifetime
968 ; 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:
974 entry:
975   %a = alloca i32, align 4
976   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
977   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
978   call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 true)
980   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
981   call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
982   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
983   ret void
986 define void @DoubleLifetime2() {
987 ; CHECK-LABEL: @DoubleLifetime2
988 ; 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:
994 entry:
995   %a = alloca i32, align 4
996   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
997   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
998   %n = load i32, ptr %a
1000   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1001   call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1002   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1003   ret void
1006 define void @DoubleLifetime3() {
1007 ; CHECK-LABEL: @DoubleLifetime3
1008 ; 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:
1014 entry:
1015   %a = alloca i32, align 4
1016   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1017   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1018   store i32 5, ptr %a
1020   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1021   call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1022   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1023   ret void
1026 define void @DoubleLifetime4() {
1027 ; CHECK-LABEL: @DoubleLifetime4
1028 ; 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:
1034 entry:
1035   %a = alloca i32, align 4
1036   call void @llvm.lifetime.start.p0(i64 4, ptr %a)
1037   call void @llvm.memset.p0.i32(ptr %a, i8 1, i32 4, i1 false)
1038   call void @llvm.lifetime.end.p0(i64 4, ptr %a)
1039   call void @unknown_call(ptr %a)
1040   ret void
1043 define void @Cmpxchg4Arg(ptr %p) {
1044 ; CHECK-LABEL: @Cmpxchg4Arg
1045 ; 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 1
1050 ; CHECK-EMPTY:
1051 entry:
1052   cmpxchg ptr %p, i32 0, i32 1 monotonic monotonic, align 1
1053   ret void
1056 define void @AtomicRMW4Arg(ptr %p) {
1057 ; CHECK-LABEL: @AtomicRMW4Arg
1058 ; 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 1
1063 ; CHECK-EMPTY:
1064 entry:
1065   atomicrmw add ptr %p, i32 1 monotonic, align 1
1066   ret void
1069 define void @Cmpxchg4Alloca() {
1070 ; CHECK-LABEL: @Cmpxchg4Alloca
1071 ; 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 1
1076 ; CHECK-EMPTY:
1077 entry:
1078   %x = alloca i32, align 4
1079   cmpxchg ptr %x, i32 0, i32 1 monotonic monotonic, align 1
1080   ret void
1083 define void @AtomicRMW4Alloca() {
1084 ; CHECK-LABEL: @AtomicRMW4Alloca
1085 ; 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 1
1090 ; CHECK-EMPTY:
1091 entry:
1092   %x = alloca i32, align 4
1093   atomicrmw add ptr %x, i32 1 monotonic, align 1
1094   ret void
1097 define void @StoreArg(ptr %p) {
1098 ; CHECK-LABEL: @StoreArg
1099 ; 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 %p
1104 ; CHECK-EMPTY:
1105 entry:
1106   store i32 1, ptr %p
1107   ret void
1110 define void @NonPointer(ptr %p) {
1111 ; CHECK-LABEL: @NonPointer
1112 ; 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 i64
1119   call void @unknown_call_int(i64 %int)
1120   ret void
1123 @ifunc = dso_local ifunc i64 (ptr), ptr @ifunc_resolver
1125 define dso_local void @CallIfunc(ptr noundef %uaddr) local_unnamed_addr {
1126 ; CHECK-LABEL: @CallIfunc
1127 ; CHECK-NEXT:  args uses:
1128 ; CHECK-NEXT:    uaddr[]: full-set
1129 entry:
1130   tail call i64 @ifunc(ptr noundef %uaddr)
1131   ret void
1134 define dso_local ptr @ifunc_resolver() {
1135 entry:
1136   ret ptr null
1139 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
1140 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)