1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=15 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM 6 7 8target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 9 10declare nonnull i8* @ret_nonnull() 11declare void @llvm.assume(i1) 12 13; Return a pointer trivially nonnull (call return attribute) 14define i8* @test1() { 15; CHECK-LABEL: define {{[^@]+}}@test1() { 16; CHECK-NEXT: [[RET:%.*]] = call nonnull i8* @ret_nonnull() 17; CHECK-NEXT: ret i8* [[RET]] 18; 19 %ret = call i8* @ret_nonnull() 20 ret i8* %ret 21} 22 23; Return a pointer trivially nonnull (argument attribute) 24define i8* @test2(i8* nonnull %p) { 25; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 26; CHECK-LABEL: define {{[^@]+}}@test2 27; CHECK-SAME: (i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1:[0-9]+]] { 28; CHECK-NEXT: ret i8* [[P]] 29; 30 ret i8* %p 31} 32 33define i8* @test2A(i1 %c, i8* %ret) { 34; CHECK: Function Attrs: inaccessiblememonly nofree norecurse nosync nounwind willreturn 35; CHECK-LABEL: define {{[^@]+}}@test2A 36; CHECK-SAME: (i1 [[C:%.*]], i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2:[0-9]+]] { 37; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] 38; CHECK: A: 39; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR13:[0-9]+]] [ "nonnull"(i8* [[RET]]) ] 40; CHECK-NEXT: ret i8* [[RET]] 41; CHECK: B: 42; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR13]] [ "nonnull"(i8* [[RET]]) ] 43; CHECK-NEXT: ret i8* [[RET]] 44; 45 br i1 %c, label %A, label %B 46A: 47 call void @llvm.assume(i1 true) [ "nonnull"(i8* %ret) ] 48 ret i8* %ret 49B: 50 call void @llvm.assume(i1 true) [ "nonnull"(i8* %ret) ] 51 ret i8* %ret 52} 53 54define i8* @test2B(i1 %c, i8* %ret) { 55; CHECK: Function Attrs: inaccessiblememonly nofree norecurse nosync nounwind willreturn 56; CHECK-LABEL: define {{[^@]+}}@test2B 57; CHECK-SAME: (i1 [[C:%.*]], i8* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2]] { 58; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] 59; CHECK: A: 60; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR13]] [ "dereferenceable"(i8* [[RET]], i32 4) ] 61; CHECK-NEXT: ret i8* [[RET]] 62; CHECK: B: 63; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR13]] [ "dereferenceable"(i8* [[RET]], i32 4) ] 64; CHECK-NEXT: ret i8* [[RET]] 65; 66 br i1 %c, label %A, label %B 67A: 68 call void @llvm.assume(i1 true) [ "dereferenceable"(i8* %ret, i32 4) ] 69 ret i8* %ret 70B: 71 call void @llvm.assume(i1 true) [ "dereferenceable"(i8* %ret, i32 4) ] 72 ret i8* %ret 73} 74 75; Given an SCC where one of the functions can not be marked nonnull, 76; can we still mark the other one which is trivially nonnull 77define i8* @scc_binder(i1 %c) { 78; IS________OPM-LABEL: define {{[^@]+}}@scc_binder 79; IS________OPM-SAME: (i1 [[C:%.*]]) { 80; IS________OPM-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] 81; IS________OPM: rec: 82; IS________OPM-NEXT: [[TMP1:%.*]] = call i8* @test3(i1 [[C]]) 83; IS________OPM-NEXT: br label [[END]] 84; IS________OPM: end: 85; IS________OPM-NEXT: ret i8* null 86; 87; IS________NPM-LABEL: define {{[^@]+}}@scc_binder 88; IS________NPM-SAME: (i1 [[C:%.*]]) { 89; IS________NPM-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] 90; IS________NPM: rec: 91; IS________NPM-NEXT: [[TMP1:%.*]] = call i8* @test3(i1 noundef [[C]]) 92; IS________NPM-NEXT: br label [[END]] 93; IS________NPM: end: 94; IS________NPM-NEXT: ret i8* null 95; 96 br i1 %c, label %rec, label %end 97rec: 98 call i8* @test3(i1 %c) 99 br label %end 100end: 101 ret i8* null 102} 103 104define i8* @test3(i1 %c) { 105; CHECK-LABEL: define {{[^@]+}}@test3 106; CHECK-SAME: (i1 [[C:%.*]]) { 107; CHECK-NEXT: [[TMP1:%.*]] = call i8* @scc_binder(i1 [[C]]) 108; CHECK-NEXT: [[RET:%.*]] = call nonnull i8* @ret_nonnull() 109; CHECK-NEXT: ret i8* [[RET]] 110; 111 call i8* @scc_binder(i1 %c) 112 %ret = call i8* @ret_nonnull() 113 ret i8* %ret 114} 115 116; Given a mutual recursive set of functions, we can mark them 117; nonnull if neither can ever return null. (In this case, they 118; just never return period.) 119define i8* @test4_helper() { 120; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 121; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper 122; NOT_CGSCC_NPM-SAME: () #[[ATTR3:[0-9]+]] { 123; NOT_CGSCC_NPM-NEXT: ret i8* undef 124; 125; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 126; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper 127; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 128; IS__CGSCC_NPM-NEXT: ret i8* undef 129; 130 %ret = call i8* @test4() 131 ret i8* %ret 132} 133 134define i8* @test4() { 135; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 136; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4 137; NOT_CGSCC_NPM-SAME: () #[[ATTR3]] { 138; NOT_CGSCC_NPM-NEXT: ret i8* undef 139; 140; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 141; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4 142; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { 143; IS__CGSCC_NPM-NEXT: ret i8* undef 144; 145 %ret = call i8* @test4_helper() 146 ret i8* %ret 147} 148 149; Given a mutual recursive set of functions which *can* return null 150; make sure we haven't marked them as nonnull. 151define i8* @test5_helper(i1 %c) { 152; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 153; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test5_helper 154; NOT_CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR3]] { 155; NOT_CGSCC_NPM-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] 156; NOT_CGSCC_NPM: rec: 157; NOT_CGSCC_NPM-NEXT: br label [[END]] 158; NOT_CGSCC_NPM: end: 159; NOT_CGSCC_NPM-NEXT: ret i8* null 160; 161; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 162; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test5_helper 163; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 164; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] 165; IS__CGSCC_NPM: rec: 166; IS__CGSCC_NPM-NEXT: br label [[END]] 167; IS__CGSCC_NPM: end: 168; IS__CGSCC_NPM-NEXT: ret i8* null 169; 170 br i1 %c, label %rec, label %end 171rec: 172 %ret = call i8* @test5(i1 %c) 173 br label %end 174end: 175 ret i8* null 176} 177 178define i8* @test5(i1 %c) { 179; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 180; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test5 181; NOT_CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR3]] { 182; NOT_CGSCC_NPM-NEXT: ret i8* null 183; 184; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 185; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test5 186; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] { 187; IS__CGSCC_NPM-NEXT: ret i8* null 188; 189 %ret = call i8* @test5_helper(i1 %c) 190 ret i8* %ret 191} 192 193; Local analysis, but going through a self recursive phi 194define i8* @test6a() { 195; 196; NOT_CGSCC_NPM: Function Attrs: noreturn 197; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6a 198; NOT_CGSCC_NPM-SAME: () #[[ATTR4:[0-9]+]] { 199; NOT_CGSCC_NPM-NEXT: entry: 200; NOT_CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @ret_nonnull() 201; NOT_CGSCC_NPM-NEXT: br label [[LOOP:%.*]] 202; NOT_CGSCC_NPM: loop: 203; NOT_CGSCC_NPM-NEXT: unreachable 204; NOT_CGSCC_NPM: exit: 205; NOT_CGSCC_NPM-NEXT: unreachable 206; 207; IS__CGSCC_NPM: Function Attrs: noreturn 208; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test6a 209; IS__CGSCC_NPM-SAME: () #[[ATTR3:[0-9]+]] { 210; IS__CGSCC_NPM-NEXT: entry: 211; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @ret_nonnull() 212; IS__CGSCC_NPM-NEXT: br label [[LOOP:%.*]] 213; IS__CGSCC_NPM: loop: 214; IS__CGSCC_NPM-NEXT: unreachable 215; IS__CGSCC_NPM: exit: 216; IS__CGSCC_NPM-NEXT: unreachable 217; 218entry: 219 %ret = call i8* @ret_nonnull() 220 br label %loop 221loop: 222 %phi = phi i8* [%ret, %entry], [%phi, %loop] 223 br i1 undef, label %loop, label %exit 224exit: 225 ret i8* %phi 226} 227 228define i8* @test6b(i1 %c) { 229; IS________OPM-LABEL: define {{[^@]+}}@test6b 230; IS________OPM-SAME: (i1 [[C:%.*]]) { 231; IS________OPM-NEXT: entry: 232; IS________OPM-NEXT: [[RET:%.*]] = call nonnull i8* @ret_nonnull() 233; IS________OPM-NEXT: br label [[LOOP:%.*]] 234; IS________OPM: loop: 235; IS________OPM-NEXT: [[PHI:%.*]] = phi i8* [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] 236; IS________OPM-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 237; IS________OPM: exit: 238; IS________OPM-NEXT: ret i8* [[PHI]] 239; 240; IS________NPM-LABEL: define {{[^@]+}}@test6b 241; IS________NPM-SAME: (i1 [[C:%.*]]) { 242; IS________NPM-NEXT: entry: 243; IS________NPM-NEXT: [[RET:%.*]] = call nonnull i8* @ret_nonnull() 244; IS________NPM-NEXT: br label [[LOOP:%.*]] 245; IS________NPM: loop: 246; IS________NPM-NEXT: [[PHI:%.*]] = phi i8* [ [[RET]], [[ENTRY:%.*]] ], [ [[RET]], [[LOOP]] ] 247; IS________NPM-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 248; IS________NPM: exit: 249; IS________NPM-NEXT: ret i8* [[RET]] 250; 251entry: 252 %ret = call i8* @ret_nonnull() 253 br label %loop 254loop: 255 %phi = phi i8* [%ret, %entry], [%phi, %loop] 256 br i1 %c, label %loop, label %exit 257exit: 258 ret i8* %phi 259} 260 261define i8* @test7(i8* %a) { 262; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 263; CHECK-LABEL: define {{[^@]+}}@test7 264; CHECK-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] { 265; CHECK-NEXT: ret i8* [[A]] 266; 267 %b = getelementptr inbounds i8, i8* %a, i64 0 268 ret i8* %b 269} 270 271define i8* @test8(i8* %a) { 272; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 273; CHECK-LABEL: define {{[^@]+}}@test8 274; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] { 275; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 1 276; CHECK-NEXT: ret i8* [[B]] 277; 278 %b = getelementptr inbounds i8, i8* %a, i64 1 279 ret i8* %b 280} 281 282define i8* @test9(i8* %a, i64 %n) { 283; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 284; CHECK-LABEL: define {{[^@]+}}@test9 285; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR1]] { 286; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 [[N]] 287; CHECK-NEXT: ret i8* [[B]] 288; 289 %b = getelementptr inbounds i8, i8* %a, i64 %n 290 ret i8* %b 291} 292 293; ATTRIBUTOR_OPM: define i8* @test10 294; ATTRIBUTOR_NPM: define nonnull i8* @test10 295define i8* @test10(i8* %a, i64 %n) { 296; CHECK: Function Attrs: inaccessiblememonly nofree norecurse nosync nounwind willreturn 297; CHECK-LABEL: define {{[^@]+}}@test10 298; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR2]] { 299; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[N]], 0 300; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CMP]]) #[[ATTR13]] 301; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 [[N]] 302; CHECK-NEXT: ret i8* [[B]] 303; 304 %cmp = icmp ne i64 %n, 0 305 call void @llvm.assume(i1 %cmp) 306 %b = getelementptr inbounds i8, i8* %a, i64 %n 307 ret i8* %b 308} 309 310; TEST 11 311; char* test11(char *p) { 312; return p? p: nonnull(); 313; } 314; FIXME: missing nonnull 315define i8* @test11(i8*) local_unnamed_addr { 316; CHECK-LABEL: define {{[^@]+}}@test11 317; CHECK-SAME: (i8* [[TMP0:%.*]]) local_unnamed_addr { 318; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null 319; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] 320; CHECK: 3: 321; CHECK-NEXT: [[TMP4:%.*]] = tail call i8* @ret_nonnull() 322; CHECK-NEXT: br label [[TMP5]] 323; CHECK: 5: 324; CHECK-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] 325; CHECK-NEXT: ret i8* [[TMP6]] 326; 327 %2 = icmp eq i8* %0, null 328 br i1 %2, label %3, label %5 329 330; <label>:3: ; preds = %1 331 %4 = tail call i8* @ret_nonnull() 332 br label %5 333 334; <label>:5: ; preds = %3, %1 335 %6 = phi i8* [ %4, %3 ], [ %0, %1 ] 336 ret i8* %6 337} 338 339; TEST 12 340; Simple CallSite Test 341declare void @test12_helper(i8*) 342define void @test12(i8* nonnull %a) { 343; CHECK-LABEL: define {{[^@]+}}@test12 344; CHECK-SAME: (i8* nonnull [[A:%.*]]) { 345; CHECK-NEXT: tail call void @test12_helper(i8* nonnull [[A]]) 346; CHECK-NEXT: ret void 347; 348 tail call void @test12_helper(i8* %a) 349 ret void 350} 351 352; TEST 13 353; Simple Argument Tests 354declare i8* @unknown() 355define void @test13_helper() { 356; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test13_helper() { 357; NOT_CGSCC_NPM-NEXT: [[NONNULLPTR:%.*]] = tail call nonnull i8* @ret_nonnull() 358; NOT_CGSCC_NPM-NEXT: [[MAYBENULLPTR:%.*]] = tail call i8* @unknown() 359; NOT_CGSCC_NPM-NEXT: tail call void @test13(i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]], i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]], i8* noalias nocapture nofree readnone [[MAYBENULLPTR]]) #[[ATTR5:[0-9]+]] 360; NOT_CGSCC_NPM-NEXT: tail call void @test13(i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]], i8* noalias nocapture nofree readnone [[MAYBENULLPTR]], i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]]) #[[ATTR5]] 361; NOT_CGSCC_NPM-NEXT: ret void 362; 363; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test13_helper() { 364; IS__CGSCC_NPM-NEXT: [[NONNULLPTR:%.*]] = tail call nonnull i8* @ret_nonnull() 365; IS__CGSCC_NPM-NEXT: [[MAYBENULLPTR:%.*]] = tail call i8* @unknown() 366; IS__CGSCC_NPM-NEXT: tail call void @test13(i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]], i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]], i8* noalias nocapture nofree readnone [[MAYBENULLPTR]]) #[[ATTR4:[0-9]+]] 367; IS__CGSCC_NPM-NEXT: tail call void @test13(i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]], i8* noalias nocapture nofree readnone [[MAYBENULLPTR]], i8* noalias nocapture nofree nonnull readnone [[NONNULLPTR]]) #[[ATTR4]] 368; IS__CGSCC_NPM-NEXT: ret void 369; 370 %nonnullptr = tail call i8* @ret_nonnull() 371 %maybenullptr = tail call i8* @unknown() 372 tail call void @test13(i8* %nonnullptr, i8* %nonnullptr, i8* %maybenullptr) 373 tail call void @test13(i8* %nonnullptr, i8* %maybenullptr, i8* %nonnullptr) 374 ret void 375} 376define internal void @test13(i8* %a, i8* %b, i8* %c) { 377; 378; NOT_CGSCC_NPM: Function Attrs: nounwind 379; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test13 380; NOT_CGSCC_NPM-SAME: (i8* noalias nocapture nofree nonnull readnone [[A:%.*]], i8* noalias nocapture nofree readnone [[B:%.*]], i8* noalias nocapture nofree readnone [[C:%.*]]) #[[ATTR5]] { 381; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[A]]) #[[ATTR5]] 382; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[B]]) #[[ATTR5]] 383; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[C]]) #[[ATTR5]] 384; NOT_CGSCC_NPM-NEXT: ret void 385; 386; IS__CGSCC_NPM: Function Attrs: nounwind 387; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test13 388; IS__CGSCC_NPM-SAME: (i8* noalias nocapture nofree nonnull readnone [[A:%.*]], i8* noalias nocapture nofree readnone [[B:%.*]], i8* noalias nocapture nofree readnone [[C:%.*]]) #[[ATTR4]] { 389; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[A]]) #[[ATTR4]] 390; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[B]]) #[[ATTR4]] 391; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[C]]) #[[ATTR4]] 392; IS__CGSCC_NPM-NEXT: ret void 393; 394 call void @use_i8_ptr(i8* %a) 395 call void @use_i8_ptr(i8* %b) 396 call void @use_i8_ptr(i8* %c) 397 ret void 398} 399 400declare nonnull i8* @nonnull() 401 402; TEST 14 403; Complex propagation 404; Argument of f1, f2, f3 can be marked with nonnull. 405 406; * Argument 407; 1. In f1:bb6, %arg can be marked with nonnull because of the comparison in bb1 408; 2. Because f2 is internal function, f2(i32* %arg) -> @f2(i32* nonnull %arg) 409; 3. In f1:bb4 %tmp5 is nonnull and f3 is internal function. 410; Then, f3(i32* %arg) -> @f3(i32* nonnull %arg) 411; 4. We get nonnull in whole f1 call sites so f1(i32* %arg) -> @f1(i32* nonnull %arg) 412 413 414define internal i32* @f1(i32* %arg) { 415; FIXME: missing nonnull It should be nonnull @f1(i32* nonnull readonly %arg) 416; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly 417; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f1 418; NOT_CGSCC_NPM-SAME: (i32* nofree readonly [[ARG:%.*]]) #[[ATTR6:[0-9]+]] { 419; NOT_CGSCC_NPM-NEXT: bb: 420; NOT_CGSCC_NPM-NEXT: [[TMP:%.*]] = icmp eq i32* [[ARG]], null 421; NOT_CGSCC_NPM-NEXT: br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]] 422; NOT_CGSCC_NPM: bb1: 423; NOT_CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARG]], align 4 424; NOT_CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 425; NOT_CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]] 426; NOT_CGSCC_NPM: bb4: 427; NOT_CGSCC_NPM-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 1 428; NOT_CGSCC_NPM-NEXT: [[TMP5B:%.*]] = tail call i32* @f3(i32* nofree nonnull readonly [[TMP5]]) #[[ATTR14:[0-9]+]] 429; NOT_CGSCC_NPM-NEXT: [[TMP5C:%.*]] = getelementptr inbounds i32, i32* [[TMP5B]], i64 -1 430; NOT_CGSCC_NPM-NEXT: br label [[BB9]] 431; NOT_CGSCC_NPM: bb6: 432; NOT_CGSCC_NPM-NEXT: [[TMP7:%.*]] = tail call i32* @f2(i32* nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR14]] 433; NOT_CGSCC_NPM-NEXT: ret i32* [[TMP7]] 434; NOT_CGSCC_NPM: bb9: 435; NOT_CGSCC_NPM-NEXT: [[TMP10:%.*]] = phi i32* [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to i32*), [[BB:%.*]] ] 436; NOT_CGSCC_NPM-NEXT: ret i32* [[TMP10]] 437; 438; IS__CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly 439; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1 440; IS__CGSCC_NPM-SAME: (i32* nofree readonly [[ARG:%.*]]) #[[ATTR5:[0-9]+]] { 441; IS__CGSCC_NPM-NEXT: bb: 442; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = icmp eq i32* [[ARG]], null 443; IS__CGSCC_NPM-NEXT: br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]] 444; IS__CGSCC_NPM: bb1: 445; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARG]], align 4 446; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 447; IS__CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]] 448; IS__CGSCC_NPM: bb4: 449; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARG]], i64 1 450; IS__CGSCC_NPM-NEXT: [[TMP5B:%.*]] = tail call i32* @f3(i32* nofree nonnull readonly [[TMP5]]) #[[ATTR14:[0-9]+]] 451; IS__CGSCC_NPM-NEXT: [[TMP5C:%.*]] = getelementptr inbounds i32, i32* [[TMP5B]], i64 -1 452; IS__CGSCC_NPM-NEXT: br label [[BB9]] 453; IS__CGSCC_NPM: bb6: 454; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = tail call i32* @f2(i32* nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR14]] 455; IS__CGSCC_NPM-NEXT: ret i32* [[TMP7]] 456; IS__CGSCC_NPM: bb9: 457; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = phi i32* [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to i32*), [[BB:%.*]] ] 458; IS__CGSCC_NPM-NEXT: ret i32* [[TMP10]] 459; 460 461bb: 462 %tmp = icmp eq i32* %arg, null 463 br i1 %tmp, label %bb9, label %bb1 464 465bb1: ; preds = %bb 466 %tmp2 = load i32, i32* %arg, align 4 467 %tmp3 = icmp eq i32 %tmp2, 0 468 br i1 %tmp3, label %bb6, label %bb4 469 470bb4: ; preds = %bb1 471 %tmp5 = getelementptr inbounds i32, i32* %arg, i64 1 472 %tmp5b = tail call i32* @f3(i32* %tmp5) 473 %tmp5c = getelementptr inbounds i32, i32* %tmp5b, i64 -1 474 br label %bb9 475 476bb6: ; preds = %bb1 477 %tmp7 = tail call i32* @f2(i32* %arg) 478 ret i32* %tmp7 479 480bb9: ; preds = %bb4, %bb 481 %tmp10 = phi i32* [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to i32*), %bb ] 482 ret i32* %tmp10 483} 484 485define internal i32* @f2(i32* %arg) { 486; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly 487; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f2 488; NOT_CGSCC_NPM-SAME: (i32* nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR6]] { 489; NOT_CGSCC_NPM-NEXT: bb: 490; NOT_CGSCC_NPM-NEXT: [[TMP:%.*]] = tail call i32* @f1(i32* nofree readonly [[ARG]]) #[[ATTR14]] 491; NOT_CGSCC_NPM-NEXT: ret i32* [[TMP]] 492; 493; IS__CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly 494; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f2 495; IS__CGSCC_NPM-SAME: (i32* nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR5]] { 496; IS__CGSCC_NPM-NEXT: bb: 497; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = tail call i32* @f1(i32* nofree readonly [[ARG]]) #[[ATTR14]] 498; IS__CGSCC_NPM-NEXT: ret i32* [[TMP]] 499; 500bb: 501 %tmp = tail call i32* @f1(i32* %arg) 502 ret i32* %tmp 503} 504 505define dso_local noalias i32* @f3(i32* %arg) { 506; FIXME: missing nonnull. It should be nonnull @f3(i32* nonnull readonly %arg) 507; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly 508; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f3 509; NOT_CGSCC_NPM-SAME: (i32* nofree readonly [[ARG:%.*]]) #[[ATTR6]] { 510; NOT_CGSCC_NPM-NEXT: bb: 511; NOT_CGSCC_NPM-NEXT: [[TMP:%.*]] = call i32* @f1(i32* nofree readonly [[ARG]]) #[[ATTR14]] 512; NOT_CGSCC_NPM-NEXT: ret i32* [[TMP]] 513; 514; IS__CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly 515; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f3 516; IS__CGSCC_NPM-SAME: (i32* nofree readonly [[ARG:%.*]]) #[[ATTR5]] { 517; IS__CGSCC_NPM-NEXT: bb: 518; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = call i32* @f1(i32* nofree readonly [[ARG]]) #[[ATTR14]] 519; IS__CGSCC_NPM-NEXT: ret i32* [[TMP]] 520; 521bb: 522; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg) 523 %tmp = call i32* @f1(i32* %arg) 524 ret i32* %tmp 525} 526 527; TEST 15 528define void @f15(i8* %arg) { 529; CHECK-LABEL: define {{[^@]+}}@f15 530; CHECK-SAME: (i8* noundef nonnull dereferenceable(4) [[ARG:%.*]]) { 531; CHECK-NEXT: tail call void @use1(i8* noundef nonnull dereferenceable(4) [[ARG]]) 532; CHECK-NEXT: ret void 533; 534 535 tail call void @use1(i8* dereferenceable(4) %arg) 536 ret void 537} 538 539declare void @fun0() #1 540declare void @fun1(i8*) #1 541declare void @fun2(i8*, i8*) #1 542declare void @fun3(i8*, i8*, i8*) #1 543; TEST 16 simple path test 544; if(..) 545; fun2(nonnull %a, nonnull %b) 546; else 547; fun2(nonnull %a, %b) 548; We can say that %a is nonnull but %b is not. 549define void @f16(i8* %a, i8 * %b, i8 %c) { 550; NOT_CGSCC_NPM: Function Attrs: nounwind willreturn 551; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f16 552; NOT_CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7:[0-9]+]] { 553; NOT_CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 554; NOT_CGSCC_NPM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 555; NOT_CGSCC_NPM: if.then: 556; NOT_CGSCC_NPM-NEXT: tail call void @fun2(i8* nonnull [[A]], i8* nonnull [[B]]) #[[ATTR7]] 557; NOT_CGSCC_NPM-NEXT: ret void 558; NOT_CGSCC_NPM: if.else: 559; NOT_CGSCC_NPM-NEXT: tail call void @fun2(i8* nonnull [[A]], i8* [[B]]) #[[ATTR7]] 560; NOT_CGSCC_NPM-NEXT: ret void 561; 562; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 563; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f16 564; IS__CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) #[[ATTR6:[0-9]+]] { 565; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 566; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 567; IS__CGSCC_NPM: if.then: 568; IS__CGSCC_NPM-NEXT: tail call void @fun2(i8* nonnull [[A]], i8* nonnull [[B]]) #[[ATTR6]] 569; IS__CGSCC_NPM-NEXT: ret void 570; IS__CGSCC_NPM: if.else: 571; IS__CGSCC_NPM-NEXT: tail call void @fun2(i8* nonnull [[A]], i8* [[B]]) #[[ATTR6]] 572; IS__CGSCC_NPM-NEXT: ret void 573; 574 %cmp = icmp eq i8 %c, 0 575 br i1 %cmp, label %if.then, label %if.else 576if.then: 577 tail call void @fun2(i8* nonnull %a, i8* nonnull %b) 578 ret void 579if.else: 580 tail call void @fun2(i8* nonnull %a, i8* %b) 581 ret void 582} 583; TEST 17 explore child BB test 584; if(..) 585; ... (willreturn & nounwind) 586; else 587; ... (willreturn & nounwind) 588; fun1(nonnull %a) 589; We can say that %a is nonnull 590define void @f17(i8* %a, i8 %c) { 591; 592; NOT_CGSCC_NPM: Function Attrs: nounwind willreturn 593; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f17 594; NOT_CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR7]] { 595; NOT_CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 596; NOT_CGSCC_NPM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 597; NOT_CGSCC_NPM: if.then: 598; NOT_CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR7]] 599; NOT_CGSCC_NPM-NEXT: br label [[CONT:%.*]] 600; NOT_CGSCC_NPM: if.else: 601; NOT_CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR7]] 602; NOT_CGSCC_NPM-NEXT: br label [[CONT]] 603; NOT_CGSCC_NPM: cont: 604; NOT_CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[A]]) #[[ATTR7]] 605; NOT_CGSCC_NPM-NEXT: ret void 606; 607; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 608; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f17 609; IS__CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR6]] { 610; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 611; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 612; IS__CGSCC_NPM: if.then: 613; IS__CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR6]] 614; IS__CGSCC_NPM-NEXT: br label [[CONT:%.*]] 615; IS__CGSCC_NPM: if.else: 616; IS__CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR6]] 617; IS__CGSCC_NPM-NEXT: br label [[CONT]] 618; IS__CGSCC_NPM: cont: 619; IS__CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[A]]) #[[ATTR6]] 620; IS__CGSCC_NPM-NEXT: ret void 621; 622 %cmp = icmp eq i8 %c, 0 623 br i1 %cmp, label %if.then, label %if.else 624if.then: 625 tail call void @fun0() 626 br label %cont 627if.else: 628 tail call void @fun0() 629 br label %cont 630cont: 631 tail call void @fun1(i8* nonnull %a) 632 ret void 633} 634; TEST 18 More complex test 635; if(..) 636; ... (willreturn & nounwind) 637; else 638; ... (willreturn & nounwind) 639; if(..) 640; ... (willreturn & nounwind) 641; else 642; ... (willreturn & nounwind) 643; fun1(nonnull %a) 644 645define void @f18(i8* %a, i8* %b, i8 %c) { 646; NOT_CGSCC_NPM: Function Attrs: nounwind willreturn 647; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f18 648; NOT_CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7]] { 649; NOT_CGSCC_NPM-NEXT: [[CMP1:%.*]] = icmp eq i8 [[C]], 0 650; NOT_CGSCC_NPM-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 651; NOT_CGSCC_NPM: if.then: 652; NOT_CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR7]] 653; NOT_CGSCC_NPM-NEXT: br label [[CONT:%.*]] 654; NOT_CGSCC_NPM: if.else: 655; NOT_CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR7]] 656; NOT_CGSCC_NPM-NEXT: br label [[CONT]] 657; NOT_CGSCC_NPM: cont: 658; NOT_CGSCC_NPM-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 1 659; NOT_CGSCC_NPM-NEXT: br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]] 660; NOT_CGSCC_NPM: cont.then: 661; NOT_CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[B]]) #[[ATTR7]] 662; NOT_CGSCC_NPM-NEXT: br label [[CONT2:%.*]] 663; NOT_CGSCC_NPM: cont.else: 664; NOT_CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR7]] 665; NOT_CGSCC_NPM-NEXT: br label [[CONT2]] 666; NOT_CGSCC_NPM: cont2: 667; NOT_CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[A]]) #[[ATTR7]] 668; NOT_CGSCC_NPM-NEXT: ret void 669; 670; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 671; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f18 672; IS__CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) #[[ATTR6]] { 673; IS__CGSCC_NPM-NEXT: [[CMP1:%.*]] = icmp eq i8 [[C]], 0 674; IS__CGSCC_NPM-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 675; IS__CGSCC_NPM: if.then: 676; IS__CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR6]] 677; IS__CGSCC_NPM-NEXT: br label [[CONT:%.*]] 678; IS__CGSCC_NPM: if.else: 679; IS__CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR6]] 680; IS__CGSCC_NPM-NEXT: br label [[CONT]] 681; IS__CGSCC_NPM: cont: 682; IS__CGSCC_NPM-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 1 683; IS__CGSCC_NPM-NEXT: br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]] 684; IS__CGSCC_NPM: cont.then: 685; IS__CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[B]]) #[[ATTR6]] 686; IS__CGSCC_NPM-NEXT: br label [[CONT2:%.*]] 687; IS__CGSCC_NPM: cont.else: 688; IS__CGSCC_NPM-NEXT: tail call void @fun0() #[[ATTR6]] 689; IS__CGSCC_NPM-NEXT: br label [[CONT2]] 690; IS__CGSCC_NPM: cont2: 691; IS__CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[A]]) #[[ATTR6]] 692; IS__CGSCC_NPM-NEXT: ret void 693; 694 %cmp1 = icmp eq i8 %c, 0 695 br i1 %cmp1, label %if.then, label %if.else 696if.then: 697 tail call void @fun0() 698 br label %cont 699if.else: 700 tail call void @fun0() 701 br label %cont 702cont: 703 %cmp2 = icmp eq i8 %c, 1 704 br i1 %cmp2, label %cont.then, label %cont.else 705cont.then: 706 tail call void @fun1(i8* nonnull %b) 707 br label %cont2 708cont.else: 709 tail call void @fun0() 710 br label %cont2 711cont2: 712 tail call void @fun1(i8* nonnull %a) 713 ret void 714} 715 716; TEST 19: Loop 717 718define void @f19(i8* %a, i8* %b, i8 %c) { 719; NOT_CGSCC_NPM: Function Attrs: nounwind 720; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@f19 721; NOT_CGSCC_NPM-SAME: (i8* [[A:%.*]], i8* nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR5]] { 722; NOT_CGSCC_NPM-NEXT: br label [[LOOP_HEADER:%.*]] 723; NOT_CGSCC_NPM: loop.header: 724; NOT_CGSCC_NPM-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 0 725; NOT_CGSCC_NPM-NEXT: br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]] 726; NOT_CGSCC_NPM: loop.body: 727; NOT_CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[B]]) #[[ATTR5]] 728; NOT_CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[A]]) #[[ATTR5]] 729; NOT_CGSCC_NPM-NEXT: br label [[LOOP_HEADER]] 730; NOT_CGSCC_NPM: loop.exit: 731; NOT_CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[B]]) #[[ATTR5]] 732; NOT_CGSCC_NPM-NEXT: ret void 733; 734; IS__CGSCC_NPM: Function Attrs: nounwind 735; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f19 736; IS__CGSCC_NPM-SAME: (i8* [[A:%.*]], i8* nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR4]] { 737; IS__CGSCC_NPM-NEXT: br label [[LOOP_HEADER:%.*]] 738; IS__CGSCC_NPM: loop.header: 739; IS__CGSCC_NPM-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 0 740; IS__CGSCC_NPM-NEXT: br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]] 741; IS__CGSCC_NPM: loop.body: 742; IS__CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[B]]) #[[ATTR4]] 743; IS__CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[A]]) #[[ATTR4]] 744; IS__CGSCC_NPM-NEXT: br label [[LOOP_HEADER]] 745; IS__CGSCC_NPM: loop.exit: 746; IS__CGSCC_NPM-NEXT: tail call void @fun1(i8* nonnull [[B]]) #[[ATTR4]] 747; IS__CGSCC_NPM-NEXT: ret void 748; 749 br label %loop.header 750loop.header: 751 %cmp2 = icmp eq i8 %c, 0 752 br i1 %cmp2, label %loop.body, label %loop.exit 753loop.body: 754 tail call void @fun1(i8* nonnull %b) 755 tail call void @fun1(i8* nonnull %a) 756 br label %loop.header 757loop.exit: 758 tail call void @fun1(i8* nonnull %b) 759 ret void 760} 761 762; Test propagation of nonnull callsite args back to caller. 763 764declare void @use1(i8* %x) 765declare void @use2(i8* %x, i8* %y); 766declare void @use3(i8* %x, i8* %y, i8* %z); 767 768declare void @use1nonnull(i8* nonnull %x); 769declare void @use2nonnull(i8* nonnull %x, i8* nonnull %y); 770declare void @use3nonnull(i8* nonnull %x, i8* nonnull %y, i8* nonnull %z); 771 772declare i8 @use1safecall(i8* %x) readonly nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor 773 774; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute. 775 776define void @parent1(i8* %a, i8* %b, i8* %c) { 777; CHECK-LABEL: define {{[^@]+}}@parent1 778; CHECK-SAME: (i8* [[A:%.*]], i8* [[B:%.*]], i8* [[C:%.*]]) { 779; CHECK-NEXT: call void @use3(i8* [[C]], i8* [[A]], i8* [[B]]) 780; CHECK-NEXT: call void @use3nonnull(i8* nonnull [[B]], i8* nonnull [[C]], i8* nonnull [[A]]) 781; CHECK-NEXT: ret void 782; 783 call void @use3(i8* %c, i8* %a, i8* %b) 784 call void @use3nonnull(i8* %b, i8* %c, i8* %a) 785 ret void 786} 787 788; Extend non-null to parent for all arguments. 789 790define void @parent2(i8* %a, i8* %b, i8* %c) { 791; CHECK-LABEL: define {{[^@]+}}@parent2 792; CHECK-SAME: (i8* nonnull [[A:%.*]], i8* nonnull [[B:%.*]], i8* nonnull [[C:%.*]]) { 793; CHECK-NEXT: call void @use3nonnull(i8* nonnull [[B]], i8* nonnull [[C]], i8* nonnull [[A]]) 794; CHECK-NEXT: call void @use3(i8* nonnull [[C]], i8* nonnull [[A]], i8* nonnull [[B]]) 795; CHECK-NEXT: ret void 796; 797 798 call void @use3nonnull(i8* %b, i8* %c, i8* %a) 799 call void @use3(i8* %c, i8* %a, i8* %b) 800 ret void 801} 802 803; Extend non-null to parent for 1st argument. 804 805define void @parent3(i8* %a, i8* %b, i8* %c) { 806; CHECK-LABEL: define {{[^@]+}}@parent3 807; CHECK-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8* [[C:%.*]]) { 808; CHECK-NEXT: call void @use1nonnull(i8* nonnull [[A]]) 809; CHECK-NEXT: call void @use3(i8* [[C]], i8* [[B]], i8* nonnull [[A]]) 810; CHECK-NEXT: ret void 811; 812 813 814 call void @use1nonnull(i8* %a) 815 call void @use3(i8* %c, i8* %b, i8* %a) 816 ret void 817} 818 819; Extend non-null to parent for last 2 arguments. 820 821define void @parent4(i8* %a, i8* %b, i8* %c) { 822; CHECK-LABEL: define {{[^@]+}}@parent4 823; CHECK-SAME: (i8* [[A:%.*]], i8* nonnull [[B:%.*]], i8* nonnull [[C:%.*]]) { 824; CHECK-NEXT: call void @use2nonnull(i8* nonnull [[C]], i8* nonnull [[B]]) 825; CHECK-NEXT: call void @use2(i8* [[A]], i8* nonnull [[C]]) 826; CHECK-NEXT: call void @use1(i8* nonnull [[B]]) 827; CHECK-NEXT: ret void 828; 829 830 831 832 call void @use2nonnull(i8* %c, i8* %b) 833 call void @use2(i8* %a, i8* %c) 834 call void @use1(i8* %b) 835 ret void 836} 837 838; The callsite must execute in order for the attribute to transfer to the parent. 839; It appears benign to extend non-null to the parent in this case, but we can't do that 840; because it would incorrectly propagate the wrong information to its callers. 841 842define void @parent5(i8* %a, i1 %a_is_notnull) { 843; CHECK-LABEL: define {{[^@]+}}@parent5 844; CHECK-SAME: (i8* [[A:%.*]], i1 [[A_IS_NOTNULL:%.*]]) { 845; CHECK-NEXT: br i1 [[A_IS_NOTNULL]], label [[T:%.*]], label [[F:%.*]] 846; CHECK: t: 847; CHECK-NEXT: call void @use1nonnull(i8* nonnull [[A]]) 848; CHECK-NEXT: ret void 849; CHECK: f: 850; CHECK-NEXT: ret void 851; 852 853 br i1 %a_is_notnull, label %t, label %f 854t: 855 call void @use1nonnull(i8* %a) 856 ret void 857f: 858 ret void 859} 860 861; The callsite must execute in order for the attribute to transfer to the parent. 862; The volatile load can't trap, so we can guarantee that we'll get to the call. 863 864define i8 @parent6(i8* %a, i8* %b) { 865; CHECK-LABEL: define {{[^@]+}}@parent6 866; CHECK-SAME: (i8* nonnull [[A:%.*]], i8* nofree noundef [[B:%.*]]) { 867; CHECK-NEXT: [[C:%.*]] = load volatile i8, i8* [[B]], align 1 868; CHECK-NEXT: call void @use1nonnull(i8* nonnull [[A]]) 869; CHECK-NEXT: ret i8 [[C]] 870; 871 872 %c = load volatile i8, i8* %b 873 call void @use1nonnull(i8* %a) 874 ret i8 %c 875} 876 877; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent. 878 879define i8 @parent7(i8* %a) { 880; CHECK-LABEL: define {{[^@]+}}@parent7 881; CHECK-SAME: (i8* nonnull [[A:%.*]]) { 882; CHECK-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* nonnull readonly [[A]]) #[[ATTR15:[0-9]+]] 883; CHECK-NEXT: call void @use1nonnull(i8* nonnull [[A]]) 884; CHECK-NEXT: ret i8 [[RET]] 885; 886 887 888 %ret = call i8 @use1safecall(i8* %a) 889 call void @use1nonnull(i8* %a) 890 ret i8 %ret 891} 892 893; Make sure that an invoke works similarly to a call. 894 895declare i32 @esfp(...) 896 897define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){ 898; NOT_CGSCC_NPM: Function Attrs: nounwind 899; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@parent8 900; NOT_CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #[[ATTR5]] personality i8* bitcast (i32 (...)* @esfp to i8*) { 901; NOT_CGSCC_NPM-NEXT: entry: 902; NOT_CGSCC_NPM-NEXT: invoke void @use2nonnull(i8* nonnull [[A]], i8* nonnull [[B]]) 903; NOT_CGSCC_NPM-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] 904; NOT_CGSCC_NPM: cont: 905; NOT_CGSCC_NPM-NEXT: ret i1 false 906; NOT_CGSCC_NPM: exc: 907; NOT_CGSCC_NPM-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } 908; NOT_CGSCC_NPM-NEXT: filter [0 x i8*] zeroinitializer 909; NOT_CGSCC_NPM-NEXT: unreachable 910; 911; IS__CGSCC_NPM: Function Attrs: nounwind 912; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@parent8 913; IS__CGSCC_NPM-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #[[ATTR4]] personality i8* bitcast (i32 (...)* @esfp to i8*) { 914; IS__CGSCC_NPM-NEXT: entry: 915; IS__CGSCC_NPM-NEXT: invoke void @use2nonnull(i8* nonnull [[A]], i8* nonnull [[B]]) 916; IS__CGSCC_NPM-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] 917; IS__CGSCC_NPM: cont: 918; IS__CGSCC_NPM-NEXT: ret i1 false 919; IS__CGSCC_NPM: exc: 920; IS__CGSCC_NPM-NEXT: [[LP:%.*]] = landingpad { i8*, i32 } 921; IS__CGSCC_NPM-NEXT: filter [0 x i8*] zeroinitializer 922; IS__CGSCC_NPM-NEXT: unreachable 923; 924 925entry: 926 invoke void @use2nonnull(i8* %a, i8* %b) 927 to label %cont unwind label %exc 928 929cont: 930 %null_check = icmp eq i8* %b, null 931 ret i1 %null_check 932 933exc: 934 %lp = landingpad { i8*, i32 } 935 filter [0 x i8*] zeroinitializer 936 unreachable 937} 938 939define i32* @gep1(i32* %p) { 940; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 941; CHECK-LABEL: define {{[^@]+}}@gep1 942; CHECK-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] { 943; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 944; CHECK-NEXT: ret i32* [[Q]] 945; 946 %q = getelementptr inbounds i32, i32* %p, i32 1 947 ret i32* %q 948} 949 950define i32* @gep1_no_null_opt(i32* %p) #0 { 951; Should't be able to derive nonnull based on gep. 952; NOT_CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn 953; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@gep1_no_null_opt 954; NOT_CGSCC_NPM-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR9:[0-9]+]] { 955; NOT_CGSCC_NPM-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 956; NOT_CGSCC_NPM-NEXT: ret i32* [[Q]] 957; 958; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn 959; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@gep1_no_null_opt 960; IS__CGSCC_NPM-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR8:[0-9]+]] { 961; IS__CGSCC_NPM-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 962; IS__CGSCC_NPM-NEXT: ret i32* [[Q]] 963; 964 %q = getelementptr inbounds i32, i32* %p, i32 1 965 ret i32* %q 966} 967 968define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) { 969; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 970; CHECK-LABEL: define {{[^@]+}}@gep2 971; CHECK-SAME: (i32 addrspace(3)* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] { 972; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32 addrspace(3)* [[P]], i32 1 973; CHECK-NEXT: ret i32 addrspace(3)* [[Q]] 974; 975 %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1 976 ret i32 addrspace(3)* %q 977} 978 979; FIXME: We should propagate dereferenceable here but *not* nonnull 980define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) { 981; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 982; CHECK-LABEL: define {{[^@]+}}@as 983; CHECK-SAME: (i32 addrspace(3)* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] { 984; CHECK-NEXT: ret i32 addrspace(3)* [[P]] 985; 986 ret i32 addrspace(3)* %p 987} 988 989; CHECK-NOT: @g2() 990define internal i32* @g2() { 991; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 992; IS__CGSCC____-LABEL: define {{[^@]+}}@g2 993; IS__CGSCC____-SAME: () #[[ATTR1]] { 994; IS__CGSCC____-NEXT: ret i32* inttoptr (i64 4 to i32*) 995; 996 ret i32* inttoptr (i64 4 to i32*) 997} 998 999define i32* @g1() { 1000; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 1001; IS__TUNIT____-LABEL: define {{[^@]+}}@g1 1002; IS__TUNIT____-SAME: () #[[ATTR1]] { 1003; IS__TUNIT____-NEXT: ret i32* inttoptr (i64 4 to i32*) 1004; 1005; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn 1006; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@g1 1007; IS__CGSCC_OPM-SAME: () #[[ATTR3]] { 1008; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call noundef nonnull align 4 i32* @g2() #[[ATTR16:[0-9]+]] 1009; IS__CGSCC_OPM-NEXT: ret i32* [[C]] 1010; 1011; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn 1012; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@g1 1013; IS__CGSCC_NPM-SAME: () #[[ATTR9:[0-9]+]] { 1014; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call noundef nonnull align 4 i32* @g2() #[[ATTR16:[0-9]+]] 1015; IS__CGSCC_NPM-NEXT: ret i32* [[C]] 1016; 1017 %c = call i32* @g2() 1018 ret i32* %c 1019} 1020 1021declare void @use_i32_ptr(i32* readnone nocapture) nounwind 1022define internal void @called_by_weak(i32* %a) { 1023; NOT_CGSCC_NPM: Function Attrs: nounwind 1024; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@called_by_weak 1025; NOT_CGSCC_NPM-SAME: (i32* noalias nocapture nonnull readnone [[A:%.*]]) #[[ATTR5]] { 1026; NOT_CGSCC_NPM-NEXT: call void @use_i32_ptr(i32* noalias nocapture nonnull readnone [[A]]) #[[ATTR5]] 1027; NOT_CGSCC_NPM-NEXT: ret void 1028; 1029; IS__CGSCC_NPM: Function Attrs: nounwind 1030; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@called_by_weak 1031; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nonnull readnone [[A:%.*]]) #[[ATTR4]] { 1032; IS__CGSCC_NPM-NEXT: call void @use_i32_ptr(i32* noalias nocapture nonnull readnone [[A]]) #[[ATTR4]] 1033; IS__CGSCC_NPM-NEXT: ret void 1034; 1035 call void @use_i32_ptr(i32* %a) 1036 ret void 1037} 1038 1039; Check we do not annotate the function interface of this weak function. 1040define weak_odr void @weak_caller(i32* nonnull %a) { 1041; 1042; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@weak_caller 1043; NOT_CGSCC_NPM-SAME: (i32* nonnull [[A:%.*]]) { 1044; NOT_CGSCC_NPM-NEXT: call void @called_by_weak(i32* noalias nocapture nonnull readnone [[A]]) #[[ATTR5]] 1045; NOT_CGSCC_NPM-NEXT: ret void 1046; 1047; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@weak_caller 1048; IS__CGSCC_NPM-SAME: (i32* nonnull [[A:%.*]]) { 1049; IS__CGSCC_NPM-NEXT: call void @called_by_weak(i32* noalias nocapture nonnull readnone [[A]]) #[[ATTR4]] 1050; IS__CGSCC_NPM-NEXT: ret void 1051; 1052 call void @called_by_weak(i32* %a) 1053 ret void 1054} 1055 1056; Expect nonnull 1057define internal void @control(i32* dereferenceable(4) %a) { 1058; NOT_CGSCC_NPM: Function Attrs: nounwind 1059; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@control 1060; NOT_CGSCC_NPM-SAME: (i32* noalias nocapture noundef nonnull readnone align 16 dereferenceable(8) [[A:%.*]]) #[[ATTR5]] { 1061; NOT_CGSCC_NPM-NEXT: call void @use_i32_ptr(i32* noalias nocapture noundef nonnull readnone align 16 dereferenceable(8) [[A]]) #[[ATTR5]] 1062; NOT_CGSCC_NPM-NEXT: ret void 1063; 1064; IS__CGSCC_NPM: Function Attrs: nounwind 1065; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@control 1066; IS__CGSCC_NPM-SAME: (i32* noalias nocapture noundef nonnull readnone align 16 dereferenceable(8) [[A:%.*]]) #[[ATTR4]] { 1067; IS__CGSCC_NPM-NEXT: call void @use_i32_ptr(i32* noalias nocapture noundef nonnull readnone align 16 dereferenceable(8) [[A]]) #[[ATTR4]] 1068; IS__CGSCC_NPM-NEXT: ret void 1069; 1070 call void @use_i32_ptr(i32* %a) 1071 ret void 1072} 1073; Avoid nonnull as we do not touch naked functions 1074define internal void @naked(i32* dereferenceable(4) %a) naked { 1075; CHECK: Function Attrs: naked 1076; CHECK-LABEL: define {{[^@]+}}@naked 1077; CHECK-SAME: (i32* dereferenceable(4) [[A:%.*]]) #[[ATTR10:[0-9]+]] { 1078; CHECK-NEXT: call void @use_i32_ptr(i32* [[A]]) 1079; CHECK-NEXT: ret void 1080; 1081 call void @use_i32_ptr(i32* %a) 1082 ret void 1083} 1084; Avoid nonnull as we do not touch optnone 1085define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline { 1086; 1087; CHECK: Function Attrs: noinline optnone 1088; CHECK-LABEL: define {{[^@]+}}@optnone 1089; CHECK-SAME: (i32* dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] { 1090; CHECK-NEXT: call void @use_i32_ptr(i32* [[A]]) 1091; CHECK-NEXT: ret void 1092; 1093 call void @use_i32_ptr(i32* %a) 1094 ret void 1095} 1096define void @make_live(i32* nonnull dereferenceable(8) %a) { 1097; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@make_live 1098; NOT_CGSCC_NPM-SAME: (i32* noundef nonnull align 16 dereferenceable(8) [[A:%.*]]) { 1099; NOT_CGSCC_NPM-NEXT: call void @naked(i32* noundef nonnull align 16 dereferenceable(8) [[A]]) 1100; NOT_CGSCC_NPM-NEXT: call void @control(i32* noalias nocapture noundef nonnull readnone align 16 dereferenceable(8) [[A]]) #[[ATTR5]] 1101; NOT_CGSCC_NPM-NEXT: call void @optnone(i32* noundef nonnull align 16 dereferenceable(8) [[A]]) 1102; NOT_CGSCC_NPM-NEXT: ret void 1103; 1104; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@make_live 1105; IS__CGSCC_NPM-SAME: (i32* noundef nonnull align 16 dereferenceable(8) [[A:%.*]]) { 1106; IS__CGSCC_NPM-NEXT: call void @naked(i32* noundef nonnull align 16 dereferenceable(8) [[A]]) 1107; IS__CGSCC_NPM-NEXT: call void @control(i32* noalias nocapture noundef nonnull readnone align 16 dereferenceable(8) [[A]]) #[[ATTR4]] 1108; IS__CGSCC_NPM-NEXT: call void @optnone(i32* noundef nonnull align 16 dereferenceable(8) [[A]]) 1109; IS__CGSCC_NPM-NEXT: ret void 1110; 1111 call void @naked(i32* nonnull dereferenceable(8) align 16 %a) 1112 call void @control(i32* nonnull dereferenceable(8) align 16 %a) 1113 call void @optnone(i32* nonnull dereferenceable(8) align 16 %a) 1114 ret void 1115} 1116 1117 1118;int f(int *u, int n){ 1119; for(int i = 0;i<n;i++){ 1120; h(u); 1121; } 1122; return g(nonnull u); 1123;} 1124declare void @h(i32*) willreturn nounwind 1125declare i32 @g(i32*) willreturn nounwind 1126define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) { 1127; 1128; IS________OPM: Function Attrs: nounwind 1129; IS________OPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 1130; IS________OPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) #[[ATTR5]] { 1131; IS________OPM-NEXT: en: 1132; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1133; IS________OPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1134; IS________OPM: ex: 1135; IS________OPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR5]] 1136; IS________OPM-NEXT: ret i32 [[TMP5]] 1137; IS________OPM: hd: 1138; IS________OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 1139; IS________OPM-NEXT: tail call void @h(i32* [[A]]) #[[ATTR5]] 1140; IS________OPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1141; IS________OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1142; IS________OPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1143; 1144; IS__TUNIT_NPM: Function Attrs: nounwind willreturn 1145; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 1146; IS__TUNIT_NPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { 1147; IS__TUNIT_NPM-NEXT: en: 1148; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1149; IS__TUNIT_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1150; IS__TUNIT_NPM: ex: 1151; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR7]] 1152; IS__TUNIT_NPM-NEXT: ret i32 [[TMP5]] 1153; IS__TUNIT_NPM: hd: 1154; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 1155; IS__TUNIT_NPM-NEXT: tail call void @h(i32* [[A]]) #[[ATTR7]] 1156; IS__TUNIT_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1157; IS__TUNIT_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1158; IS__TUNIT_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1159; 1160; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 1161; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 1162; IS__CGSCC_NPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] { 1163; IS__CGSCC_NPM-NEXT: en: 1164; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1165; IS__CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1166; IS__CGSCC_NPM: ex: 1167; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR6]] 1168; IS__CGSCC_NPM-NEXT: ret i32 [[TMP5]] 1169; IS__CGSCC_NPM: hd: 1170; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 1171; IS__CGSCC_NPM-NEXT: tail call void @h(i32* [[A]]) #[[ATTR6]] 1172; IS__CGSCC_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1173; IS__CGSCC_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1174; IS__CGSCC_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1175; 1176en: 1177 %tmp3 = icmp eq i32 %b, 0 1178 br i1 %tmp3, label %ex, label %hd 1179 1180ex: 1181 %tmp5 = tail call i32 @g(i32* nonnull %a) 1182 ret i32 %tmp5 1183 1184hd: 1185 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ] 1186 tail call void @h(i32* %a) 1187 %tmp8 = add nuw i32 %tmp7, 1 1188 %tmp9 = icmp eq i32 %tmp8, %b 1189 br i1 %tmp9, label %ex, label %hd 1190} 1191 1192define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) { 1193; 1194; IS________OPM: Function Attrs: nounwind 1195; IS________OPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b 1196; IS________OPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) #[[ATTR5]] { 1197; IS________OPM-NEXT: en: 1198; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1199; IS________OPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1200; IS________OPM: ex: 1201; IS________OPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR5]] 1202; IS________OPM-NEXT: ret i32 [[TMP5]] 1203; IS________OPM: hd: 1204; IS________OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 1205; IS________OPM-NEXT: tail call void @h(i32* [[A]]) #[[ATTR5]] 1206; IS________OPM-NEXT: br label [[HD2]] 1207; IS________OPM: hd2: 1208; IS________OPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1209; IS________OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1210; IS________OPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1211; 1212; IS__TUNIT_NPM: Function Attrs: nounwind willreturn 1213; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b 1214; IS__TUNIT_NPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { 1215; IS__TUNIT_NPM-NEXT: en: 1216; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1217; IS__TUNIT_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1218; IS__TUNIT_NPM: ex: 1219; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR7]] 1220; IS__TUNIT_NPM-NEXT: ret i32 [[TMP5]] 1221; IS__TUNIT_NPM: hd: 1222; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 1223; IS__TUNIT_NPM-NEXT: tail call void @h(i32* [[A]]) #[[ATTR7]] 1224; IS__TUNIT_NPM-NEXT: br label [[HD2]] 1225; IS__TUNIT_NPM: hd2: 1226; IS__TUNIT_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1227; IS__TUNIT_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1228; IS__TUNIT_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1229; 1230; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 1231; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b 1232; IS__CGSCC_NPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] { 1233; IS__CGSCC_NPM-NEXT: en: 1234; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1235; IS__CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1236; IS__CGSCC_NPM: ex: 1237; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR6]] 1238; IS__CGSCC_NPM-NEXT: ret i32 [[TMP5]] 1239; IS__CGSCC_NPM: hd: 1240; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 1241; IS__CGSCC_NPM-NEXT: tail call void @h(i32* [[A]]) #[[ATTR6]] 1242; IS__CGSCC_NPM-NEXT: br label [[HD2]] 1243; IS__CGSCC_NPM: hd2: 1244; IS__CGSCC_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1245; IS__CGSCC_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1246; IS__CGSCC_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1247; 1248en: 1249 %tmp3 = icmp eq i32 %b, 0 1250 br i1 %tmp3, label %ex, label %hd 1251 1252ex: 1253 %tmp5 = tail call i32 @g(i32* nonnull %a) 1254 ret i32 %tmp5 1255 1256hd: 1257 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ] 1258 tail call void @h(i32* %a) 1259 br label %hd2 1260 1261hd2: 1262 %tmp8 = add nuw i32 %tmp7, 1 1263 %tmp9 = icmp eq i32 %tmp8, %b 1264 br i1 %tmp9, label %ex, label %hd 1265} 1266 1267define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind { 1268; 1269; NOT_CGSCC_NPM: Function Attrs: nounwind willreturn 1270; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 1271; NOT_CGSCC_NPM-SAME: (i32* nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { 1272; NOT_CGSCC_NPM-NEXT: en: 1273; NOT_CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1274; NOT_CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1275; NOT_CGSCC_NPM: ex: 1276; NOT_CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR5]] 1277; NOT_CGSCC_NPM-NEXT: ret i32 [[TMP5]] 1278; NOT_CGSCC_NPM: hd: 1279; NOT_CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 1280; NOT_CGSCC_NPM-NEXT: tail call void @h(i32* nonnull [[A]]) #[[ATTR5]] 1281; NOT_CGSCC_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1282; NOT_CGSCC_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1283; NOT_CGSCC_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1284; 1285; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 1286; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 1287; IS__CGSCC_NPM-SAME: (i32* nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] { 1288; IS__CGSCC_NPM-NEXT: en: 1289; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1290; IS__CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1291; IS__CGSCC_NPM: ex: 1292; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR4]] 1293; IS__CGSCC_NPM-NEXT: ret i32 [[TMP5]] 1294; IS__CGSCC_NPM: hd: 1295; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] 1296; IS__CGSCC_NPM-NEXT: tail call void @h(i32* nonnull [[A]]) #[[ATTR4]] 1297; IS__CGSCC_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1298; IS__CGSCC_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1299; IS__CGSCC_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1300; 1301en: 1302 %tmp3 = icmp eq i32 %b, 0 1303 br i1 %tmp3, label %ex, label %hd 1304 1305ex: 1306 %tmp5 = tail call i32 @g(i32* nonnull %a) 1307 ret i32 %tmp5 1308 1309hd: 1310 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ] 1311 tail call void @h(i32* %a) 1312 %tmp8 = add nuw i32 %tmp7, 1 1313 %tmp9 = icmp eq i32 %tmp8, %b 1314 br i1 %tmp9, label %ex, label %hd 1315} 1316 1317define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind { 1318; 1319; NOT_CGSCC_NPM: Function Attrs: nounwind willreturn 1320; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b 1321; NOT_CGSCC_NPM-SAME: (i32* nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { 1322; NOT_CGSCC_NPM-NEXT: en: 1323; NOT_CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1324; NOT_CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1325; NOT_CGSCC_NPM: ex: 1326; NOT_CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR5]] 1327; NOT_CGSCC_NPM-NEXT: ret i32 [[TMP5]] 1328; NOT_CGSCC_NPM: hd: 1329; NOT_CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 1330; NOT_CGSCC_NPM-NEXT: tail call void @h(i32* nonnull [[A]]) #[[ATTR5]] 1331; NOT_CGSCC_NPM-NEXT: br label [[HD2]] 1332; NOT_CGSCC_NPM: hd2: 1333; NOT_CGSCC_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1334; NOT_CGSCC_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1335; NOT_CGSCC_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1336; 1337; IS__CGSCC_NPM: Function Attrs: nounwind willreturn 1338; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b 1339; IS__CGSCC_NPM-SAME: (i32* nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] { 1340; IS__CGSCC_NPM-NEXT: en: 1341; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 1342; IS__CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] 1343; IS__CGSCC_NPM: ex: 1344; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) #[[ATTR4]] 1345; IS__CGSCC_NPM-NEXT: ret i32 [[TMP5]] 1346; IS__CGSCC_NPM: hd: 1347; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] 1348; IS__CGSCC_NPM-NEXT: tail call void @h(i32* nonnull [[A]]) #[[ATTR4]] 1349; IS__CGSCC_NPM-NEXT: br label [[HD2]] 1350; IS__CGSCC_NPM: hd2: 1351; IS__CGSCC_NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 1352; IS__CGSCC_NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] 1353; IS__CGSCC_NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] 1354; 1355en: 1356 %tmp3 = icmp eq i32 %b, 0 1357 br i1 %tmp3, label %ex, label %hd 1358 1359ex: 1360 %tmp5 = tail call i32 @g(i32* nonnull %a) 1361 ret i32 %tmp5 1362 1363hd: 1364 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ] 1365 tail call void @h(i32* %a) 1366 br label %hd2 1367 1368hd2: 1369 %tmp8 = add nuw i32 %tmp7, 1 1370 %tmp9 = icmp eq i32 %tmp8, %b 1371 br i1 %tmp9, label %ex, label %hd 1372} 1373 1374; Original from PR43833 1375declare void @sink(i32*) 1376 1377define void @PR43833(i32* %0, i32 %1) { 1378; IS________OPM-LABEL: define {{[^@]+}}@PR43833 1379; IS________OPM-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { 1380; IS________OPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP1]], 1 1381; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 1382; IS________OPM: 4: 1383; IS________OPM-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 1384; IS________OPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP5]] 1385; IS________OPM-NEXT: br label [[TMP8:%.*]] 1386; IS________OPM: 7: 1387; IS________OPM-NEXT: ret void 1388; IS________OPM: 8: 1389; IS________OPM-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 1390; IS________OPM-NEXT: tail call void @sink(i32* [[TMP6]]) 1391; IS________OPM-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 1392; IS________OPM-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 1393; IS________OPM-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 1394; 1395; IS________NPM-LABEL: define {{[^@]+}}@PR43833 1396; IS________NPM-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { 1397; IS________NPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP1]], 1 1398; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 1399; IS________NPM: 4: 1400; IS________NPM-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 1401; IS________NPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP5]] 1402; IS________NPM-NEXT: br label [[TMP8:%.*]] 1403; IS________NPM: 7: 1404; IS________NPM-NEXT: ret void 1405; IS________NPM: 8: 1406; IS________NPM-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 1407; IS________NPM-NEXT: tail call void @sink(i32* nonnull [[TMP6]]) 1408; IS________NPM-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 1409; IS________NPM-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 1410; IS________NPM-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 1411; 1412 %3 = icmp sgt i32 %1, 1 1413 br i1 %3, label %4, label %7 1414 14154: ; preds = %2 1416 %5 = zext i32 %1 to i64 1417 %6 = getelementptr inbounds i32, i32* %0, i64 %5 1418 br label %8 1419 14207: ; preds = %8, %2 1421 ret void 1422 14238: ; preds = %8, %4 1424 %9 = phi i32 [ 1, %4 ], [ %10, %8 ] 1425 tail call void @sink(i32* %6) 1426 %10 = add nuw nsw i32 %9, 1 1427 %11 = icmp eq i32 %10, %1 1428 br i1 %11, label %7, label %8 1429} 1430 1431; Adjusted from PR43833 1432define void @PR43833_simple(i32* %0, i32 %1) { 1433; IS________OPM-LABEL: define {{[^@]+}}@PR43833_simple 1434; IS________OPM-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { 1435; IS________OPM-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0 1436; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 1437; IS________OPM: 4: 1438; IS________OPM-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 1439; IS________OPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP5]] 1440; IS________OPM-NEXT: br label [[TMP8:%.*]] 1441; IS________OPM: 7: 1442; IS________OPM-NEXT: ret void 1443; IS________OPM: 8: 1444; IS________OPM-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 1445; IS________OPM-NEXT: tail call void @sink(i32* [[TMP6]]) 1446; IS________OPM-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 1447; IS________OPM-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 1448; IS________OPM-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 1449; 1450; IS________NPM-LABEL: define {{[^@]+}}@PR43833_simple 1451; IS________NPM-SAME: (i32* [[TMP0:%.*]], i32 [[TMP1:%.*]]) { 1452; IS________NPM-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0 1453; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]] 1454; IS________NPM: 4: 1455; IS________NPM-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i64 1456; IS________NPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP5]] 1457; IS________NPM-NEXT: br label [[TMP8:%.*]] 1458; IS________NPM: 7: 1459; IS________NPM-NEXT: ret void 1460; IS________NPM: 8: 1461; IS________NPM-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ] 1462; IS________NPM-NEXT: tail call void @sink(i32* nonnull [[TMP6]]) 1463; IS________NPM-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 1 1464; IS________NPM-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]] 1465; IS________NPM-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]] 1466; 1467 %3 = icmp ne i32 %1, 0 1468 br i1 %3, label %4, label %7 1469 14704: ; preds = %2 1471 %5 = zext i32 %1 to i64 1472 %6 = getelementptr inbounds i32, i32* %0, i64 %5 1473 br label %8 1474 14757: ; preds = %8, %2 1476 ret void 1477 14788: ; preds = %8, %4 1479 %9 = phi i32 [ 1, %4 ], [ %10, %8 ] 1480 tail call void @sink(i32* %6) 1481 %10 = add nuw nsw i32 %9, 1 1482 %11 = icmp eq i32 %10, %1 1483 br i1 %11, label %7, label %8 1484} 1485 1486declare i8* @strrchr(i8* %0, i32 %1) nofree nounwind readonly willreturn 1487 1488; We should not mark the return of @strrchr as `nonnull`, it may well be NULL! 1489define i8* @mybasename(i8* nofree readonly %str) { 1490; CHECK: Function Attrs: nofree nounwind readonly willreturn 1491; CHECK-LABEL: define {{[^@]+}}@mybasename 1492; CHECK-SAME: (i8* nofree readonly [[STR:%.*]]) #[[ATTR12:[0-9]+]] { 1493; CHECK-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) #[[ATTR15]] 1494; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[CALL]], null 1495; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 1 1496; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i8* [[ADD_PTR]], i8* [[STR]] 1497; CHECK-NEXT: ret i8* [[COND]] 1498; 1499 %call = call i8* @strrchr(i8* %str, i32 47) 1500 %tobool = icmp ne i8* %call, null 1501 %add.ptr = getelementptr inbounds i8, i8* %call, i64 1 1502 %cond = select i1 %tobool, i8* %add.ptr, i8* %str 1503 ret i8* %cond 1504} 1505 1506define void @nonnull_assume_pos(i8* %arg) { 1507; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_pos 1508; ATTRIBUTOR-SAME: (i8* nocapture nofree nonnull readnone [[ARG:%.*]]) 1509; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #11 [ "nonnull"(i8* [[ARG]]) ] 1510; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[ARG]]) 1511; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i8* @unknown() 1512; ATTRIBUTOR-NEXT: ret void 1513; 1514; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_assume_pos 1515; NOT_CGSCC_NPM-SAME: (i8* nocapture nofree nonnull readnone [[ARG:%.*]]) { 1516; NOT_CGSCC_NPM-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR13]] [ "nonnull"(i8* [[ARG]]) ] 1517; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR5]] 1518; NOT_CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i8* @unknown() 1519; NOT_CGSCC_NPM-NEXT: ret void 1520; 1521; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_assume_pos 1522; IS__CGSCC_NPM-SAME: (i8* nocapture nofree nonnull readnone [[ARG:%.*]]) { 1523; IS__CGSCC_NPM-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR13]] [ "nonnull"(i8* [[ARG]]) ] 1524; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR4]] 1525; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i8* @unknown() 1526; IS__CGSCC_NPM-NEXT: ret void 1527; 1528 call void @llvm.assume(i1 true) ["nonnull"(i8* %arg)] 1529 call void @use_i8_ptr(i8* %arg) 1530 call i8* @unknown() 1531 ret void 1532} 1533define void @nonnull_assume_neg(i8* %arg) { 1534; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_neg 1535; ATTRIBUTOR-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) 1536; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i8* @unknown() 1537; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[ARG]]) 1538; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[ARG]]) ] 1539; ATTRIBUTOR-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[ARG]]) 1540; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = call i8* @unknown() 1541; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree nonnull readnone [[ARG]]) 1542; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[ARG]]) ] 1543; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree nonnull readnone [[ARG]]) 1544; ATTRIBUTOR-NEXT: ret void 1545; 1546; 1547; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_assume_neg 1548; NOT_CGSCC_NPM-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) { 1549; NOT_CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i8* @unknown() 1550; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[ARG]]) #[[ATTR5]] 1551; NOT_CGSCC_NPM-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(i8* [[ARG]]) ] 1552; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR5]] 1553; NOT_CGSCC_NPM-NEXT: [[TMP2:%.*]] = call i8* @unknown() 1554; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR5]] 1555; NOT_CGSCC_NPM-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(i8* [[ARG]]) ] 1556; NOT_CGSCC_NPM-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR5]] 1557; NOT_CGSCC_NPM-NEXT: ret void 1558; 1559; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@nonnull_assume_neg 1560; IS__CGSCC_NPM-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) { 1561; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i8* @unknown() 1562; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[ARG]]) #[[ATTR4]] 1563; IS__CGSCC_NPM-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(i8* [[ARG]]) ] 1564; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR4]] 1565; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = call i8* @unknown() 1566; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR4]] 1567; IS__CGSCC_NPM-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(i8* [[ARG]]) ] 1568; IS__CGSCC_NPM-NEXT: call void @use_i8_ptr_ret(i8* noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR4]] 1569; IS__CGSCC_NPM-NEXT: ret void 1570; 1571 call i8* @unknown() 1572 call void @use_i8_ptr(i8* %arg) 1573 call void @llvm.assume(i1 true) ["nonnull"(i8* %arg)] 1574 call void @use_i8_ptr(i8* %arg) 1575 call i8* @unknown() 1576 call void @use_i8_ptr_ret(i8* %arg) 1577 call void @llvm.assume(i1 true) ["nonnull"(i8* %arg)] 1578 call void @use_i8_ptr_ret(i8* %arg) 1579 ret void 1580} 1581declare void @use_i8_ptr(i8* nofree nocapture readnone) nounwind 1582declare void @use_i8_ptr_ret(i8* nofree nocapture readnone) nounwind willreturn 1583 1584define i8* @nonnull_function_ptr_1() { 1585; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 1586; CHECK-LABEL: define {{[^@]+}}@nonnull_function_ptr_1 1587; CHECK-SAME: () #[[ATTR1]] { 1588; CHECK-NEXT: ret i8* bitcast (i8* ()* @nonnull_function_ptr_1 to i8*) 1589; 1590 %bc = bitcast i8*()* @nonnull_function_ptr_1 to i8* 1591 ret i8* %bc 1592} 1593 1594declare i8* @function_decl() 1595define i8* @nonnull_function_ptr_2() { 1596; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 1597; CHECK-LABEL: define {{[^@]+}}@nonnull_function_ptr_2 1598; CHECK-SAME: () #[[ATTR1]] { 1599; CHECK-NEXT: ret i8* bitcast (i8* ()* @function_decl to i8*) 1600; 1601 %bc = bitcast i8*()* @function_decl to i8* 1602 ret i8* %bc 1603} 1604 1605; FIXME: nonnull should not be propagated to the caller's p unless there is noundef 1606define void @nonnull_caller(i8* %p) { 1607; CHECK-LABEL: define {{[^@]+}}@nonnull_caller 1608; CHECK-SAME: (i8* nonnull [[P:%.*]]) { 1609; CHECK-NEXT: call void @nonnull_callee(i8* nonnull [[P]]) 1610; CHECK-NEXT: ret void 1611; 1612 call void @nonnull_callee(i8* %p) 1613 ret void 1614} 1615 1616declare void @nonnull_callee(i8* nonnull %p) 1617 1618attributes #0 = { null_pointer_is_valid } 1619attributes #1 = { nounwind willreturn} 1620;. 1621; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { inaccessiblememonly nocallback nofree nosync nounwind willreturn } 1622; IS__TUNIT____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } 1623; IS__TUNIT____: attributes #[[ATTR2]] = { inaccessiblememonly nofree norecurse nosync nounwind willreturn } 1624; IS__TUNIT____: attributes #[[ATTR3]] = { nofree nosync nounwind readnone willreturn } 1625; IS__TUNIT____: attributes #[[ATTR4]] = { noreturn } 1626; IS__TUNIT____: attributes #[[ATTR5]] = { nounwind } 1627; IS__TUNIT____: attributes #[[ATTR6]] = { argmemonly nofree nosync nounwind readonly } 1628; IS__TUNIT____: attributes #[[ATTR7]] = { nounwind willreturn } 1629; IS__TUNIT____: attributes #[[ATTR8:[0-9]+]] = { nounwind readonly willreturn } 1630; IS__TUNIT____: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } 1631; IS__TUNIT____: attributes #[[ATTR10]] = { naked } 1632; IS__TUNIT____: attributes #[[ATTR11]] = { noinline optnone } 1633; IS__TUNIT____: attributes #[[ATTR12]] = { nofree nounwind readonly willreturn } 1634; IS__TUNIT____: attributes #[[ATTR13]] = { willreturn } 1635; IS__TUNIT____: attributes #[[ATTR14]] = { nofree nosync nounwind readonly } 1636; IS__TUNIT____: attributes #[[ATTR15]] = { readonly willreturn } 1637;. 1638; IS__CGSCC_OPM: attributes #[[ATTR0:[0-9]+]] = { inaccessiblememonly nocallback nofree nosync nounwind willreturn } 1639; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } 1640; IS__CGSCC_OPM: attributes #[[ATTR2]] = { inaccessiblememonly nofree norecurse nosync nounwind willreturn } 1641; IS__CGSCC_OPM: attributes #[[ATTR3]] = { nofree nosync nounwind readnone willreturn } 1642; IS__CGSCC_OPM: attributes #[[ATTR4]] = { noreturn } 1643; IS__CGSCC_OPM: attributes #[[ATTR5]] = { nounwind } 1644; IS__CGSCC_OPM: attributes #[[ATTR6]] = { argmemonly nofree nosync nounwind readonly } 1645; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nounwind willreturn } 1646; IS__CGSCC_OPM: attributes #[[ATTR8:[0-9]+]] = { nounwind readonly willreturn } 1647; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } 1648; IS__CGSCC_OPM: attributes #[[ATTR10]] = { naked } 1649; IS__CGSCC_OPM: attributes #[[ATTR11]] = { noinline optnone } 1650; IS__CGSCC_OPM: attributes #[[ATTR12]] = { nofree nounwind readonly willreturn } 1651; IS__CGSCC_OPM: attributes #[[ATTR13]] = { willreturn } 1652; IS__CGSCC_OPM: attributes #[[ATTR14]] = { nofree nosync nounwind readonly } 1653; IS__CGSCC_OPM: attributes #[[ATTR15]] = { readonly willreturn } 1654; IS__CGSCC_OPM: attributes #[[ATTR16]] = { readnone willreturn } 1655;. 1656; IS__CGSCC_NPM: attributes #[[ATTR0:[0-9]+]] = { inaccessiblememonly nocallback nofree nosync nounwind willreturn } 1657; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } 1658; IS__CGSCC_NPM: attributes #[[ATTR2]] = { inaccessiblememonly nofree norecurse nosync nounwind willreturn } 1659; IS__CGSCC_NPM: attributes #[[ATTR3]] = { noreturn } 1660; IS__CGSCC_NPM: attributes #[[ATTR4]] = { nounwind } 1661; IS__CGSCC_NPM: attributes #[[ATTR5]] = { argmemonly nofree nosync nounwind readonly } 1662; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nounwind willreturn } 1663; IS__CGSCC_NPM: attributes #[[ATTR7:[0-9]+]] = { nounwind readonly willreturn } 1664; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn } 1665; IS__CGSCC_NPM: attributes #[[ATTR9]] = { nofree nosync nounwind readnone willreturn } 1666; IS__CGSCC_NPM: attributes #[[ATTR10]] = { naked } 1667; IS__CGSCC_NPM: attributes #[[ATTR11]] = { noinline optnone } 1668; IS__CGSCC_NPM: attributes #[[ATTR12]] = { nofree nounwind readonly willreturn } 1669; IS__CGSCC_NPM: attributes #[[ATTR13]] = { willreturn } 1670; IS__CGSCC_NPM: attributes #[[ATTR14]] = { nofree nosync nounwind readonly } 1671; IS__CGSCC_NPM: attributes #[[ATTR15]] = { readonly willreturn } 1672; IS__CGSCC_NPM: attributes #[[ATTR16]] = { readnone willreturn } 1673;. 1674