1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=FNATTR
3; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=FNATTR
4
5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6
7declare nonnull i8* @ret_nonnull()
8
9; Return a pointer trivially nonnull (call return attribute)
10define i8* @test1() {
11; FNATTR: define nonnull i8* @test1
12  %ret = call i8* @ret_nonnull()
13  ret i8* %ret
14}
15
16; Return a pointer trivially nonnull (argument attribute)
17define i8* @test2(i8* nonnull %p) {
18; FNATTR: define nonnull i8* @test2
19  ret i8* %p
20}
21
22; Given an SCC where one of the functions can not be marked nonnull,
23; can we still mark the other one which is trivially nonnull
24define i8* @scc_binder(i1 %c) {
25; FNATTR: define i8* @scc_binder
26  br i1 %c, label %rec, label %end
27rec:
28  call i8* @test3(i1 %c)
29  br label %end
30end:
31  ret i8* null
32}
33
34define i8* @test3(i1 %c) {
35; FNATTR: define nonnull i8* @test3
36  call i8* @scc_binder(i1 %c)
37  %ret = call i8* @ret_nonnull()
38  ret i8* %ret
39}
40
41; Given a mutual recursive set of functions, we can mark them
42; nonnull if neither can ever return null.  (In this case, they
43; just never return period.)
44define i8* @test4_helper() {
45; FNATTR: define noalias nonnull i8* @test4_helper
46  %ret = call i8* @test4()
47  ret i8* %ret
48}
49
50define i8* @test4() {
51; FNATTR: define noalias nonnull i8* @test4
52  %ret = call i8* @test4_helper()
53  ret i8* %ret
54}
55
56; Given a mutual recursive set of functions which *can* return null
57; make sure we haven't marked them as nonnull.
58define i8* @test5_helper(i1 %c) {
59; FNATTR: define noalias i8* @test5_helper
60  br i1 %c, label %rec, label %end
61rec:
62  %ret = call i8* @test5(i1 %c)
63  br label %end
64end:
65  ret i8* null
66}
67
68define i8* @test5(i1 %c) {
69; FNATTR: define noalias i8* @test5
70  %ret = call i8* @test5_helper(i1 %c)
71  ret i8* %ret
72}
73
74; Local analysis, but going through a self recursive phi
75define i8* @test6a() {
76entry:
77  %ret = call i8* @ret_nonnull()
78  br label %loop
79loop:
80  %phi = phi i8* [%ret, %entry], [%phi, %loop]
81  br i1 undef, label %loop, label %exit
82exit:
83  ret i8* %phi
84}
85
86define i8* @test6b(i1 %c) {
87entry:
88  %ret = call i8* @ret_nonnull()
89  br label %loop
90loop:
91  %phi = phi i8* [%ret, %entry], [%phi, %loop]
92  br i1 %c, label %loop, label %exit
93exit:
94  ret i8* %phi
95}
96
97; FNATTR: define i8* @test7
98define i8* @test7(i8* %a) {
99  %b = getelementptr inbounds i8, i8* %a, i64 0
100  ret i8* %b
101}
102
103; FNATTR: define nonnull i8* @test8
104define i8* @test8(i8* %a) {
105  %b = getelementptr inbounds i8, i8* %a, i64 1
106  ret i8* %b
107}
108
109; FNATTR: define i8* @test9
110define i8* @test9(i8* %a, i64 %n) {
111  %b = getelementptr inbounds i8, i8* %a, i64 %n
112  ret i8* %b
113}
114
115declare void @llvm.assume(i1)
116; FNATTR: define i8* @test10
117; FIXME: missing nonnull
118define i8* @test10(i8* %a, i64 %n) {
119  %cmp = icmp ne i64 %n, 0
120  call void @llvm.assume(i1 %cmp)
121  %b = getelementptr inbounds i8, i8* %a, i64 %n
122  ret i8* %b
123}
124
125; TEST 11
126; char* test11(char *p) {
127;   return p? p: nonnull();
128; }
129; FNATTR: define i8* @test11
130; FIXME: missing nonnull
131define i8* @test11(i8*) local_unnamed_addr {
132  %2 = icmp eq i8* %0, null
133  br i1 %2, label %3, label %5
134
135; <label>:3:                                      ; preds = %1
136  %4 = tail call i8* @ret_nonnull()
137  br label %5
138
139; <label>:5:                                      ; preds = %3, %1
140  %6 = phi i8* [ %4, %3 ], [ %0, %1 ]
141  ret i8* %6
142}
143
144; TEST 12
145; Simple CallSite Test
146declare void @test12_helper(i8*)
147define void @test12(i8* nonnull %a) {
148  tail call void @test12_helper(i8* %a)
149  ret void
150}
151
152; TEST 13
153; Simple Argument Tests
154declare i8* @unknown()
155define void @test13_helper() {
156  %nonnullptr = tail call i8* @ret_nonnull()
157  %maybenullptr = tail call i8* @unknown()
158  tail call void @test13(i8* %nonnullptr, i8* %nonnullptr, i8* %maybenullptr)
159  tail call void @test13(i8* %nonnullptr, i8* %maybenullptr, i8* %nonnullptr)
160  ret void
161}
162define internal void @test13(i8* %a, i8* %b, i8* %c) {
163  ret void
164}
165
166declare nonnull i8* @nonnull()
167
168; TEST 14
169; Complex propagation
170; Argument of f1, f2, f3 can be marked with nonnull.
171
172; * Argument
173; 1. In f1:bb6, %arg can be marked with nonnull because of the comparison in bb1
174; 2. Because f2 is internal function, f2(i32* %arg) -> @f2(i32* nonnull %arg)
175; 3. In f1:bb4 %tmp5 is nonnull and f3 is internal function.
176;    Then, f3(i32* %arg) -> @f3(i32* nonnull %arg)
177; 4. We get nonnull in whole f1 call sites so f1(i32* %arg) -> @f1(i32* nonnull %arg)
178
179
180define internal i32* @f1(i32* %arg) {
181; FIXME: missing nonnull It should be nonnull @f1(i32* nonnull readonly %arg)
182
183bb:
184  %tmp = icmp eq i32* %arg, null
185  br i1 %tmp, label %bb9, label %bb1
186
187bb1:                                              ; preds = %bb
188  %tmp2 = load i32, i32* %arg, align 4
189  %tmp3 = icmp eq i32 %tmp2, 0
190  br i1 %tmp3, label %bb6, label %bb4
191
192bb4:                                              ; preds = %bb1
193  %tmp5 = getelementptr inbounds i32, i32* %arg, i64 1
194  %tmp5b = tail call i32* @f3(i32* %tmp5)
195  %tmp5c = getelementptr inbounds i32, i32* %tmp5b, i64 -1
196  br label %bb9
197
198bb6:                                              ; preds = %bb1
199; FIXME: missing nonnull. It should be @f2(i32* nonnull %arg)
200  %tmp7 = tail call i32* @f2(i32* %arg)
201  ret i32* %tmp7
202
203bb9:                                              ; preds = %bb4, %bb
204  %tmp10 = phi i32* [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to i32*), %bb ]
205  ret i32* %tmp10
206}
207
208define internal i32* @f2(i32* %arg) {
209; FIXME: missing nonnull. It should be nonnull @f2(i32* nonnull %arg)
210bb:
211
212; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
213  %tmp = tail call i32* @f1(i32* %arg)
214  ret i32* %tmp
215}
216
217define dso_local noalias i32* @f3(i32* %arg) {
218; FIXME: missing nonnull. It should be nonnull @f3(i32* nonnull readonly %arg)
219bb:
220; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
221  %tmp = call i32* @f1(i32* %arg)
222  ret i32* %tmp
223}
224
225; TEST 15
226define void @f15(i8* %arg) {
227
228  tail call void @use1(i8* dereferenceable(4) %arg)
229  ret void
230}
231
232declare void @fun0() #1
233declare void @fun1(i8*) #1
234declare void @fun2(i8*, i8*) #1
235declare void @fun3(i8*, i8*, i8*) #1
236; TEST 16 simple path test
237; if(..)
238;   fun2(nonnull %a, nonnull %b)
239; else
240;   fun2(nonnull %a, %b)
241; We can say that %a is nonnull but %b is not.
242define void @f16(i8* %a, i8 * %b, i8 %c) {
243; FIXME: missing nonnull on %a
244  %cmp = icmp eq i8 %c, 0
245  br i1 %cmp, label %if.then, label %if.else
246if.then:
247  tail call void @fun2(i8* nonnull %a, i8* nonnull %b)
248  ret void
249if.else:
250  tail call void @fun2(i8* nonnull %a, i8* %b)
251  ret void
252}
253; TEST 17 explore child BB test
254; if(..)
255;    ... (willreturn & nounwind)
256; else
257;    ... (willreturn & nounwind)
258; fun1(nonnull %a)
259; We can say that %a is nonnull
260define void @f17(i8* %a, i8 %c) {
261  %cmp = icmp eq i8 %c, 0
262  br i1 %cmp, label %if.then, label %if.else
263if.then:
264  tail call void @fun0()
265  br label %cont
266if.else:
267  tail call void @fun0()
268  br label %cont
269cont:
270  tail call void @fun1(i8* nonnull %a)
271  ret void
272}
273; TEST 18 More complex test
274; if(..)
275;    ... (willreturn & nounwind)
276; else
277;    ... (willreturn & nounwind)
278; if(..)
279;    ... (willreturn & nounwind)
280; else
281;    ... (willreturn & nounwind)
282; fun1(nonnull %a)
283
284define void @f18(i8* %a, i8* %b, i8 %c) {
285  %cmp1 = icmp eq i8 %c, 0
286  br i1 %cmp1, label %if.then, label %if.else
287if.then:
288  tail call void @fun0()
289  br label %cont
290if.else:
291  tail call void @fun0()
292  br label %cont
293cont:
294  %cmp2 = icmp eq i8 %c, 1
295  br i1 %cmp2, label %cont.then, label %cont.else
296cont.then:
297  tail call void @fun1(i8* nonnull %b)
298  br label %cont2
299cont.else:
300  tail call void @fun0()
301  br label %cont2
302cont2:
303  tail call void @fun1(i8* nonnull %a)
304  ret void
305}
306
307; TEST 19: Loop
308
309define void @f19(i8* %a, i8* %b, i8 %c) {
310; FIXME: missing nonnull on %b
311  br label %loop.header
312loop.header:
313  %cmp2 = icmp eq i8 %c, 0
314  br i1 %cmp2, label %loop.body, label %loop.exit
315loop.body:
316  tail call void @fun1(i8* nonnull %b)
317  tail call void @fun1(i8* nonnull %a)
318  br label %loop.header
319loop.exit:
320  tail call void @fun1(i8* nonnull %b)
321  ret void
322}
323
324; Test propagation of nonnull callsite args back to caller.
325
326declare void @use1(i8* %x)
327declare void @use2(i8* %x, i8* %y);
328declare void @use3(i8* %x, i8* %y, i8* %z);
329
330declare void @use1nonnull(i8* nonnull %x);
331declare void @use2nonnull(i8* nonnull %x, i8* nonnull %y);
332declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z);
333
334declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantees that execution continues to successor
335
336; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.
337
338define void @parent1(i8* %a, i8* %b, i8* %c) {
339; FNATTR-LABEL: @parent1(i8* %a, i8* %b, i8* %c)
340; FNATTR-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
341; FNATTR-NEXT:    call void @use3nonnull(i8* %b, i8* %c, i8* %a)
342; FNATTR-NEXT:    ret void
343  call void @use3(i8* %c, i8* %a, i8* %b)
344  call void @use3nonnull(i8* %b, i8* %c, i8* %a)
345  ret void
346}
347
348; Extend non-null to parent for all arguments.
349
350define void @parent2(i8* %a, i8* %b, i8* %c) {
351; FNATTR-LABEL: @parent2(i8* nonnull %a, i8* nonnull %b, i8* nonnull %c)
352; FNATTR-NEXT:    call void @use3nonnull(i8* %b, i8* %c, i8* %a)
353; FNATTR-NEXT:    call void @use3(i8* %c, i8* %a, i8* %b)
354
355
356; FNATTR-NEXT:    ret void
357  call void @use3nonnull(i8* %b, i8* %c, i8* %a)
358  call void @use3(i8* %c, i8* %a, i8* %b)
359  ret void
360}
361
362; Extend non-null to parent for 1st argument.
363
364define void @parent3(i8* %a, i8* %b, i8* %c) {
365; FNATTR-LABEL: @parent3(i8* nonnull %a, i8* %b, i8* %c)
366; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
367; FNATTR-NEXT:    call void @use3(i8* %c, i8* %b, i8* %a)
368
369
370; FNATTR-NEXT:  ret void
371
372  call void @use1nonnull(i8* %a)
373  call void @use3(i8* %c, i8* %b, i8* %a)
374  ret void
375}
376
377; Extend non-null to parent for last 2 arguments.
378
379define void @parent4(i8* %a, i8* %b, i8* %c) {
380; CHECK-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c)
381; CHECK-NEXT:    call void @use2nonnull(i8* %c, i8* %b)
382; CHECK-NEXT:    call void @use2(i8* %a, i8* %c)
383; CHECK-NEXT:    call void @use1(i8* %b)
384
385
386; FNATTR: ret void
387
388  call void @use2nonnull(i8* %c, i8* %b)
389  call void @use2(i8* %a, i8* %c)
390  call void @use1(i8* %b)
391  ret void
392}
393
394; The callsite must execute in order for the attribute to transfer to the parent.
395; It appears benign to extend non-null to the parent in this case, but we can't do that
396; because it would incorrectly propagate the wrong information to its callers.
397
398define void @parent5(i8* %a, i1 %a_is_notnull) {
399; FNATTR: @parent5(i8* %a, i1 %a_is_notnull)
400; FNATTR-NEXT:    br i1 %a_is_notnull, label %t, label %f
401; FNATTR:       t:
402; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
403; FNATTR-NEXT:    ret void
404; FNATTR:       f:
405; FNATTR-NEXT:    ret void
406
407  br i1 %a_is_notnull, label %t, label %f
408t:
409  call void @use1nonnull(i8* %a)
410  ret void
411f:
412  ret void
413}
414
415; The callsite must execute in order for the attribute to transfer to the parent.
416; The volatile load can't trap, so we can guarantee that we'll get to the call.
417
418define i8 @parent6(i8* %a, i8* %b) {
419; FNATTR-LABEL: @parent6(i8* nonnull %a, i8* %b)
420; FNATTR-NEXT:    [[C:%.*]] = load volatile i8, i8* %b
421; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
422; FNATTR-NEXT:    ret i8 [[C]]
423
424  %c = load volatile i8, i8* %b
425  call void @use1nonnull(i8* %a)
426  ret i8 %c
427}
428
429; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.
430
431define i8 @parent7(i8* %a) {
432; FNATTR-LABEL: @parent7(i8* nonnull %a)
433; FNATTR-NEXT:    [[RET:%.*]] = call i8 @use1safecall(i8* %a)
434; FNATTR-NEXT:    call void @use1nonnull(i8* %a)
435
436
437
438; FNATTR-NEXT: ret i8 [[RET]]
439
440  %ret = call i8 @use1safecall(i8* %a)
441  call void @use1nonnull(i8* %a)
442  ret i8 %ret
443}
444
445; Make sure that an invoke works similarly to a call.
446
447declare i32 @esfp(...)
448
449define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){
450; FNATTR-LABEL: @parent8(i8* nonnull %a, i8* nocapture readnone %bogus1, i8* nonnull %b)
451; FNATTR-NEXT:  entry:
452; FNATTR-NEXT:    invoke void @use2nonnull(i8* %a, i8* %b)
453; FNATTR-NEXT:    to label %cont unwind label %exc
454; FNATTR:       cont:
455; FNATTR-NEXT:    [[NULL_CHECK:%.*]] = icmp eq i8* %b, null
456; FNATTR-NEXT:    ret i1 [[NULL_CHECK]]
457; FNATTR:       exc:
458; FNATTR-NEXT:    [[LP:%.*]] = landingpad { i8*, i32 }
459; FNATTR-NEXT:    filter [0 x i8*] zeroinitializer
460; FNATTR-NEXT:    unreachable
461
462entry:
463  invoke void @use2nonnull(i8* %a, i8* %b)
464  to label %cont unwind label %exc
465
466cont:
467  %null_check = icmp eq i8* %b, null
468  ret i1 %null_check
469
470exc:
471  %lp = landingpad { i8*, i32 }
472  filter [0 x i8*] zeroinitializer
473  unreachable
474}
475
476; FNATTR: define nonnull i32* @gep1(
477define i32* @gep1(i32* %p) {
478  %q = getelementptr inbounds i32, i32* %p, i32 1
479  ret i32* %q
480}
481
482define i32* @gep1_no_null_opt(i32* %p) #0 {
483; Should't be able to derive nonnull based on gep.
484; FNATTR: define i32* @gep1_no_null_opt(
485  %q = getelementptr inbounds i32, i32* %p, i32 1
486  ret i32* %q
487}
488
489; FNATTR: define i32 addrspace(3)* @gep2(
490define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) {
491  %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1
492  ret i32 addrspace(3)* %q
493}
494
495; FNATTR:     define i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) %p)
496; FIXME: We should propagate dereferenceable here but *not* nonnull
497define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) {
498  ret i32 addrspace(3)* %p
499}
500
501; FNATTR: define internal nonnull i32* @g2()
502define internal i32* @g2() {
503  ret i32* inttoptr (i64 4 to i32*)
504}
505
506define  i32* @g1() {
507 %c = call i32* @g2()
508  ret i32* %c
509}
510
511declare void @use_i32_ptr(i32*) readnone nounwind
512define internal void @called_by_weak(i32* %a) {
513  call void @use_i32_ptr(i32* %a)
514  ret void
515}
516
517; Check we do not annotate the function interface of this weak function.
518define weak_odr void @weak_caller(i32* nonnull %a) {
519  call void @called_by_weak(i32* %a)
520  ret void
521}
522
523; Expect nonnull
524define internal void @control(i32* dereferenceable(4) %a) {
525  call void @use_i32_ptr(i32* %a)
526  ret void
527}
528; Avoid nonnull as we do not touch naked functions
529define internal void @naked(i32* dereferenceable(4) %a) naked {
530  call void @use_i32_ptr(i32* %a)
531  ret void
532}
533; Avoid nonnull as we do not touch optnone
534define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline {
535  call void @use_i32_ptr(i32* %a)
536  ret void
537}
538define void @make_live(i32* nonnull dereferenceable(8) %a) {
539  call void @naked(i32* nonnull dereferenceable(8) align 16 %a)
540  call void @control(i32* nonnull dereferenceable(8) align 16 %a)
541  call void @optnone(i32* nonnull dereferenceable(8) align 16 %a)
542  ret void
543}
544
545;int f(int *u, int n){
546;  for(int i = 0;i<n;i++){
547;    h(u);
548;  }
549;  return g(nonnull u);
550;}
551declare void @h(i32*) willreturn nounwind
552declare i32 @g(i32*) willreturn nounwind
553define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) {
554; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1
555; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
556; FNATTR-NEXT:  en:
557; FNATTR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
558; FNATTR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
559; FNATTR:       ex:
560; FNATTR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
561; FNATTR-NEXT:    ret i32 [[TMP5]]
562; FNATTR:       hd:
563; FNATTR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
564; FNATTR-NEXT:    tail call void @h(i32* [[A]])
565; FNATTR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
566; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
567; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
568;
569;
570en:
571  %tmp3 = icmp eq i32 %b, 0
572  br i1 %tmp3, label %ex, label %hd
573
574ex:
575  %tmp5 = tail call i32 @g(i32* nonnull %a)
576  ret i32 %tmp5
577
578hd:
579  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
580  tail call void @h(i32* %a)
581  %tmp8 = add nuw i32 %tmp7, 1
582  %tmp9 = icmp eq i32 %tmp8, %b
583  br i1 %tmp9, label %ex, label %hd
584}
585
586define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) {
587; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b
588; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
589; FNATTR-NEXT:  en:
590; FNATTR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
591; FNATTR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
592; FNATTR:       ex:
593; FNATTR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
594; FNATTR-NEXT:    ret i32 [[TMP5]]
595; FNATTR:       hd:
596; FNATTR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
597; FNATTR-NEXT:    tail call void @h(i32* [[A]])
598; FNATTR-NEXT:    br label [[HD2]]
599; FNATTR:       hd2:
600; FNATTR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
601; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
602; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
603;
604;
605en:
606  %tmp3 = icmp eq i32 %b, 0
607  br i1 %tmp3, label %ex, label %hd
608
609ex:
610  %tmp5 = tail call i32 @g(i32* nonnull %a)
611  ret i32 %tmp5
612
613hd:
614  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
615  tail call void @h(i32* %a)
616  br label %hd2
617
618hd2:
619  %tmp8 = add nuw i32 %tmp7, 1
620  %tmp9 = icmp eq i32 %tmp8, %b
621  br i1 %tmp9, label %ex, label %hd
622}
623
624define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind {
625; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2
626; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
627; FNATTR-NEXT:  en:
628; FNATTR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
629; FNATTR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
630; FNATTR:       ex:
631; FNATTR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
632; FNATTR-NEXT:    ret i32 [[TMP5]]
633; FNATTR:       hd:
634; FNATTR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]
635; FNATTR-NEXT:    tail call void @h(i32* [[A]])
636; FNATTR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
637; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
638; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
639;
640;
641en:
642  %tmp3 = icmp eq i32 %b, 0
643  br i1 %tmp3, label %ex, label %hd
644
645ex:
646  %tmp5 = tail call i32 @g(i32* nonnull %a)
647  ret i32 %tmp5
648
649hd:
650  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
651  tail call void @h(i32* %a)
652  %tmp8 = add nuw i32 %tmp7, 1
653  %tmp9 = icmp eq i32 %tmp8, %b
654  br i1 %tmp9, label %ex, label %hd
655}
656
657define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind {
658; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b
659; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]])
660; FNATTR-NEXT:  en:
661; FNATTR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0
662; FNATTR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]
663; FNATTR:       ex:
664; FNATTR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]])
665; FNATTR-NEXT:    ret i32 [[TMP5]]
666; FNATTR:       hd:
667; FNATTR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]
668; FNATTR-NEXT:    tail call void @h(i32* [[A]])
669; FNATTR-NEXT:    br label [[HD2]]
670; FNATTR:       hd2:
671; FNATTR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 1
672; FNATTR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]
673; FNATTR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]
674;
675;
676en:
677  %tmp3 = icmp eq i32 %b, 0
678  br i1 %tmp3, label %ex, label %hd
679
680ex:
681  %tmp5 = tail call i32 @g(i32* nonnull %a)
682  ret i32 %tmp5
683
684hd:
685  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]
686  tail call void @h(i32* %a)
687  br label %hd2
688
689hd2:
690  %tmp8 = add nuw i32 %tmp7, 1
691  %tmp9 = icmp eq i32 %tmp8, %b
692  br i1 %tmp9, label %ex, label %hd
693}
694
695; Original from PR43833
696declare void @sink(i32*)
697
698; FIXME: the sink argument should be marked nonnull as in @PR43833_simple.
699define void @PR43833(i32* %0, i32 %1) {
700; FNATTR-LABEL: @PR43833(
701; FNATTR-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP1:%.*]], 1
702; FNATTR-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
703; FNATTR:       4:
704; FNATTR-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
705; FNATTR-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
706; FNATTR-NEXT:    br label [[TMP8:%.*]]
707; FNATTR:       7:
708; FNATTR-NEXT:    ret void
709; FNATTR:       8:
710; FNATTR-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
711; FNATTR-NEXT:    tail call void @sink(i32* [[TMP6]])
712; FNATTR-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
713; FNATTR-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
714; FNATTR-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
715;
716  %3 = icmp sgt i32 %1, 1
717  br i1 %3, label %4, label %7
718
7194:                                                ; preds = %2
720  %5 = zext i32 %1 to i64
721  %6 = getelementptr inbounds i32, i32* %0, i64 %5
722  br label %8
723
7247:                                                ; preds = %8, %2
725  ret void
726
7278:                                                ; preds = %8, %4
728  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]
729  tail call void @sink(i32* %6)
730  %10 = add nuw nsw i32 %9, 1
731  %11 = icmp eq i32 %10, %1
732  br i1 %11, label %7, label %8
733}
734
735; Adjusted from PR43833
736define void @PR43833_simple(i32* %0, i32 %1) {
737; FNATTR-LABEL: @PR43833_simple(
738; FNATTR-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0
739; FNATTR-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]
740; FNATTR:       4:
741; FNATTR-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i64
742; FNATTR-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]]
743; FNATTR-NEXT:    br label [[TMP8:%.*]]
744; FNATTR:       7:
745; FNATTR-NEXT:    ret void
746; FNATTR:       8:
747; FNATTR-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]
748; FNATTR-NEXT:    tail call void @sink(i32* [[TMP6]])
749; FNATTR-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 1
750; FNATTR-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]
751; FNATTR-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]
752;
753;
754  %3 = icmp ne i32 %1, 0
755  br i1 %3, label %4, label %7
756
7574:                                                ; preds = %2
758  %5 = zext i32 %1 to i64
759  %6 = getelementptr inbounds i32, i32* %0, i64 %5
760  br label %8
761
7627:                                                ; preds = %8, %2
763  ret void
764
7658:                                                ; preds = %8, %4
766  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]
767  tail call void @sink(i32* %6)
768  %10 = add nuw nsw i32 %9, 1
769  %11 = icmp eq i32 %10, %1
770  br i1 %11, label %7, label %8
771}
772
773attributes #0 = { null_pointer_is_valid }
774attributes #1 = { nounwind willreturn}
775