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
5
6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7target triple = "x86_64-unknown-linux-gnu"
8
9@sink = global i8* null, align 8
10
11declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
12declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
13declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
14declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile)
15
16; Address leaked.
17define 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{{$}}
22; CHECK-EMPTY:
23entry:
24  %x = alloca i32, align 4
25  %x1 = bitcast i32* %x to i8*
26  store i8* %x1, i8** @sink, align 8
27  ret void
28}
29
30define 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){{$}}
35; CHECK-EMPTY:
36entry:
37  %x = alloca i32, align 4
38  %x1 = bitcast i32* %x to i8*
39  store i8 0, i8* %x1, align 1
40  ret void
41}
42
43define 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){{$}}
48; CHECK-EMPTY:
49entry:
50  %x = alloca i32, align 4
51  store i32 0, i32* %x, align 4
52  ret void
53}
54
55define 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){{$}}
60; CHECK-EMPTY:
61entry:
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
66  ret void
67}
68
69; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.
70define 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{{$}}
75; CHECK-EMPTY:
76entry:
77  %x = alloca i32, align 4
78  %x1 = ptrtoint i32* %x to i64
79  %x2 = add i64 %x1, 2
80  %x3 = inttoptr i64 %x2 to i8*
81  store i8 0, i8* %x3, align 1
82  ret void
83}
84
85define 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:
90; CHECK-EMPTY:
91entry:
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
96  ret void
97}
98
99define 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:
104; CHECK-EMPTY:
105entry:
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)
109  ret void
110}
111
112define 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){{$}}
117; CHECK-EMPTY:
118entry:
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
124  ret void
125}
126
127; There is no difference in load vs store handling.
128define 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){{$}}
133; CHECK-EMPTY:
134entry:
135  %x = alloca i32, align 4
136  %x1 = bitcast i32* %x to i8*
137  %v = load i8, i8* %x1, align 1
138  ret void
139}
140
141define 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){{$}}
146; CHECK-EMPTY:
147entry:
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
153  ret void
154}
155
156; Leak through ret.
157define i8* @Ret() {
158; CHECK-LABEL: @Ret dso_preemptable{{$}}
159; CHECK-NEXT: args uses:
160; CHECK-NEXT: allocas uses:
161; CHECK-NEXT: x[4]: full-set{{$}}
162; CHECK-EMPTY:
163entry:
164  %x = alloca i32, align 4
165  %x1 = bitcast i32* %x to i8*
166  %x2 = getelementptr i8, i8* %x1, i64 2
167  ret i8* %x2
168}
169
170declare void @Foo(i16* %p)
171
172define 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)){{$}}
178; CHECK-EMPTY:
179entry:
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);
184  ret void
185}
186
187; Indirect calls can not be analyzed (yet).
188; FIXME: %p[]: full-set looks invalid
189define 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{{$}}
195; CHECK-EMPTY:
196entry:
197  %x = alloca i32, align 4
198  %x1 = bitcast i32* %x to i8*
199  call void %p(i8* %x1);
200  ret void
201}
202
203define 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){{$}}
209; CHECK-EMPTY:
210entry:
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
216  ret void
217}
218
219define 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){{$}}
224; CHECK-EMPTY:
225entry:
226  %x = alloca i32, i32 10, align 4
227  %x2 = getelementptr i32, i32* %x, i64 -400000000000
228  store i32 0, i32* %x2, align 1
229  ret void
230}
231
232define 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){{$}}
237; CHECK-EMPTY:
238entry:
239  %x = alloca i32, i32 10, align 4
240  %x2 = getelementptr i32, i32* %x, i16 %z
241  store i32 0, i32* %x2, align 1
242  ret void
243}
244
245define 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){{$}}
250; CHECK-EMPTY:
251entry:
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
257  ret void
258}
259
260define 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){{$}}
265; CHECK-EMPTY:
266entry:
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
272  ret void
273}
274
275define 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){{$}}
280; CHECK-EMPTY:
281entry:
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
287  ret void
288}
289
290define 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{{$}}
295; CHECK-EMPTY:
296entry:
297  %x = alloca i32, i64 %size, align 16
298  ret void
299}
300
301; Dynamic alloca with unknown size.
302define 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){{$}}
307; CHECK-EMPTY:
308entry:
309  %x = alloca i32, i64 %size, align 16
310  store i32 0, i32* %x, align 1
311  ret void
312}
313
314; Dynamic alloca with limited size.
315; FIXME: could be proved safe. Implement.
316define 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){{$}}
321; CHECK-EMPTY:
322entry:
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
326  ret void
327}
328
329define 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){{$}}
334; CHECK-EMPTY:
335entry:
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
339  br label %for.body
340
341for.body:
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
349
350for.cond.cleanup:
351  ret i8 %add
352}
353
354; OOB in a loop.
355define 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){{$}}
360; CHECK-EMPTY:
361entry:
362  %x = alloca [10 x i8], align 1
363  %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
364 ; 11 iterations
365  %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 11
366  br label %for.body
367
368for.body:
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
376
377for.cond.cleanup:
378  ret i8 %add
379}
380
381define 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){{$}}
386; CHECK-EMPTY:
387entry:
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
392
393if.then:
394  call void @llvm.memset.p0i8.i32(i8* nonnull align 16 %x1.sub, i8 0, i32 %sz, i1 false)
395  br label %if.end
396
397if.end:
398  ret void
399}
400
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.
403define 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){{$}}
410; CHECK-EMPTY:
411entry:
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
416  ret void
417}
418
419%zerosize_type = type {}
420
421define 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
427; CHECK-EMPTY:
428entry:
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
433  ret void
434}
435
436define 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
441; CHECK-EMPTY:
442entry:
443  %a = alloca i32, align 4
444  call void @LeakAddress() ["unknown"(i32* %a)]
445  ret void
446}
447
448define void @ByVal(i16* byval(i16) %p) {
449  ; CHECK-LABEL: @ByVal dso_preemptable{{$}}
450  ; CHECK-NEXT: args uses:
451  ; CHECK-NEXT: allocas uses:
452  ; CHECK-EMPTY:
453entry:
454  ret void
455}
456
457define 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)
463; CHECK-EMPTY:
464entry:
465  %x = alloca i16, align 4
466  call void @ByVal(i16* byval(i16) %x)
467
468  %y = alloca i64, align 4
469  %y1 = bitcast i64* %y to i16*
470  call void @ByVal(i16* byval(i16) %y1)
471
472  ret void
473}
474
475declare void @ByValArray([100000 x i64]* byval([100000 x i64]) %p)
476
477define 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)
482; CHECK-EMPTY:
483entry:
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)
489  ret void
490}
491
492define 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:
497  ; CHECK-EMPTY:
498  %p2 = getelementptr i8, i8* %p, i64 -9223372036854775808
499  %v = load i8, i8* %p2, align 1
500  ret i8 %v
501}
502
503define 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)){{$}}
509; CHECK-EMPTY:
510entry:
511  %x = alloca i8, align 4
512  %x2 = getelementptr i8, i8* %x, i64 -9223372036854775808
513  %v = call i8 @LoadMinInt64(i8* %x2)
514  ret void
515}
516
517define 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{{$}}
523; CHECK-EMPTY:
524entry:
525  %x = alloca i8, align 4
526  br label %end
527
528dead:
529  store i8 5, i8* %x
530  store i64 -5, i64* %p
531  br label %end
532
533end:
534  ret void
535}
536
537define 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{{$}}
544; CHECK-EMPTY:
545entry:
546  %x = alloca i8, align 4
547  %y = alloca i8, align 4
548  %z = alloca i8, align 4
549
550  store i8 5, i8* %x
551  %n = load i8, i8* %y
552  call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
553
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)
557
558  ret void
559}
560
561define 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){{$}}
568; CHECK-EMPTY:
569entry:
570  %x = alloca i8, align 4
571  %y = alloca i8, align 4
572  %z = alloca i8, align 4
573
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)
577
578  store i8 5, i8* %x
579  %n = load i8, i8* %y
580  call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
581
582  ret void
583}
584
585define 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{{$}}
592; CHECK-EMPTY:
593entry:
594  %x = alloca i8, align 4
595  %y = alloca i8, align 4
596  %z = alloca i8, align 4
597
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)
601
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)
605
606  store i8 5, i8* %x
607  %n = load i8, i8* %y
608  call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
609
610  ret void
611}
612
613declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
614declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
615