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