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