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