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-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=BOTH,OLD,ATTRIBUTOR,ATTRIBUTOR_OPM 5; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -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 nonnull readnone %a, i8* nocapture readnone %b, i8* nocapture 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* 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* 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* %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* 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* %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* readonly %arg) 240bb: 241; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg) 242; ATTRIBUTOR: %tmp = call nonnull i32* @f1(i32* %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; BOTH-LABEL: @parent8(i8* nonnull %a, i8* nocapture readnone %bogus1, i8* nonnull %b) 495; BOTH-NEXT: entry: 496; FNATTR-NEXT: invoke void @use2nonnull(i8* %a, i8* %b) 497; ATTRIBUTOR-NEXT: invoke void @use2nonnull(i8* nonnull %a, i8* nonnull %b) 498; BOTH-NEXT: to label %cont unwind label %exc 499; BOTH: cont: 500; BOTH-NEXT: [[NULL_CHECK:%.*]] = icmp eq i8* %b, null 501; BOTH-NEXT: ret i1 [[NULL_CHECK]] 502; BOTH: exc: 503; BOTH-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } 504; BOTH-NEXT: filter [0 x i8*] zeroinitializer 505; BOTH-NEXT: unreachable 506 507entry: 508 invoke void @use2nonnull(i8* %a, i8* %b) 509 to label %cont unwind label %exc 510 511cont: 512 %null_check = icmp eq i8* %b, null 513 ret i1 %null_check 514 515exc: 516 %lp = landingpad { i8*, i32 } 517 filter [0 x i8*] zeroinitializer 518 unreachable 519} 520 521; BOTH: define nonnull i32* @gep1( 522define i32* @gep1(i32* %p) { 523 %q = getelementptr inbounds i32, i32* %p, i32 1 524 ret i32* %q 525} 526 527define i32* @gep1_no_null_opt(i32* %p) #0 { 528; Should't be able to derive nonnull based on gep. 529; BOTH: define i32* @gep1_no_null_opt( 530 %q = getelementptr inbounds i32, i32* %p, i32 1 531 ret i32* %q 532} 533 534; BOTH: define i32 addrspace(3)* @gep2( 535define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) { 536 %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1 537 ret i32 addrspace(3)* %q 538} 539 540; FNATTR: define i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) %p) 541; FIXME: We should propagate dereferenceable here but *not* nonnull 542; ATTRIBUTOR: define dereferenceable_or_null(4) i32 addrspace(3)* @as(i32 addrspace(3)* readnone returned dereferenceable(4) dereferenceable_or_null(4) %p) 543define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) { 544 ret i32 addrspace(3)* %p 545} 546 547; BOTH: define internal nonnull i32* @g2() 548define internal i32* @g2() { 549 ret i32* inttoptr (i64 4 to i32*) 550} 551 552define i32* @g1() { 553 %c = call i32* @g2() 554 ret i32* %c 555} 556 557declare void @use_i32_ptr(i32*) readnone nounwind 558; ATTRIBUTOR: define internal void @called_by_weak(i32* nocapture nonnull readnone %a) 559define internal void @called_by_weak(i32* %a) { 560 call void @use_i32_ptr(i32* %a) 561 ret void 562} 563 564; Check we do not annotate the function interface of this weak function. 565; ATTRIBUTOR: define weak_odr void @weak_caller(i32* nonnull %a) 566define weak_odr void @weak_caller(i32* nonnull %a) { 567 call void @called_by_weak(i32* %a) 568 ret void 569} 570 571; Expect nonnull 572; ATTRIBUTOR: define internal void @control(i32* nocapture nonnull readnone align 16 dereferenceable(8) %a) 573define internal void @control(i32* dereferenceable(4) %a) { 574 call void @use_i32_ptr(i32* %a) 575 ret void 576} 577; Avoid nonnull as we do not touch naked functions 578; ATTRIBUTOR: define internal void @naked(i32* dereferenceable(4) %a) 579define internal void @naked(i32* dereferenceable(4) %a) naked { 580 call void @use_i32_ptr(i32* %a) 581 ret void 582} 583; Avoid nonnull as we do not touch optnone 584; ATTRIBUTOR: define internal void @optnone(i32* dereferenceable(4) %a) 585define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline { 586 call void @use_i32_ptr(i32* %a) 587 ret void 588} 589define void @make_live(i32* nonnull dereferenceable(8) %a) { 590 call void @naked(i32* nonnull dereferenceable(8) align 16 %a) 591 call void @control(i32* nonnull dereferenceable(8) align 16 %a) 592 call void @optnone(i32* nonnull dereferenceable(8) align 16 %a) 593 ret void 594} 595 596;int f(int *u, int n){ 597; for(int i = 0;i<n;i++){ 598; h(u); 599; } 600; return g(nonnull u); 601;} 602declare void @h(i32*) willreturn nounwind 603declare i32 @g(i32*) willreturn nounwind 604define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) { 605; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 606; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 607; FNATTR-NEXT: en: 608; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 609; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 610; FNATTR: ex: 611; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 612; FNATTR-NEXT: ret i32 [[TMP5]] 613; FNATTR: hd: 614; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 615; FNATTR-NEXT: tail call void @h(i32* [[A]]) 616; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 617; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 618; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 619; 620; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 621; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 622; ATTRIBUTOR-NEXT: en: 623; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 624; ATTRIBUTOR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 625; ATTRIBUTOR: ex: 626; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 627; ATTRIBUTOR-NEXT: ret i32 [[TMP5]] 628; ATTRIBUTOR: hd: 629; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 630; ATTRIBUTOR-NEXT: tail call void @h(i32* [[A]]) 631; ATTRIBUTOR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 632; ATTRIBUTOR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 633; ATTRIBUTOR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 634; 635en: 636 %tmp3 = icmp eq i32 %b, 0 637 br i1 %tmp3, label %ex, label %hd 638 639ex: 640 %tmp5 = tail call i32 @g(i32* nonnull %a) 641 ret i32 %tmp5 642 643hd: 644 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ] 645 tail call void @h(i32* %a) 646 %tmp8 = add nuw i32 %tmp7, 1 647 %tmp9 = icmp eq i32 %tmp8, %b 648 br i1 %tmp9, label %ex, label %hd 649} 650 651define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) { 652; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b 653; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 654; FNATTR-NEXT: en: 655; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 656; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 657; FNATTR: ex: 658; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 659; FNATTR-NEXT: ret i32 [[TMP5]] 660; FNATTR: hd: 661; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 662; FNATTR-NEXT: tail call void @h(i32* [[A]]) 663; FNATTR-NEXT: br label [[HD2]] 664; FNATTR: hd2: 665; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 666; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 667; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 668; 669; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b 670; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 671; ATTRIBUTOR-NEXT: en: 672; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 673; ATTRIBUTOR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 674; ATTRIBUTOR: ex: 675; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 676; ATTRIBUTOR-NEXT: ret i32 [[TMP5]] 677; ATTRIBUTOR: hd: 678; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 679; ATTRIBUTOR-NEXT: tail call void @h(i32* [[A]]) 680; ATTRIBUTOR-NEXT: br label [[HD2]] 681; ATTRIBUTOR: hd2: 682; ATTRIBUTOR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 683; ATTRIBUTOR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 684; ATTRIBUTOR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 685; 686en: 687 %tmp3 = icmp eq i32 %b, 0 688 br i1 %tmp3, label %ex, label %hd 689 690ex: 691 %tmp5 = tail call i32 @g(i32* nonnull %a) 692 ret i32 %tmp5 693 694hd: 695 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ] 696 tail call void @h(i32* %a) 697 br label %hd2 698 699hd2: 700 %tmp8 = add nuw i32 %tmp7, 1 701 %tmp9 = icmp eq i32 %tmp8, %b 702 br i1 %tmp9, label %ex, label %hd 703} 704 705define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind { 706; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 707; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 708; FNATTR-NEXT: en: 709; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 710; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 711; FNATTR: ex: 712; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 713; FNATTR-NEXT: ret i32 [[TMP5]] 714; FNATTR: hd: 715; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 716; FNATTR-NEXT: tail call void @h(i32* [[A]]) 717; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 718; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 719; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 720; 721; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 722; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 723; ATTRIBUTOR-NEXT: en: 724; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 725; ATTRIBUTOR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 726; ATTRIBUTOR: ex: 727; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 728; ATTRIBUTOR-NEXT: ret i32 [[TMP5]] 729; ATTRIBUTOR: hd: 730; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 731; ATTRIBUTOR-NEXT: tail call void @h(i32* nonnull [[A]]) 732; ATTRIBUTOR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 733; ATTRIBUTOR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 734; ATTRIBUTOR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 735; 736en: 737 %tmp3 = icmp eq i32 %b, 0 738 br i1 %tmp3, label %ex, label %hd 739 740ex: 741 %tmp5 = tail call i32 @g(i32* nonnull %a) 742 ret i32 %tmp5 743 744hd: 745 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ] 746 tail call void @h(i32* %a) 747 %tmp8 = add nuw i32 %tmp7, 1 748 %tmp9 = icmp eq i32 %tmp8, %b 749 br i1 %tmp9, label %ex, label %hd 750} 751 752define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind { 753; FNATTR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b 754; FNATTR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 755; FNATTR-NEXT: en: 756; FNATTR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 757; FNATTR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 758; FNATTR: ex: 759; FNATTR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 760; FNATTR-NEXT: ret i32 [[TMP5]] 761; FNATTR: hd: 762; FNATTR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 763; FNATTR-NEXT: tail call void @h(i32* [[A]]) 764; FNATTR-NEXT: br label [[HD2]] 765; FNATTR: hd2: 766; FNATTR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 767; FNATTR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 768; FNATTR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 769; 770; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b 771; ATTRIBUTOR-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) 772; ATTRIBUTOR-NEXT: en: 773; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B:%.*]], 0 774; ATTRIBUTOR-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 775; ATTRIBUTOR: ex: 776; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A:%.*]]) 777; ATTRIBUTOR-NEXT: ret i32 [[TMP5]] 778; ATTRIBUTOR: hd: 779; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 780; ATTRIBUTOR-NEXT: tail call void @h(i32* nonnull [[A]]) 781; ATTRIBUTOR-NEXT: br label [[HD2]] 782; ATTRIBUTOR: hd2: 783; ATTRIBUTOR-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 784; ATTRIBUTOR-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 785; ATTRIBUTOR-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 786; 787en: 788 %tmp3 = icmp eq i32 %b, 0 789 br i1 %tmp3, label %ex, label %hd 790 791ex: 792 %tmp5 = tail call i32 @g(i32* nonnull %a) 793 ret i32 %tmp5 794 795hd: 796 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ] 797 tail call void @h(i32* %a) 798 br label %hd2 799 800hd2: 801 %tmp8 = add nuw i32 %tmp7, 1 802 %tmp9 = icmp eq i32 %tmp8, %b 803 br i1 %tmp9, label %ex, label %hd 804} 805 806; Original from PR43833 807declare void @sink(i32*) 808 809; FIXME: the sink argument should be marked nonnull as in @PR43833_simple. 810define void @PR43833(i32* %0, i32 %1) { 811; BOTH-LABEL: @PR43833( 812; BOTH-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP1:%.*]], 1 813; BOTH-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 814; BOTH: 4: 815; BOTH-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 816; BOTH-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]] 817; BOTH-NEXT: br label [[TMP8:%.*]] 818; BOTH: 7: 819; BOTH-NEXT: ret void 820; BOTH: 8: 821; BOTH-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 822; BOTH-NEXT: tail call void @sink(i32* [[TMP6]]) 823; BOTH-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 824; BOTH-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 825; BOTH-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 826; 827 %3 = icmp sgt i32 %1, 1 828 br i1 %3, label %4, label %7 829 8304: ; preds = %2 831 %5 = zext i32 %1 to i64 832 %6 = getelementptr inbounds i32, i32* %0, i64 %5 833 br label %8 834 8357: ; preds = %8, %2 836 ret void 837 8388: ; preds = %8, %4 839 %9 = phi i32 [ 1, %4 ], [ %10, %8 ] 840 tail call void @sink(i32* %6) 841 %10 = add nuw nsw i32 %9, 1 842 %11 = icmp eq i32 %10, %1 843 br i1 %11, label %7, label %8 844} 845 846; Adjusted from PR43833 847define void @PR43833_simple(i32* %0, i32 %1) { 848; OLD-LABEL: @PR43833_simple( 849; OLD-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0 850; OLD-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 851; OLD: 4: 852; OLD-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 853; OLD-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]] 854; OLD-NEXT: br label [[TMP8:%.*]] 855; OLD: 7: 856; OLD-NEXT: ret void 857; OLD: 8: 858; OLD-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 859; OLD-NEXT: tail call void @sink(i32* [[TMP6]]) 860; OLD-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 861; OLD-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 862; OLD-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 863; 864; ATTRIBUTOR_NPM-LABEL: @PR43833_simple( 865; ATTRIBUTOR_NPM-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1:%.*]], 0 866; ATTRIBUTOR_NPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 867; ATTRIBUTOR_NPM: 4: 868; ATTRIBUTOR_NPM-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 869; ATTRIBUTOR_NPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0:%.*]], i64 [[TMP5]] 870; ATTRIBUTOR_NPM-NEXT: br label [[TMP8:%.*]] 871; ATTRIBUTOR_NPM: 7: 872; ATTRIBUTOR_NPM-NEXT: ret void 873; ATTRIBUTOR_NPM: 8: 874; ATTRIBUTOR_NPM-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 875; ATTRIBUTOR_NPM-NEXT: tail call void @sink(i32* nonnull [[TMP6]]) 876; ATTRIBUTOR_NPM-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 877; ATTRIBUTOR_NPM-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 878; ATTRIBUTOR_NPM-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 879; 880 %3 = icmp ne i32 %1, 0 881 br i1 %3, label %4, label %7 882 8834: ; preds = %2 884 %5 = zext i32 %1 to i64 885 %6 = getelementptr inbounds i32, i32* %0, i64 %5 886 br label %8 887 8887: ; preds = %8, %2 889 ret void 890 8918: ; preds = %8, %4 892 %9 = phi i32 [ 1, %4 ], [ %10, %8 ] 893 tail call void @sink(i32* %6) 894 %10 = add nuw nsw i32 %9, 1 895 %11 = icmp eq i32 %10, %1 896 br i1 %11, label %7, label %8 897} 898 899attributes #0 = { "null-pointer-is-valid"="true" } 900attributes #1 = { nounwind willreturn} 901