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 noundef %x); 331declare void @use1nonnull_without_noundef(i8* nonnull %x); 332declare void @use2nonnull(i8* nonnull noundef %x, i8* nonnull noundef %y); 333declare void @use3nonnull(i8* nonnull noundef %x, i8* nonnull noundef %y, i8* nonnull noundef %z); 334 335declare i8 @use1safecall(i8* %x) nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor 336 337; Without noundef, nonnull cannot be propagated to the parent 338 339define void @parent_poison(i8* %a) { 340; FNATTR-LABEL: @parent_poison(i8* %a) 341 call void @use1nonnull_without_noundef(i8* %a) 342 ret void 343} 344 345; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute. 346 347define void @parent1(i8* %a, i8* %b, i8* %c) { 348; FNATTR-LABEL: @parent1(i8* %a, i8* %b, i8* %c) 349; FNATTR-NEXT: call void @use3(i8* %c, i8* %a, i8* %b) 350; FNATTR-NEXT: call void @use3nonnull(i8* %b, i8* %c, i8* %a) 351; FNATTR-NEXT: ret void 352 call void @use3(i8* %c, i8* %a, i8* %b) 353 call void @use3nonnull(i8* %b, i8* %c, i8* %a) 354 ret void 355} 356 357; Extend non-null to parent for all arguments. 358 359define void @parent2(i8* %a, i8* %b, i8* %c) { 360; FNATTR-LABEL: @parent2(i8* nonnull %a, i8* nonnull %b, i8* nonnull %c) 361; FNATTR-NEXT: call void @use3nonnull(i8* %b, i8* %c, i8* %a) 362; FNATTR-NEXT: call void @use3(i8* %c, i8* %a, i8* %b) 363 364 365; FNATTR-NEXT: ret void 366 call void @use3nonnull(i8* %b, i8* %c, i8* %a) 367 call void @use3(i8* %c, i8* %a, i8* %b) 368 ret void 369} 370 371; Extend non-null to parent for 1st argument. 372 373define void @parent3(i8* %a, i8* %b, i8* %c) { 374; FNATTR-LABEL: @parent3(i8* nonnull %a, i8* %b, i8* %c) 375; FNATTR-NEXT: call void @use1nonnull(i8* %a) 376; FNATTR-NEXT: call void @use3(i8* %c, i8* %b, i8* %a) 377 378 379; FNATTR-NEXT: ret void 380 381 call void @use1nonnull(i8* %a) 382 call void @use3(i8* %c, i8* %b, i8* %a) 383 ret void 384} 385 386; Extend non-null to parent for last 2 arguments. 387 388define void @parent4(i8* %a, i8* %b, i8* %c) { 389; CHECK-LABEL: @parent4(i8* %a, i8* nonnull %b, i8* nonnull %c) 390; CHECK-NEXT: call void @use2nonnull(i8* %c, i8* %b) 391; CHECK-NEXT: call void @use2(i8* %a, i8* %c) 392; CHECK-NEXT: call void @use1(i8* %b) 393 394 395; FNATTR: ret void 396 397 call void @use2nonnull(i8* %c, i8* %b) 398 call void @use2(i8* %a, i8* %c) 399 call void @use1(i8* %b) 400 ret void 401} 402 403; The callsite must execute in order for the attribute to transfer to the parent. 404; It appears benign to extend non-null to the parent in this case, but we can't do that 405; because it would incorrectly propagate the wrong information to its callers. 406 407define void @parent5(i8* %a, i1 %a_is_notnull) { 408; FNATTR: @parent5(i8* %a, i1 %a_is_notnull) 409; FNATTR-NEXT: br i1 %a_is_notnull, label %t, label %f 410; FNATTR: t: 411; FNATTR-NEXT: call void @use1nonnull(i8* %a) 412; FNATTR-NEXT: ret void 413; FNATTR: f: 414; FNATTR-NEXT: ret void 415 416 br i1 %a_is_notnull, label %t, label %f 417t: 418 call void @use1nonnull(i8* %a) 419 ret void 420f: 421 ret void 422} 423 424; The callsite must execute in order for the attribute to transfer to the parent. 425; The volatile load can't trap, so we can guarantee that we'll get to the call. 426 427define i8 @parent6(i8* %a, i8* %b) { 428; FNATTR-LABEL: @parent6(i8* nonnull %a, i8* %b) 429; FNATTR-NEXT: [[C:%.*]] = load volatile i8, i8* %b 430; FNATTR-NEXT: call void @use1nonnull(i8* %a) 431; FNATTR-NEXT: ret i8 [[C]] 432 433 %c = load volatile i8, i8* %b 434 call void @use1nonnull(i8* %a) 435 ret i8 %c 436} 437 438; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent. 439 440define i8 @parent7(i8* %a) { 441; FNATTR-LABEL: @parent7(i8* nonnull %a) 442; FNATTR-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* %a) 443; FNATTR-NEXT: call void @use1nonnull(i8* %a) 444 445 446 447; FNATTR-NEXT: ret i8 [[RET]] 448 449 %ret = call i8 @use1safecall(i8* %a) 450 call void @use1nonnull(i8* %a) 451 ret i8 %ret 452} 453 454; Make sure that an invoke works similarly to a call. 455 456declare i32 @esfp(...) 457 458define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){ 459; FNATTR-LABEL: @parent8(i8* nonnull %a, i8* nocapture readnone %bogus1, i8* nonnull %b) 460; FNATTR-NEXT: entry: 461; FNATTR-NEXT: invoke void @use2nonnull(i8* %a, i8* %b) 462; FNATTR-NEXT: to label %cont unwind label %exc 463; FNATTR: cont: 464; FNATTR-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* %b, null 465; FNATTR-NEXT: ret i1 [[NULL_CHECK]] 466; FNATTR: exc: 467; FNATTR-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } 468; FNATTR-NEXT: filter [0 x i8*] zeroinitializer 469; FNATTR-NEXT: unreachable 470 471entry: 472 invoke void @use2nonnull(i8* %a, i8* %b) 473 to label %cont unwind label %exc 474 475cont: 476 %null_check = icmp eq i8* %b, null 477 ret i1 %null_check 478 479exc: 480 %lp = landingpad { i8*, i32 } 481 filter [0 x i8*] zeroinitializer 482 unreachable 483} 484 485; FNATTR: define nonnull i32* @gep1( 486define i32* @gep1(i32* %p) { 487 %q = getelementptr inbounds i32, i32* %p, i32 1 488 ret i32* %q 489} 490 491define i32* @gep1_no_null_opt(i32* %p) #0 { 492; Should't be able to derive nonnull based on gep. 493; FNATTR: define i32* @gep1_no_null_opt( 494 %q = getelementptr inbounds i32, i32* %p, i32 1 495 ret i32* %q 496} 497 498; FNATTR: define i32 addrspace(3)* @gep2( 499define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) { 500 %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1 501 ret i32 addrspace(3)* %q 502} 503 504; FNATTR: define i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) %p) 505; FIXME: We should propagate dereferenceable here but *not* nonnull 506define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) { 507 ret i32 addrspace(3)* %p 508} 509 510; FNATTR: define internal nonnull i32* @g2() 511define internal i32* @g2() { 512 ret i32* inttoptr (i64 4 to i32*) 513} 514 515define i32* @g1() { 516 %c = call i32* @g2() 517 ret i32* %c 518} 519 520declare void @use_i32_ptr(i32*) readnone nounwind 521define internal void @called_by_weak(i32* %a) { 522 call void @use_i32_ptr(i32* %a) 523 ret void 524} 525 526; Check we do not annotate the function interface of this weak function. 527define weak_odr void @weak_caller(i32* nonnull %a) { 528 call void @called_by_weak(i32* %a) 529 ret void 530} 531 532; Expect nonnull 533define internal void @control(i32* dereferenceable(4) %a) { 534 call void @use_i32_ptr(i32* %a) 535 ret void 536} 537; Avoid nonnull as we do not touch naked functions 538define internal void @naked(i32* dereferenceable(4) %a) naked { 539 call void @use_i32_ptr(i32* %a) 540 ret void 541} 542; Avoid nonnull as we do not touch optnone 543define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline { 544 call void @use_i32_ptr(i32* %a) 545 ret void 546} 547define void @make_live(i32* nonnull dereferenceable(8) %a) { 548 call void @naked(i32* nonnull dereferenceable(8) align 16 %a) 549 call void @control(i32* nonnull dereferenceable(8) align 16 %a) 550 call void @optnone(i32* nonnull dereferenceable(8) align 16 %a) 551 ret void 552} 553 554;int f(int *u, int n){ 555; for(int i = 0;i<n;i++){ 556; h(u); 557; } 558; return g(nonnull u); 559;} 560declare void @h(i32*) willreturn nounwind 561declare i32 @g(i32*) willreturn nounwind 562define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) { 563; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 564; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 565; FNATTR-NEXT: en: 566; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 567; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 568; FNATTR: ex: 569; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 570; FNATTR-NEXT: ret i32 [[TMP5]] 571; FNATTR: hd: 572; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 573; FNATTR-NEXT: tail call void @h(i32* [[A]]) 574; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 575; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 576; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 577; 578; 579en: 580 %tmp3 = icmp eq i32 %b, 0 581 br i1 %tmp3, label %ex, label %hd 582 583ex: 584 %tmp5 = tail call i32 @g(i32* nonnull %a) 585 ret i32 %tmp5 586 587hd: 588 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ] 589 tail call void @h(i32* %a) 590 %tmp8 = add nuw i32 %tmp7, 1 591 %tmp9 = icmp eq i32 %tmp8, %b 592 br i1 %tmp9, label %ex, label %hd 593} 594 595define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) { 596; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b 597; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 598; FNATTR-NEXT: en: 599; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 600; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 601; FNATTR: ex: 602; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 603; FNATTR-NEXT: ret i32 [[TMP5]] 604; FNATTR: hd: 605; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 606; FNATTR-NEXT: tail call void @h(i32* [[A]]) 607; FNATTR-NEXT: br label [[HD2]] 608; FNATTR: hd2: 609; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 610; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 611; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 612; 613; 614en: 615 %tmp3 = icmp eq i32 %b, 0 616 br i1 %tmp3, label %ex, label %hd 617 618ex: 619 %tmp5 = tail call i32 @g(i32* nonnull %a) 620 ret i32 %tmp5 621 622hd: 623 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ] 624 tail call void @h(i32* %a) 625 br label %hd2 626 627hd2: 628 %tmp8 = add nuw i32 %tmp7, 1 629 %tmp9 = icmp eq i32 %tmp8, %b 630 br i1 %tmp9, label %ex, label %hd 631} 632 633define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind { 634; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 635; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 636; FNATTR-NEXT: en: 637; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 638; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 639; FNATTR: ex: 640; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 641; FNATTR-NEXT: ret i32 [[TMP5]] 642; FNATTR: hd: 643; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 644; FNATTR-NEXT: tail call void @h(i32* [[A]]) 645; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 646; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 647; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 648; 649; 650en: 651 %tmp3 = icmp eq i32 %b, 0 652 br i1 %tmp3, label %ex, label %hd 653 654ex: 655 %tmp5 = tail call i32 @g(i32* nonnull %a) 656 ret i32 %tmp5 657 658hd: 659 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ] 660 tail call void @h(i32* %a) 661 %tmp8 = add nuw i32 %tmp7, 1 662 %tmp9 = icmp eq i32 %tmp8, %b 663 br i1 %tmp9, label %ex, label %hd 664} 665 666define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind { 667; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b 668; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 669; FNATTR-NEXT: en: 670; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 671; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 672; FNATTR: ex: 673; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 674; FNATTR-NEXT: ret i32 [[TMP5]] 675; FNATTR: hd: 676; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 677; FNATTR-NEXT: tail call void @h(i32* [[A]]) 678; FNATTR-NEXT: br label [[HD2]] 679; FNATTR: hd2: 680; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 681; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 682; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 683; 684; 685en: 686 %tmp3 = icmp eq i32 %b, 0 687 br i1 %tmp3, label %ex, label %hd 688 689ex: 690 %tmp5 = tail call i32 @g(i32* nonnull %a) 691 ret i32 %tmp5 692 693hd: 694 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ] 695 tail call void @h(i32* %a) 696 br label %hd2 697 698hd2: 699 %tmp8 = add nuw i32 %tmp7, 1 700 %tmp9 = icmp eq i32 %tmp8, %b 701 br i1 %tmp9, label %ex, label %hd 702} 703 704; Original from PR43833 705declare void @sink(i32*) 706 707; FIXME: the sink argument should be marked nonnull as in @PR43833_simple. 708define void @PR43833(i32* %0, i32 %1) { 709; FNATTR-LABEL: @PR43833( 710; FNATTR-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP1:%.*]], 1 711; FNATTR-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 712; FNATTR: 4: 713; FNATTR-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 714; FNATTR-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]] 715; FNATTR-NEXT: br label [[TMP8:%.*]] 716; FNATTR: 7: 717; FNATTR-NEXT: ret void 718; FNATTR: 8: 719; FNATTR-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 720; FNATTR-NEXT: tail call void @sink(i32* [[TMP6]]) 721; FNATTR-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 722; FNATTR-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 723; FNATTR-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 724; 725 %3 = icmp sgt i32 %1, 1 726 br i1 %3, label %4, label %7 727 7284: ; preds = %2 729 %5 = zext i32 %1 to i64 730 %6 = getelementptr inbounds i32, i32* %0, i64 %5 731 br label %8 732 7337: ; preds = %8, %2 734 ret void 735 7368: ; preds = %8, %4 737 %9 = phi i32 [ 1, %4 ], [ %10, %8 ] 738 tail call void @sink(i32* %6) 739 %10 = add nuw nsw i32 %9, 1 740 %11 = icmp eq i32 %10, %1 741 br i1 %11, label %7, label %8 742} 743 744; Adjusted from PR43833 745define void @PR43833_simple(i32* %0, i32 %1) { 746; FNATTR-LABEL: @PR43833_simple( 747; FNATTR-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0 748; FNATTR-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 749; FNATTR: 4: 750; FNATTR-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 751; FNATTR-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]] 752; FNATTR-NEXT: br label [[TMP8:%.*]] 753; FNATTR: 7: 754; FNATTR-NEXT: ret void 755; FNATTR: 8: 756; FNATTR-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 757; FNATTR-NEXT: tail call void @sink(i32* [[TMP6]]) 758; FNATTR-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 759; FNATTR-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 760; FNATTR-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 761; 762; 763 %3 = icmp ne i32 %1, 0 764 br i1 %3, label %4, label %7 765 7664: ; preds = %2 767 %5 = zext i32 %1 to i64 768 %6 = getelementptr inbounds i32, i32* %0, i64 %5 769 br label %8 770 7717: ; preds = %8, %2 772 ret void 773 7748: ; preds = %8, %4 775 %9 = phi i32 [ 1, %4 ], [ %10, %8 ] 776 tail call void @sink(i32* %6) 777 %10 = add nuw nsw i32 %9, 1 778 %11 = icmp eq i32 %10, %1 779 br i1 %11, label %7, label %8 780} 781 782attributes #0 = { null_pointer_is_valid } 783attributes #1 = { nounwind willreturn} 784