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