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