1; RUN: opt -S -functionattrs -enable-nonnull-arg-prop %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; Test propagation of nonnull callsite args back to caller. 75 76declare void @use1(i8* %x) 77declare void @use2(i8* %x, i8* %y); 78declare void @use3(i8* %x, i8* %y, i8* %z); 79 80declare void @use1nonnull(i8* nonnull %x); 81declare void @use2nonnull(i8* nonnull %x, i8* nonnull %y); 82declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z); 83 84declare i8 @use1safecall(i8* %x) readonly nounwind ; readonly+nounwind guarantees that execution continues to successor 85 86; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute. 87 88define void @parent1(i8* %a, i8* %b, i8* %c) { 89; CHECK-LABEL: @parent1(i8* %a, i8* %b, i8* %c) 90; CHECK-NEXT: call void @use3(i8* %c, i8* %a, i8* %b) 91; CHECK-NEXT: call void @use3nonnull(i8* %b, i8* %c, i8* %a) 92; CHECK-NEXT: ret void 93; 94 call void @use3(i8* %c, i8* %a, i8* %b) 95 call void @use3nonnull(i8* %b, i8* %c, i8* %a) 96 ret void 97} 98 99; Extend non-null to parent for all arguments. 100 101define void @parent2(i8* %a, i8* %b, i8* %c) { 102; CHECK-LABEL: @parent2(i8* nonnull %a, i8* nonnull %b, i8* nonnull %c) 103; CHECK-NEXT: call void @use3nonnull(i8* %b, i8* %c, i8* %a) 104; CHECK-NEXT: call void @use3(i8* %c, i8* %a, i8* %b) 105; CHECK-NEXT: ret void 106; 107 call void @use3nonnull(i8* %b, i8* %c, i8* %a) 108 call void @use3(i8* %c, i8* %a, i8* %b) 109 ret void 110} 111 112; Extend non-null to parent for 1st argument. 113 114define void @parent3(i8* %a, i8* %b, i8* %c) { 115; CHECK-LABEL: @parent3(i8* nonnull %a, i8* %b, i8* %c) 116; CHECK-NEXT: call void @use1nonnull(i8* %a) 117; CHECK-NEXT: call void @use3(i8* %c, i8* %b, i8* %a) 118; CHECK-NEXT: ret void 119; 120 call void @use1nonnull(i8* %a) 121 call void @use3(i8* %c, i8* %b, i8* %a) 122 ret void 123} 124 125; Extend non-null to parent for last 2 arguments. 126 127define void @parent4(i8* %a, i8* %b, i8* %c) { 128; CHECK-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c) 129; CHECK-NEXT: call void @use2nonnull(i8* %c, i8* %b) 130; CHECK-NEXT: call void @use2(i8* %a, i8* %c) 131; CHECK-NEXT: call void @use1(i8* %b) 132; CHECK-NEXT: ret void 133; 134 call void @use2nonnull(i8* %c, i8* %b) 135 call void @use2(i8* %a, i8* %c) 136 call void @use1(i8* %b) 137 ret void 138} 139 140; The callsite must execute in order for the attribute to transfer to the parent. 141; It appears benign to extend non-null to the parent in this case, but we can't do that 142; because it would incorrectly propagate the wrong information to its callers. 143 144define void @parent5(i8* %a, i1 %a_is_notnull) { 145; CHECK-LABEL: @parent5(i8* %a, i1 %a_is_notnull) 146; CHECK-NEXT: br i1 %a_is_notnull, label %t, label %f 147; CHECK: t: 148; CHECK-NEXT: call void @use1nonnull(i8* %a) 149; CHECK-NEXT: ret void 150; CHECK: f: 151; CHECK-NEXT: ret void 152; 153 br i1 %a_is_notnull, label %t, label %f 154t: 155 call void @use1nonnull(i8* %a) 156 ret void 157f: 158 ret void 159} 160 161; The callsite must execute in order for the attribute to transfer to the parent. 162; The volatile load might trap, so there's no guarantee that we'll ever get to the call. 163 164define i8 @parent6(i8* %a, i8* %b) { 165; CHECK-LABEL: @parent6(i8* %a, i8* %b) 166; CHECK-NEXT: [[C:%.*]] = load volatile i8, i8* %b 167; CHECK-NEXT: call void @use1nonnull(i8* %a) 168; CHECK-NEXT: ret i8 [[C]] 169; 170 %c = load volatile i8, i8* %b 171 call void @use1nonnull(i8* %a) 172 ret i8 %c 173} 174 175; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent. 176 177define i8 @parent7(i8* %a) { 178; CHECK-LABEL: @parent7(i8* nonnull %a) 179; CHECK-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* %a) 180; CHECK-NEXT: call void @use1nonnull(i8* %a) 181; CHECK-NEXT: ret i8 [[RET]] 182; 183 %ret = call i8 @use1safecall(i8* %a) 184 call void @use1nonnull(i8* %a) 185 ret i8 %ret 186} 187 188; Make sure that an invoke works similarly to a call. 189 190declare i32 @esfp(...) 191 192define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){ 193; CHECK-LABEL: @parent8(i8* nonnull %a, i8* nocapture readnone %bogus1, i8* nonnull %b) 194; CHECK-NEXT: entry: 195; CHECK-NEXT: invoke void @use2nonnull(i8* %a, i8* %b) 196; CHECK-NEXT: to label %cont unwind label %exc 197; CHECK: cont: 198; CHECK-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* %b, null 199; CHECK-NEXT: ret i1 [[NULL_CHECK]] 200; CHECK: exc: 201; CHECK-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } 202; CHECK-NEXT: filter [0 x i8*] zeroinitializer 203; CHECK-NEXT: unreachable 204; 205entry: 206 invoke void @use2nonnull(i8* %a, i8* %b) 207 to label %cont unwind label %exc 208 209cont: 210 %null_check = icmp eq i8* %b, null 211 ret i1 %null_check 212 213exc: 214 %lp = landingpad { i8*, i32 } 215 filter [0 x i8*] zeroinitializer 216 unreachable 217} 218 219; CHECK: define nonnull i32* @gep1( 220define i32* @gep1(i32* %p) { 221 %q = getelementptr inbounds i32, i32* %p, i32 1 222 ret i32* %q 223} 224 225; CHECK: define i32 addrspace(3)* @gep2( 226define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) { 227 %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1 228 ret i32 addrspace(3)* %q 229} 230