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