1; RUN: opt -S -functionattrs %s | FileCheck %s
2declare nonnull i8* @ret_nonnull()
3
4; Return a pointer trivially nonnull (call return attribute)
5define i8* @test1() {
6; CHECK: define nonnull i8* @test1
7  %ret = call i8* @ret_nonnull()
8  ret i8* %ret
9}
10
11; Return a pointer trivially nonnull (argument attribute)
12define i8* @test2(i8* nonnull %p) {
13; CHECK: define nonnull i8* @test2
14  ret i8* %p
15}
16
17; Given an SCC where one of the functions can not be marked nonnull,
18; can we still mark the other one which is trivially nonnull
19define i8* @scc_binder() {
20; CHECK: define i8* @scc_binder
21  call i8* @test3()
22  ret i8* null
23}
24
25define i8* @test3() {
26; CHECK: define nonnull i8* @test3
27  call i8* @scc_binder()
28  %ret = call i8* @ret_nonnull()
29  ret i8* %ret
30}
31
32; Given a mutual recursive set of functions, we can mark them
33; nonnull if neither can ever return null.  (In this case, they
34; just never return period.)
35define i8* @test4_helper() {
36; CHECK: define noalias nonnull i8* @test4_helper
37  %ret = call i8* @test4()
38  ret i8* %ret
39}
40
41define i8* @test4() {
42; CHECK: define noalias nonnull i8* @test4
43  %ret = call i8* @test4_helper()
44  ret i8* %ret
45}
46
47; Given a mutual recursive set of functions which *can* return null
48; make sure we haven't marked them as nonnull.
49define i8* @test5_helper() {
50; CHECK: define noalias i8* @test5_helper
51  %ret = call i8* @test5()
52  ret i8* null
53}
54
55define i8* @test5() {
56; CHECK: define noalias i8* @test5
57  %ret = call i8* @test5_helper()
58  ret i8* %ret
59}
60
61; Local analysis, but going through a self recursive phi
62define i8* @test6() {
63entry:
64; CHECK: define nonnull i8* @test6
65  %ret = call i8* @ret_nonnull()
66  br label %loop
67loop:
68  %phi = phi i8* [%ret, %entry], [%phi, %loop]
69  br i1 undef, label %loop, label %exit
70exit:
71  ret i8* %phi
72}
73
74
75