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