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
3
4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
5target triple = "x86_64-unknown-linux-gnu"
6
7@sink = global i8* null, align 8
8
9declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
10declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
11declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
12declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile)
13
14; Address leaked.
15define void @LeakAddress() {
16; CHECK-LABEL: @LeakAddress dso_preemptable{{$}}
17; CHECK-NEXT: args uses:
18; CHECK-NEXT: allocas uses:
19; CHECK-NEXT: x[4]: full-set{{$}}
20; CHECK-EMPTY:
21entry:
22  %x = alloca i32, align 4
23  %x1 = bitcast i32* %x to i8*
24  store i8* %x1, i8** @sink, align 8
25  ret void
26}
27
28define void @StoreInBounds() {
29; CHECK-LABEL: @StoreInBounds dso_preemptable{{$}}
30; CHECK-NEXT: args uses:
31; CHECK-NEXT: allocas uses:
32; CHECK-NEXT: x[4]: [0,1){{$}}
33; CHECK-EMPTY:
34entry:
35  %x = alloca i32, align 4
36  %x1 = bitcast i32* %x to i8*
37  store i8 0, i8* %x1, align 1
38  ret void
39}
40
41define void @StoreInBounds2() {
42; CHECK-LABEL: @StoreInBounds2 dso_preemptable{{$}}
43; CHECK-NEXT: args uses:
44; CHECK-NEXT: allocas uses:
45; CHECK-NEXT: x[4]: [0,4){{$}}
46; CHECK-EMPTY:
47entry:
48  %x = alloca i32, align 4
49  store i32 0, i32* %x, align 4
50  ret void
51}
52
53define void @StoreInBounds3() {
54; CHECK-LABEL: @StoreInBounds3 dso_preemptable{{$}}
55; CHECK-NEXT: args uses:
56; CHECK-NEXT: allocas uses:
57; CHECK-NEXT: x[4]: [2,3){{$}}
58; CHECK-EMPTY:
59entry:
60  %x = alloca i32, align 4
61  %x1 = bitcast i32* %x to i8*
62  %x2 = getelementptr i8, i8* %x1, i64 2
63  store i8 0, i8* %x2, align 1
64  ret void
65}
66
67; FIXME: ScalarEvolution does not look through ptrtoint/inttoptr.
68define void @StoreInBounds4() {
69; CHECK-LABEL: @StoreInBounds4 dso_preemptable{{$}}
70; CHECK-NEXT: args uses:
71; CHECK-NEXT: allocas uses:
72; CHECK-NEXT: x[4]: full-set{{$}}
73; CHECK-EMPTY:
74entry:
75  %x = alloca i32, align 4
76  %x1 = ptrtoint i32* %x to i64
77  %x2 = add i64 %x1, 2
78  %x3 = inttoptr i64 %x2 to i8*
79  store i8 0, i8* %x3, align 1
80  ret void
81}
82
83define dso_local void @WriteMinMax(i8* %p) {
84; CHECK-LABEL: @WriteMinMax{{$}}
85; CHECK-NEXT: args uses:
86; CHECK-NEXT: p[]: full-set
87; CHECK-NEXT: allocas uses:
88; CHECK-EMPTY:
89entry:
90  %p1 = getelementptr i8, i8* %p, i64 9223372036854775805
91  store i8 0, i8* %p1, align 1
92  %p2 = getelementptr i8, i8* %p, i64 -9223372036854775805
93  store i8 0, i8* %p2, align 1
94  ret void
95}
96
97define dso_local void @WriteMax(i8* %p) {
98; CHECK-LABEL: @WriteMax{{$}}
99; CHECK-NEXT: args uses:
100; CHECK-NEXT: p[]: [-9223372036854775807,9223372036854775806)
101; CHECK-NEXT: allocas uses:
102; CHECK-EMPTY:
103entry:
104  call void @llvm.memset.p0i8.i64(i8* %p, i8 1, i64 9223372036854775806, i1 0)
105  %p2 = getelementptr i8, i8* %p, i64 -9223372036854775807
106  call void @llvm.memset.p0i8.i64(i8* %p2, i8 1, i64 9223372036854775806, i1 0)
107  ret void
108}
109
110define void @StoreOutOfBounds() {
111; CHECK-LABEL: @StoreOutOfBounds dso_preemptable{{$}}
112; CHECK-NEXT: args uses:
113; CHECK-NEXT: allocas uses:
114; CHECK-NEXT: x[4]: [2,6){{$}}
115; CHECK-EMPTY:
116entry:
117  %x = alloca i32, align 4
118  %x1 = bitcast i32* %x to i8*
119  %x2 = getelementptr i8, i8* %x1, i64 2
120  %x3 = bitcast i8* %x2 to i32*
121  store i32 0, i32* %x3, align 1
122  ret void
123}
124
125; There is no difference in load vs store handling.
126define void @LoadInBounds() {
127; CHECK-LABEL: @LoadInBounds dso_preemptable{{$}}
128; CHECK-NEXT: args uses:
129; CHECK-NEXT: allocas uses:
130; CHECK-NEXT: x[4]: [0,1){{$}}
131; CHECK-EMPTY:
132entry:
133  %x = alloca i32, align 4
134  %x1 = bitcast i32* %x to i8*
135  %v = load i8, i8* %x1, align 1
136  ret void
137}
138
139define void @LoadOutOfBounds() {
140; CHECK-LABEL: @LoadOutOfBounds dso_preemptable{{$}}
141; CHECK-NEXT: args uses:
142; CHECK-NEXT: allocas uses:
143; CHECK-NEXT: x[4]: [2,6){{$}}
144; CHECK-EMPTY:
145entry:
146  %x = alloca i32, align 4
147  %x1 = bitcast i32* %x to i8*
148  %x2 = getelementptr i8, i8* %x1, i64 2
149  %x3 = bitcast i8* %x2 to i32*
150  %v = load i32, i32* %x3, align 1
151  ret void
152}
153
154; Leak through ret.
155define i8* @Ret() {
156; CHECK-LABEL: @Ret dso_preemptable{{$}}
157; CHECK-NEXT: args uses:
158; CHECK-NEXT: allocas uses:
159; CHECK-NEXT: x[4]: full-set{{$}}
160; CHECK-EMPTY:
161entry:
162  %x = alloca i32, align 4
163  %x1 = bitcast i32* %x to i8*
164  %x2 = getelementptr i8, i8* %x1, i64 2
165  ret i8* %x2
166}
167
168declare void @Foo(i16* %p)
169
170define void @DirectCall() {
171; CHECK-LABEL: @DirectCall dso_preemptable{{$}}
172; CHECK-NEXT: args uses:
173; CHECK-NEXT: allocas uses:
174; LOCAL-NEXT: x[8]: empty-set, @Foo(arg0, [2,3)){{$}}
175; GLOBAL-NEXT: x[8]: full-set, @Foo(arg0, [2,3)){{$}}
176; CHECK-EMPTY:
177entry:
178  %x = alloca i64, align 4
179  %x1 = bitcast i64* %x to i16*
180  %x2 = getelementptr i16, i16* %x1, i64 1
181  call void @Foo(i16* %x2);
182  ret void
183}
184
185; Indirect calls can not be analyzed (yet).
186; FIXME: %p[]: full-set looks invalid
187define void @IndirectCall(void (i8*)* %p) {
188; CHECK-LABEL: @IndirectCall dso_preemptable{{$}}
189; CHECK-NEXT: args uses:
190; CHECK-NEXT: p[]: full-set{{$}}
191; CHECK-NEXT: allocas uses:
192; CHECK-NEXT: x[4]: full-set{{$}}
193; CHECK-EMPTY:
194entry:
195  %x = alloca i32, align 4
196  %x1 = bitcast i32* %x to i8*
197  call void %p(i8* %x1);
198  ret void
199}
200
201define void @NonConstantOffset(i1 zeroext %z) {
202; CHECK-LABEL: @NonConstantOffset dso_preemptable{{$}}
203; CHECK-NEXT: args uses:
204; CHECK-NEXT: allocas uses:
205; FIXME: SCEV can't look through selects.
206; CHECK-NEXT: x[4]: [0,4){{$}}
207; CHECK-EMPTY:
208entry:
209  %x = alloca i32, align 4
210  %x1 = bitcast i32* %x to i8*
211  %idx = select i1 %z, i64 1, i64 2
212  %x2 = getelementptr i8, i8* %x1, i64 %idx
213  store i8 0, i8* %x2, align 1
214  ret void
215}
216
217define void @NegativeOffset() {
218; CHECK-LABEL: @NegativeOffset dso_preemptable{{$}}
219; CHECK-NEXT: args uses:
220; CHECK-NEXT: allocas uses:
221; CHECK-NEXT: x[40]: [-1600000000000,-1599999999996){{$}}
222; CHECK-EMPTY:
223entry:
224  %x = alloca i32, i32 10, align 4
225  %x2 = getelementptr i32, i32* %x, i64 -400000000000
226  store i32 0, i32* %x2, align 1
227  ret void
228}
229
230define void @PossiblyNegativeOffset(i16 %z) {
231; CHECK-LABEL: @PossiblyNegativeOffset dso_preemptable{{$}}
232; CHECK-NEXT: args uses:
233; CHECK-NEXT: allocas uses:
234; CHECK-NEXT: x[40]: [-131072,131072){{$}}
235; CHECK-EMPTY:
236entry:
237  %x = alloca i32, i32 10, align 4
238  %x2 = getelementptr i32, i32* %x, i16 %z
239  store i32 0, i32* %x2, align 1
240  ret void
241}
242
243define void @NonConstantOffsetOOB(i1 zeroext %z) {
244; CHECK-LABEL: @NonConstantOffsetOOB dso_preemptable{{$}}
245; CHECK-NEXT: args uses:
246; CHECK-NEXT: allocas uses:
247; CHECK-NEXT: x[4]: [0,6){{$}}
248; CHECK-EMPTY:
249entry:
250  %x = alloca i32, align 4
251  %x1 = bitcast i32* %x to i8*
252  %idx = select i1 %z, i64 1, i64 4
253  %x2 = getelementptr i8, i8* %x1, i64 %idx
254  store i8 0, i8* %x2, align 1
255  ret void
256}
257
258define void @ArrayAlloca() {
259; CHECK-LABEL: @ArrayAlloca dso_preemptable{{$}}
260; CHECK-NEXT: args uses:
261; CHECK-NEXT: allocas uses:
262; CHECK-NEXT: x[40]: [36,40){{$}}
263; CHECK-EMPTY:
264entry:
265  %x = alloca i32, i32 10, align 4
266  %x1 = bitcast i32* %x to i8*
267  %x2 = getelementptr i8, i8* %x1, i64 36
268  %x3 = bitcast i8* %x2 to i32*
269  store i32 0, i32* %x3, align 1
270  ret void
271}
272
273define void @ArrayAllocaOOB() {
274; CHECK-LABEL: @ArrayAllocaOOB dso_preemptable{{$}}
275; CHECK-NEXT: args uses:
276; CHECK-NEXT: allocas uses:
277; CHECK-NEXT: x[40]: [37,41){{$}}
278; CHECK-EMPTY:
279entry:
280  %x = alloca i32, i32 10, align 4
281  %x1 = bitcast i32* %x to i8*
282  %x2 = getelementptr i8, i8* %x1, i64 37
283  %x3 = bitcast i8* %x2 to i32*
284  store i32 0, i32* %x3, align 1
285  ret void
286}
287
288define void @DynamicAllocaUnused(i64 %size) {
289; CHECK-LABEL: @DynamicAllocaUnused dso_preemptable{{$}}
290; CHECK-NEXT: args uses:
291; CHECK-NEXT: allocas uses:
292; CHECK-NEXT: x[0]: empty-set{{$}}
293; CHECK-EMPTY:
294entry:
295  %x = alloca i32, i64 %size, align 16
296  ret void
297}
298
299; Dynamic alloca with unknown size.
300define void @DynamicAlloca(i64 %size) {
301; CHECK-LABEL: @DynamicAlloca dso_preemptable{{$}}
302; CHECK-NEXT: args uses:
303; CHECK-NEXT: allocas uses:
304; CHECK-NEXT: x[0]: [0,4){{$}}
305; CHECK-EMPTY:
306entry:
307  %x = alloca i32, i64 %size, align 16
308  store i32 0, i32* %x, align 1
309  ret void
310}
311
312; Dynamic alloca with limited size.
313; FIXME: could be proved safe. Implement.
314define void @DynamicAllocaFiniteSizeRange(i1 zeroext %z) {
315; CHECK-LABEL: @DynamicAllocaFiniteSizeRange dso_preemptable{{$}}
316; CHECK-NEXT: args uses:
317; CHECK-NEXT: allocas uses:
318; CHECK-NEXT: x[0]: [0,4){{$}}
319; CHECK-EMPTY:
320entry:
321  %size = select i1 %z, i64 3, i64 5
322  %x = alloca i32, i64 %size, align 16
323  store i32 0, i32* %x, align 1
324  ret void
325}
326
327define signext i8 @SimpleLoop() {
328; CHECK-LABEL: @SimpleLoop dso_preemptable{{$}}
329; CHECK-NEXT: args uses:
330; CHECK-NEXT: allocas uses:
331; CHECK-NEXT: x[10]: [0,10){{$}}
332; CHECK-EMPTY:
333entry:
334  %x = alloca [10 x i8], align 1
335  %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
336  %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 10
337  br label %for.body
338
339for.body:
340  %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
341  %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ]
342  %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1
343  %1 = load volatile i8, i8* %p.09, align 1
344  %add = add i8 %1, %sum.010
345  %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit
346  br i1 %exitcond, label %for.cond.cleanup, label %for.body
347
348for.cond.cleanup:
349  ret i8 %add
350}
351
352; OOB in a loop.
353define signext i8 @SimpleLoopOOB() {
354; CHECK-LABEL: @SimpleLoopOOB dso_preemptable{{$}}
355; CHECK-NEXT: args uses:
356; CHECK-NEXT: allocas uses:
357; CHECK-NEXT: x[10]: [0,11){{$}}
358; CHECK-EMPTY:
359entry:
360  %x = alloca [10 x i8], align 1
361  %0 = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 0
362 ; 11 iterations
363  %lftr.limit = getelementptr inbounds [10 x i8], [10 x i8]* %x, i64 0, i64 11
364  br label %for.body
365
366for.body:
367  %sum.010 = phi i8 [ 0, %entry ], [ %add, %for.body ]
368  %p.09 = phi i8* [ %0, %entry ], [ %incdec.ptr, %for.body ]
369  %incdec.ptr = getelementptr inbounds i8, i8* %p.09, i64 1
370  %1 = load volatile i8, i8* %p.09, align 1
371  %add = add i8 %1, %sum.010
372  %exitcond = icmp eq i8* %incdec.ptr, %lftr.limit
373  br i1 %exitcond, label %for.cond.cleanup, label %for.body
374
375for.cond.cleanup:
376  ret i8 %add
377}
378
379define dso_local void @SizeCheck(i32 %sz) {
380; CHECK-LABEL: @SizeCheck{{$}}
381; CHECK-NEXT: args uses:
382; CHECK-NEXT: allocas uses:
383; CHECK-NEXT: x1[128]: [0,4294967295){{$}}
384; CHECK-EMPTY:
385entry:
386  %x1 = alloca [128 x i8], align 16
387  %x1.sub = getelementptr inbounds [128 x i8], [128 x i8]* %x1, i64 0, i64 0
388  %cmp = icmp slt i32 %sz, 129
389  br i1 %cmp, label %if.then, label %if.end
390
391if.then:
392  call void @llvm.memset.p0i8.i32(i8* nonnull align 16 %x1.sub, i8 0, i32 %sz, i1 false)
393  br label %if.end
394
395if.end:
396  ret void
397}
398
399; FIXME: scalable allocas are considered to be of size zero, and scalable accesses to be full-range.
400; This effectively disables safety analysis for scalable allocations.
401define void @Scalable(<vscale x 4 x i32>* %p, <vscale x 4 x i32>* %unused, <vscale x 4 x i32> %v) {
402; CHECK-LABEL: @Scalable dso_preemptable{{$}}
403; CHECK-NEXT: args uses:
404; CHECK-NEXT:   p[]: full-set
405; CHECK-NEXT:   unused[]: empty-set
406; CHECK-NEXT: allocas uses:
407; CHECK-NEXT:   x[0]: [0,1){{$}}
408; CHECK-EMPTY:
409entry:
410  %x = alloca <vscale x 4 x i32>, align 4
411  %x1 = bitcast <vscale x 4 x i32>* %x to i8*
412  store i8 0, i8* %x1, align 1
413  store <vscale x 4 x i32> %v, <vscale x 4 x i32>* %p, align 4
414  ret void
415}
416
417%zerosize_type = type {}
418
419define void @ZeroSize(%zerosize_type *%p)  {
420; CHECK-LABEL: @ZeroSize dso_preemptable{{$}}
421; CHECK-NEXT: args uses:
422; CHECK-NEXT:   p[]: empty-set
423; CHECK-NEXT: allocas uses:
424; CHECK-NEXT:   x[0]: empty-set
425; CHECK-EMPTY:
426entry:
427  %x = alloca %zerosize_type, align 4
428  store %zerosize_type undef, %zerosize_type* %x, align 4
429  store %zerosize_type undef, %zerosize_type* undef, align 4
430  %val = load %zerosize_type, %zerosize_type* %p, align 4
431  ret void
432}
433
434define void @OperandBundle() {
435; CHECK-LABEL: @OperandBundle dso_preemptable{{$}}
436; CHECK-NEXT: args uses:
437; CHECK-NEXT: allocas uses:
438; CHECK-NEXT:   a[4]: full-set
439; CHECK-EMPTY:
440entry:
441  %a = alloca i32, align 4
442  call void @LeakAddress() ["unknown"(i32* %a)]
443  ret void
444}
445
446define void @ByVal(i16* byval(i16) %p) {
447  ; CHECK-LABEL: @ByVal dso_preemptable{{$}}
448  ; CHECK-NEXT: args uses:
449  ; CHECK-NEXT: allocas uses:
450  ; CHECK-EMPTY:
451entry:
452  ret void
453}
454
455define void @TestByVal() {
456; CHECK-LABEL: @TestByVal dso_preemptable{{$}}
457; CHECK-NEXT: args uses:
458; CHECK-NEXT: allocas uses:
459; CHECK-NEXT: x[2]: [0,2)
460; CHECK-NEXT: y[8]: [0,2)
461; CHECK-EMPTY:
462entry:
463  %x = alloca i16, align 4
464  call void @ByVal(i16* byval(i16) %x)
465
466  %y = alloca i64, align 4
467  %y1 = bitcast i64* %y to i16*
468  call void @ByVal(i16* byval(i16) %y1)
469
470  ret void
471}
472
473declare void @ByValArray([100000 x i64]* byval([100000 x i64]) %p)
474
475define void @TestByValArray() {
476; CHECK-LABEL: @TestByValArray dso_preemptable{{$}}
477; CHECK-NEXT: args uses:
478; CHECK-NEXT: allocas uses:
479; CHECK-NEXT: z[800000]: [500000,1300000)
480; CHECK-EMPTY:
481entry:
482  %z = alloca [100000 x i64], align 4
483  %z1 = bitcast [100000 x i64]* %z to i8*
484  %z2 = getelementptr i8, i8* %z1, i64 500000
485  %z3 = bitcast i8* %z2 to [100000 x i64]*
486  call void @ByValArray([100000 x i64]* byval([100000 x i64]) %z3)
487  ret void
488}
489
490define dso_local i8 @LoadMinInt64(i8* %p) {
491  ; CHECK-LABEL: @LoadMinInt64{{$}}
492  ; CHECK-NEXT: args uses:
493  ; CHECK-NEXT: p[]: [-9223372036854775808,-9223372036854775807){{$}}
494  ; CHECK-NEXT: allocas uses:
495  ; CHECK-EMPTY:
496  %p2 = getelementptr i8, i8* %p, i64 -9223372036854775808
497  %v = load i8, i8* %p2, align 1
498  ret i8 %v
499}
500
501define void @Overflow() {
502; CHECK-LABEL: @Overflow dso_preemptable{{$}}
503; CHECK-NEXT: args uses:
504; CHECK-NEXT: allocas uses:
505; LOCAL-NEXT: x[1]: empty-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}
506; GLOBAL-NEXT: x[1]: full-set, @LoadMinInt64(arg0, [-9223372036854775808,-9223372036854775807)){{$}}
507; CHECK-EMPTY:
508entry:
509  %x = alloca i8, align 4
510  %x2 = getelementptr i8, i8* %x, i64 -9223372036854775808
511  %v = call i8 @LoadMinInt64(i8* %x2)
512  ret void
513}
514
515define void @DeadBlock(i64* %p) {
516; CHECK-LABEL: @DeadBlock dso_preemptable{{$}}
517; CHECK-NEXT: args uses:
518; CHECK-NEXT: p[]: empty-set{{$}}
519; CHECK-NEXT: allocas uses:
520; CHECK-NEXT: x[1]: empty-set{{$}}
521; CHECK-EMPTY:
522entry:
523  %x = alloca i8, align 4
524  br label %end
525
526dead:
527  store i8 5, i8* %x
528  store i64 -5, i64* %p
529  br label %end
530
531end:
532  ret void
533}
534
535define void @LifeNotStarted() {
536; CHECK-LABEL: @LifeNotStarted dso_preemptable{{$}}
537; CHECK-NEXT: args uses:
538; CHECK-NEXT: allocas uses:
539; CHECK: x[1]: full-set{{$}}
540; CHECK: y[1]: full-set{{$}}
541; CHECK: z[1]: full-set{{$}}
542; CHECK-EMPTY:
543entry:
544  %x = alloca i8, align 4
545  %y = alloca i8, align 4
546  %z = alloca i8, align 4
547
548  store i8 5, i8* %x
549  %n = load i8, i8* %y
550  call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
551
552  call void @llvm.lifetime.start.p0i8(i64 1, i8* %x)
553  call void @llvm.lifetime.start.p0i8(i64 1, i8* %y)
554  call void @llvm.lifetime.start.p0i8(i64 1, i8* %z)
555
556  ret void
557}
558
559define void @LifeOK() {
560; CHECK-LABEL: @LifeOK dso_preemptable{{$}}
561; CHECK-NEXT: args uses:
562; CHECK-NEXT: allocas uses:
563; CHECK: x[1]: [0,1){{$}}
564; CHECK: y[1]: [0,1){{$}}
565; CHECK: z[1]: [0,1){{$}}
566; CHECK-EMPTY:
567entry:
568  %x = alloca i8, align 4
569  %y = alloca i8, align 4
570  %z = alloca i8, align 4
571
572  call void @llvm.lifetime.start.p0i8(i64 1, i8* %x)
573  call void @llvm.lifetime.start.p0i8(i64 1, i8* %y)
574  call void @llvm.lifetime.start.p0i8(i64 1, i8* %z)
575
576  store i8 5, i8* %x
577  %n = load i8, i8* %y
578  call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
579
580  ret void
581}
582
583define void @LifeEnded() {
584; CHECK-LABEL: @LifeEnded dso_preemptable{{$}}
585; CHECK-NEXT: args uses:
586; CHECK-NEXT: allocas uses:
587; CHECK: x[1]: full-set{{$}}
588; CHECK: y[1]: full-set{{$}}
589; CHECK: z[1]: full-set{{$}}
590; CHECK-EMPTY:
591entry:
592  %x = alloca i8, align 4
593  %y = alloca i8, align 4
594  %z = alloca i8, align 4
595
596  call void @llvm.lifetime.start.p0i8(i64 1, i8* %x)
597  call void @llvm.lifetime.start.p0i8(i64 1, i8* %y)
598  call void @llvm.lifetime.start.p0i8(i64 1, i8* %z)
599
600  call void @llvm.lifetime.end.p0i8(i64 1, i8* %x)
601  call void @llvm.lifetime.end.p0i8(i64 1, i8* %y)
602  call void @llvm.lifetime.end.p0i8(i64 1, i8* %z)
603
604  store i8 5, i8* %x
605  %n = load i8, i8* %y
606  call void @llvm.memset.p0i8.i32(i8* nonnull %z, i8 0, i32 1, i1 false)
607
608  ret void
609}
610
611declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
612declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
613