1709 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC4 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 814;.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 %ret22}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 {{[^@]+}}@test228; 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 %p32}33 34define ptr @test2A(i1 %c, ptr %ret) {35; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)36; TUNIT-LABEL: define {{[^@]+}}@test2A37; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2:[0-9]+]] {38; TUNIT-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]]39; TUNIT: A:40; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15:[0-9]+]] [ "nonnull"(ptr [[RET]]) ]41; TUNIT-NEXT: ret ptr [[RET]]42; TUNIT: B:43; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "nonnull"(ptr [[RET]]) ]44; TUNIT-NEXT: ret ptr [[RET]]45;46; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)47; CGSCC-LABEL: define {{[^@]+}}@test2A48; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2:[0-9]+]] {49; CGSCC-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]]50; CGSCC: A:51; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16:[0-9]+]] [ "nonnull"(ptr [[RET]]) ]52; CGSCC-NEXT: ret ptr [[RET]]53; CGSCC: B:54; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[RET]]) ]55; CGSCC-NEXT: ret ptr [[RET]]56;57 br i1 %c, label %A, label %B58A:59 call void @llvm.assume(i1 true) [ "nonnull"(ptr %ret) ]60 ret ptr %ret61B:62 call void @llvm.assume(i1 true) [ "nonnull"(ptr %ret) ]63 ret ptr %ret64}65 66define ptr @test2B(i1 %c, ptr %ret) {67; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)68; TUNIT-LABEL: define {{[^@]+}}@test2B69; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2]] {70; TUNIT-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]]71; TUNIT: A:72; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "dereferenceable"(ptr [[RET]], i32 4) ]73; TUNIT-NEXT: ret ptr [[RET]]74; TUNIT: B:75; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "dereferenceable"(ptr [[RET]], i32 4) ]76; TUNIT-NEXT: ret ptr [[RET]]77;78; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)79; CGSCC-LABEL: define {{[^@]+}}@test2B80; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2]] {81; CGSCC-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]]82; CGSCC: A:83; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "dereferenceable"(ptr [[RET]], i32 4) ]84; CGSCC-NEXT: ret ptr [[RET]]85; CGSCC: B:86; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "dereferenceable"(ptr [[RET]], i32 4) ]87; CGSCC-NEXT: ret ptr [[RET]]88;89 br i1 %c, label %A, label %B90A:91 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ret, i32 4) ]92 ret ptr %ret93B:94 call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %ret, i32 4) ]95 ret ptr %ret96}97 98; Given an SCC where one of the functions can not be marked nonnull,99; can we still mark the other one which is trivially nonnull100define ptr @scc_binder(i1 %c) {101; CHECK-LABEL: define {{[^@]+}}@scc_binder102; CHECK-SAME: (i1 noundef [[C:%.*]]) {103; CHECK-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]104; CHECK: rec:105; CHECK-NEXT: [[TMP1:%.*]] = call ptr @test3(i1 noundef [[C]])106; CHECK-NEXT: br label [[END]]107; CHECK: end:108; CHECK-NEXT: ret ptr null109;110 br i1 %c, label %rec, label %end111rec:112 call ptr @test3(i1 %c)113 br label %end114end:115 ret ptr null116}117 118define ptr @test3(i1 %c) {119; CHECK-LABEL: define {{[^@]+}}@test3120; CHECK-SAME: (i1 [[C:%.*]]) {121; CHECK-NEXT: [[TMP1:%.*]] = call ptr @scc_binder(i1 noundef [[C]])122; CHECK-NEXT: [[RET:%.*]] = call nonnull ptr @ret_nonnull()123; CHECK-NEXT: ret ptr [[RET]]124;125 call ptr @scc_binder(i1 %c)126 %ret = call ptr @ret_nonnull()127 ret ptr %ret128}129 130; Given a mutual recursive set of functions, we can mark them131; nonnull if neither can ever return null. (In this case, they132; just never return period.)133define ptr @test4_helper() {134; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)135; TUNIT-LABEL: define {{[^@]+}}@test4_helper136; TUNIT-SAME: () #[[ATTR3:[0-9]+]] {137; TUNIT-NEXT: ret ptr undef138;139; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)140; CGSCC-LABEL: define {{[^@]+}}@test4_helper141; CGSCC-SAME: () #[[ATTR1]] {142; CGSCC-NEXT: ret ptr undef143;144 %ret = call ptr @test4()145 ret ptr %ret146}147 148define ptr @test4() {149; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)150; TUNIT-LABEL: define {{[^@]+}}@test4151; TUNIT-SAME: () #[[ATTR3]] {152; TUNIT-NEXT: ret ptr undef153;154; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)155; CGSCC-LABEL: define {{[^@]+}}@test4156; CGSCC-SAME: () #[[ATTR1]] {157; CGSCC-NEXT: ret ptr undef158;159 %ret = call ptr @test4_helper()160 ret ptr %ret161}162 163; Given a mutual recursive set of functions which *can* return null164; make sure we haven't marked them as nonnull.165define ptr @test5_helper(i1 %c) {166; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)167; TUNIT-LABEL: define {{[^@]+}}@test5_helper168; TUNIT-SAME: (i1 noundef [[C:%.*]]) #[[ATTR3]] {169; TUNIT-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]170; TUNIT: rec:171; TUNIT-NEXT: br label [[END]]172; TUNIT: end:173; TUNIT-NEXT: ret ptr null174;175; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)176; CGSCC-LABEL: define {{[^@]+}}@test5_helper177; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR1]] {178; CGSCC-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]179; CGSCC: rec:180; CGSCC-NEXT: br label [[END]]181; CGSCC: end:182; CGSCC-NEXT: ret ptr null183;184 br i1 %c, label %rec, label %end185rec:186 %ret = call ptr @test5(i1 %c)187 br label %end188end:189 ret ptr null190}191 192define ptr @test5(i1 %c) {193; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)194; TUNIT-LABEL: define {{[^@]+}}@test5195; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {196; TUNIT-NEXT: ret ptr null197;198; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)199; CGSCC-LABEL: define {{[^@]+}}@test5200; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {201; CGSCC-NEXT: ret ptr null202;203 %ret = call ptr @test5_helper(i1 %c)204 ret ptr %ret205}206 207; Local analysis, but going through a self recursive phi208define ptr @test6a() {209;210; TUNIT: Function Attrs: noreturn211; TUNIT-LABEL: define {{[^@]+}}@test6a212; TUNIT-SAME: () #[[ATTR4:[0-9]+]] {213; TUNIT-NEXT: entry:214; TUNIT-NEXT: [[RET:%.*]] = call ptr @ret_nonnull()215; TUNIT-NEXT: br label [[LOOP:%.*]]216; TUNIT: loop:217; TUNIT-NEXT: unreachable218; TUNIT: exit:219; TUNIT-NEXT: unreachable220;221; CGSCC: Function Attrs: noreturn222; CGSCC-LABEL: define {{[^@]+}}@test6a223; CGSCC-SAME: () #[[ATTR3:[0-9]+]] {224; CGSCC-NEXT: entry:225; CGSCC-NEXT: [[RET:%.*]] = call ptr @ret_nonnull()226; CGSCC-NEXT: br label [[LOOP:%.*]]227; CGSCC: loop:228; CGSCC-NEXT: unreachable229; CGSCC: exit:230; CGSCC-NEXT: unreachable231;232entry:233 %ret = call ptr @ret_nonnull()234 br label %loop235loop:236 %phi = phi ptr [%ret, %entry], [%phi, %loop]237 br i1 poison, label %loop, label %exit238exit:239 ret ptr %phi240}241 242define ptr @test6b(i1 %c) {243; CHECK-LABEL: define {{[^@]+}}@test6b244; CHECK-SAME: (i1 [[C:%.*]]) {245; CHECK-NEXT: entry:246; CHECK-NEXT: [[RET:%.*]] = call nonnull ptr @ret_nonnull()247; CHECK-NEXT: br label [[LOOP:%.*]]248; CHECK: loop:249; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[RET]], [[LOOP]] ]250; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]]251; CHECK: exit:252; CHECK-NEXT: ret ptr [[RET]]253;254entry:255 %ret = call ptr @ret_nonnull()256 br label %loop257loop:258 %phi = phi ptr [%ret, %entry], [%phi, %loop]259 br i1 %c, label %loop, label %exit260exit:261 ret ptr %phi262}263 264define ptr @test7(ptr %a) {265; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)266; CHECK-LABEL: define {{[^@]+}}@test7267; CHECK-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {268; CHECK-NEXT: ret ptr [[A]]269;270 ret ptr %a271}272 273define ptr @test8(ptr %a) {274; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)275; CHECK-LABEL: define {{[^@]+}}@test8276; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR1]] {277; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1278; CHECK-NEXT: ret ptr [[B]]279;280 %b = getelementptr inbounds i8, ptr %a, i64 1281 ret ptr %b282}283 284define ptr @test9(ptr %a, i64 %n) {285; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)286; CHECK-LABEL: define {{[^@]+}}@test9287; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR1]] {288; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]289; CHECK-NEXT: ret ptr [[B]]290;291 %b = getelementptr inbounds i8, ptr %a, i64 %n292 ret ptr %b293}294 295; ATTRIBUTOR_OPM: define ptr @test10296; ATTRIBUTOR_NPM: define nonnull ptr @test10297define ptr @test10(ptr %a, i64 %n) {298; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)299; TUNIT-LABEL: define {{[^@]+}}@test10300; TUNIT-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR2]] {301; TUNIT-NEXT: [[CMP:%.*]] = icmp ne i64 [[N]], 0302; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[CMP]]) #[[ATTR15]]303; TUNIT-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]304; TUNIT-NEXT: ret ptr [[B]]305;306; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write)307; CGSCC-LABEL: define {{[^@]+}}@test10308; CGSCC-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR2]] {309; CGSCC-NEXT: [[CMP:%.*]] = icmp ne i64 [[N]], 0310; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[CMP]]) #[[ATTR16]]311; CGSCC-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]312; CGSCC-NEXT: ret ptr [[B]]313;314 %cmp = icmp ne i64 %n, 0315 call void @llvm.assume(i1 %cmp)316 %b = getelementptr inbounds i8, ptr %a, i64 %n317 ret ptr %b318}319 320; TEST 11321; char* test11(char *p) {322; return p? p: nonnull();323; }324; FIXME: missing nonnull325define ptr @test11(ptr) local_unnamed_addr {326; CHECK-LABEL: define {{[^@]+}}@test11327; CHECK-SAME: (ptr [[TMP0:%.*]]) local_unnamed_addr {328; CHECK-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null329; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]330; CHECK: 3:331; CHECK-NEXT: [[TMP4:%.*]] = tail call ptr @ret_nonnull()332; CHECK-NEXT: br label [[TMP5]]333; CHECK: 5:334; CHECK-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]335; CHECK-NEXT: ret ptr [[TMP6]]336;337 %2 = icmp eq ptr %0, null338 br i1 %2, label %3, label %5339 340; <label>:3: ; preds = %1341 %4 = tail call ptr @ret_nonnull()342 br label %5343 344; <label>:5: ; preds = %3, %1345 %6 = phi ptr [ %4, %3 ], [ %0, %1 ]346 ret ptr %6347}348 349; TEST 12350; Simple CallSite Test351declare void @test12_helper(ptr)352define void @test12(ptr nonnull %a) {353; CHECK-LABEL: define {{[^@]+}}@test12354; CHECK-SAME: (ptr nonnull [[A:%.*]]) {355; CHECK-NEXT: tail call void @test12_helper(ptr nonnull [[A]])356; CHECK-NEXT: ret void357;358 tail call void @test12_helper(ptr %a)359 ret void360}361 362; TEST 13363; Simple Argument Tests364declare ptr @unknown()365define void @test13_helper() {366; TUNIT-LABEL: define {{[^@]+}}@test13_helper() {367; TUNIT-NEXT: [[NONNULLPTR:%.*]] = tail call nonnull ptr @ret_nonnull()368; TUNIT-NEXT: [[MAYBENULLPTR:%.*]] = tail call ptr @unknown()369; 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]+]]370; 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]]371; TUNIT-NEXT: ret void372;373; CGSCC-LABEL: define {{[^@]+}}@test13_helper() {374; CGSCC-NEXT: [[NONNULLPTR:%.*]] = tail call nonnull ptr @ret_nonnull()375; CGSCC-NEXT: [[MAYBENULLPTR:%.*]] = tail call ptr @unknown()376; 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]+]]377; 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]]378; CGSCC-NEXT: ret void379;380 %nonnullptr = tail call ptr @ret_nonnull()381 %maybenullptr = tail call ptr @unknown()382 tail call void @test13(ptr %nonnullptr, ptr %nonnullptr, ptr %maybenullptr)383 tail call void @test13(ptr %nonnullptr, ptr %maybenullptr, ptr %nonnullptr)384 ret void385}386define internal void @test13(ptr %a, ptr %b, ptr %c) {387;388; TUNIT: Function Attrs: nounwind389; TUNIT-LABEL: define {{[^@]+}}@test13390; 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]] {391; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR5]]392; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[B]]) #[[ATTR5]]393; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR5]]394; TUNIT-NEXT: ret void395;396; CGSCC: Function Attrs: nounwind397; CGSCC-LABEL: define {{[^@]+}}@test13398; 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]] {399; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR4]]400; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[B]]) #[[ATTR4]]401; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[C]]) #[[ATTR4]]402; CGSCC-NEXT: ret void403;404 call void @use_i8_ptr(ptr %a)405 call void @use_i8_ptr(ptr %b)406 call void @use_i8_ptr(ptr %c)407 ret void408}409 410declare nonnull ptr @nonnull()411 412; TEST 14413; Complex propagation414; Argument of f1, f2, f3 can be marked with nonnull.415 416; * Argument417; 1. In f1:bb6, %arg can be marked with nonnull because of the comparison in bb1418; 2. Because f2 is internal function, f2(ptr %arg) -> @f2(ptr nonnull %arg)419; 3. In f1:bb4 %tmp5 is nonnull and f3 is internal function.420; Then, f3(ptr %arg) -> @f3(ptr nonnull %arg)421; 4. We get nonnull in whole f1 call sites so f1(ptr %arg) -> @f1(ptr nonnull %arg)422 423 424define internal ptr @f1(ptr %arg) {425; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)426; CGSCC-LABEL: define {{[^@]+}}@f1427; CGSCC-SAME: (ptr nofree nonnull readonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR5:[0-9]+]] {428; CGSCC-NEXT: bb:429; CGSCC-NEXT: br label [[BB1:%.*]]430; CGSCC: bb1:431; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4, !invariant.load [[META0:![0-9]+]]432; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0433; CGSCC-NEXT: br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]]434; CGSCC: bb4:435; CGSCC-NEXT: [[TMP5C:%.*]] = getelementptr inbounds i32, ptr undef, i64 -1436; CGSCC-NEXT: br label [[BB9:%.*]]437; CGSCC: bb6:438; CGSCC-NEXT: ret ptr undef439; CGSCC: bb9:440; CGSCC-NEXT: ret ptr undef441;442 443bb:444 %tmp = icmp eq ptr %arg, null445 br i1 %tmp, label %bb9, label %bb1446 447bb1: ; preds = %bb448 %tmp2 = load i32, ptr %arg, align 4449 %tmp3 = icmp eq i32 %tmp2, 0450 br i1 %tmp3, label %bb6, label %bb4451 452bb4: ; preds = %bb1453 %tmp5 = getelementptr inbounds i32, ptr %arg, i64 1454 %tmp5b = tail call ptr @f3(ptr %tmp5)455 %tmp5c = getelementptr inbounds i32, ptr %tmp5b, i64 -1456 br label %bb9457 458bb6: ; preds = %bb1459 %tmp7 = tail call ptr @f2(ptr %arg)460 ret ptr %tmp7461 462bb9: ; preds = %bb4, %bb463 %tmp10 = phi ptr [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to ptr), %bb ]464 ret ptr %tmp10465}466 467define internal ptr @f2(ptr %arg) {468; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)469; CGSCC-LABEL: define {{[^@]+}}@f2470; CGSCC-SAME: (ptr noalias nofree nonnull readnone align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR6:[0-9]+]] {471; CGSCC-NEXT: bb:472; CGSCC-NEXT: ret ptr undef473;474bb:475 %tmp = tail call ptr @f1(ptr %arg)476 ret ptr %tmp477}478 479define dso_local noalias ptr @f3(ptr %arg) {480; FIXME: missing nonnull. It should be nonnull @f3(ptr nonnull readonly %arg)481; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)482; TUNIT-LABEL: define {{[^@]+}}@f3483; TUNIT-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]]) #[[ATTR3]] {484; TUNIT-NEXT: bb:485; TUNIT-NEXT: ret ptr undef486;487; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)488; CGSCC-LABEL: define {{[^@]+}}@f3489; CGSCC-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]]) #[[ATTR1]] {490; CGSCC-NEXT: bb:491; CGSCC-NEXT: ret ptr undef492;493bb:494; FIXME: missing nonnull. It should be @f1(ptr nonnull readonly %arg)495 %tmp = call ptr @f1(ptr %arg)496 ret ptr %tmp497}498 499; TEST 15500define void @f15(ptr %arg) {501; CHECK-LABEL: define {{[^@]+}}@f15502; CHECK-SAME: (ptr noundef nonnull dereferenceable(4) [[ARG:%.*]]) {503; CHECK-NEXT: tail call void @use1(ptr noundef nonnull dereferenceable(4) [[ARG]])504; CHECK-NEXT: ret void505;506 507 tail call void @use1(ptr dereferenceable(4) %arg)508 ret void509}510 511declare void @fun0() #1512declare void @fun1(ptr) #1513declare void @fun2(ptr, ptr) #1514declare void @fun3(ptr, ptr, ptr) #1515; TEST 16 simple path test516; if(..)517; fun2(nonnull %a, nonnull %b)518; else519; fun2(nonnull %a, %b)520; We can say that %a is nonnull but %b is not.521define void @f16(ptr %a, ptr %b, i8 %c) {522; TUNIT: Function Attrs: mustprogress nounwind willreturn523; TUNIT-LABEL: define {{[^@]+}}@f16524; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7:[0-9]+]] {525; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0526; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]527; TUNIT: if.then:528; TUNIT-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR6:[0-9]+]]529; TUNIT-NEXT: ret void530; TUNIT: if.else:531; TUNIT-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR6]]532; TUNIT-NEXT: ret void533;534; CGSCC: Function Attrs: mustprogress nounwind willreturn535; CGSCC-LABEL: define {{[^@]+}}@f16536; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR8:[0-9]+]] {537; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0538; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]539; CGSCC: if.then:540; CGSCC-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR7:[0-9]+]]541; CGSCC-NEXT: ret void542; CGSCC: if.else:543; CGSCC-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR7]]544; CGSCC-NEXT: ret void545;546 %cmp = icmp eq i8 %c, 0547 br i1 %cmp, label %if.then, label %if.else548if.then:549 tail call void @fun2(ptr nonnull %a, ptr nonnull %b)550 ret void551if.else:552 tail call void @fun2(ptr nonnull %a, ptr %b)553 ret void554}555; TEST 17 explore child BB test556; if(..)557; ... (willreturn & nounwind)558; else559; ... (willreturn & nounwind)560; fun1(nonnull %a)561; We can say that %a is nonnull562define void @f17(ptr %a, i8 %c) {563;564; TUNIT: Function Attrs: mustprogress nounwind willreturn565; TUNIT-LABEL: define {{[^@]+}}@f17566; TUNIT-SAME: (ptr nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR7]] {567; TUNIT-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0568; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]569; TUNIT: if.then:570; TUNIT-NEXT: tail call void @fun0() #[[ATTR6]]571; TUNIT-NEXT: br label [[CONT:%.*]]572; TUNIT: if.else:573; TUNIT-NEXT: tail call void @fun0() #[[ATTR6]]574; TUNIT-NEXT: br label [[CONT]]575; TUNIT: cont:576; TUNIT-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR6]]577; TUNIT-NEXT: ret void578;579; CGSCC: Function Attrs: mustprogress nounwind willreturn580; CGSCC-LABEL: define {{[^@]+}}@f17581; CGSCC-SAME: (ptr nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR8]] {582; CGSCC-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0583; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]584; CGSCC: if.then:585; CGSCC-NEXT: tail call void @fun0() #[[ATTR7]]586; CGSCC-NEXT: br label [[CONT:%.*]]587; CGSCC: if.else:588; CGSCC-NEXT: tail call void @fun0() #[[ATTR7]]589; CGSCC-NEXT: br label [[CONT]]590; CGSCC: cont:591; CGSCC-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR7]]592; CGSCC-NEXT: ret void593;594 %cmp = icmp eq i8 %c, 0595 br i1 %cmp, label %if.then, label %if.else596if.then:597 tail call void @fun0()598 br label %cont599if.else:600 tail call void @fun0()601 br label %cont602cont:603 tail call void @fun1(ptr nonnull %a)604 ret void605}606; TEST 18 More complex test607; if(..)608; ... (willreturn & nounwind)609; else610; ... (willreturn & nounwind)611; if(..)612; ... (willreturn & nounwind)613; else614; ... (willreturn & nounwind)615; fun1(nonnull %a)616 617define void @f18(ptr %a, ptr %b, i8 %c) {618; TUNIT: Function Attrs: mustprogress nounwind willreturn619; TUNIT-LABEL: define {{[^@]+}}@f18620; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7]] {621; TUNIT-NEXT: [[CMP1:%.*]] = icmp eq i8 [[C]], 0622; TUNIT-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]623; TUNIT: if.then:624; TUNIT-NEXT: tail call void @fun0() #[[ATTR6]]625; TUNIT-NEXT: br label [[CONT:%.*]]626; TUNIT: if.else:627; TUNIT-NEXT: tail call void @fun0() #[[ATTR6]]628; TUNIT-NEXT: br label [[CONT]]629; TUNIT: cont:630; TUNIT-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 1631; TUNIT-NEXT: br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]632; TUNIT: cont.then:633; TUNIT-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR6]]634; TUNIT-NEXT: br label [[CONT2:%.*]]635; TUNIT: cont.else:636; TUNIT-NEXT: tail call void @fun0() #[[ATTR6]]637; TUNIT-NEXT: br label [[CONT2]]638; TUNIT: cont2:639; TUNIT-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR6]]640; TUNIT-NEXT: ret void641;642; CGSCC: Function Attrs: mustprogress nounwind willreturn643; CGSCC-LABEL: define {{[^@]+}}@f18644; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR8]] {645; CGSCC-NEXT: [[CMP1:%.*]] = icmp eq i8 [[C]], 0646; CGSCC-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]647; CGSCC: if.then:648; CGSCC-NEXT: tail call void @fun0() #[[ATTR7]]649; CGSCC-NEXT: br label [[CONT:%.*]]650; CGSCC: if.else:651; CGSCC-NEXT: tail call void @fun0() #[[ATTR7]]652; CGSCC-NEXT: br label [[CONT]]653; CGSCC: cont:654; CGSCC-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 1655; CGSCC-NEXT: br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]656; CGSCC: cont.then:657; CGSCC-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR7]]658; CGSCC-NEXT: br label [[CONT2:%.*]]659; CGSCC: cont.else:660; CGSCC-NEXT: tail call void @fun0() #[[ATTR7]]661; CGSCC-NEXT: br label [[CONT2]]662; CGSCC: cont2:663; CGSCC-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR7]]664; CGSCC-NEXT: ret void665;666 %cmp1 = icmp eq i8 %c, 0667 br i1 %cmp1, label %if.then, label %if.else668if.then:669 tail call void @fun0()670 br label %cont671if.else:672 tail call void @fun0()673 br label %cont674cont:675 %cmp2 = icmp eq i8 %c, 1676 br i1 %cmp2, label %cont.then, label %cont.else677cont.then:678 tail call void @fun1(ptr nonnull %b)679 br label %cont2680cont.else:681 tail call void @fun0()682 br label %cont2683cont2:684 tail call void @fun1(ptr nonnull %a)685 ret void686}687 688; TEST 19: Loop689 690define void @f19(ptr %a, ptr %b, i8 %c) {691; TUNIT: Function Attrs: nounwind692; TUNIT-LABEL: define {{[^@]+}}@f19693; TUNIT-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR5]] {694; TUNIT-NEXT: br label [[LOOP_HEADER:%.*]]695; TUNIT: loop.header:696; TUNIT-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 0697; TUNIT-NEXT: br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]698; TUNIT: loop.body:699; TUNIT-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR5]]700; TUNIT-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR5]]701; TUNIT-NEXT: br label [[LOOP_HEADER]]702; TUNIT: loop.exit:703; TUNIT-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR5]]704; TUNIT-NEXT: ret void705;706; CGSCC: Function Attrs: nounwind707; CGSCC-LABEL: define {{[^@]+}}@f19708; CGSCC-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR4]] {709; CGSCC-NEXT: br label [[LOOP_HEADER:%.*]]710; CGSCC: loop.header:711; CGSCC-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 0712; CGSCC-NEXT: br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]713; CGSCC: loop.body:714; CGSCC-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR4]]715; CGSCC-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR4]]716; CGSCC-NEXT: br label [[LOOP_HEADER]]717; CGSCC: loop.exit:718; CGSCC-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR4]]719; CGSCC-NEXT: ret void720;721 br label %loop.header722loop.header:723 %cmp2 = icmp eq i8 %c, 0724 br i1 %cmp2, label %loop.body, label %loop.exit725loop.body:726 tail call void @fun1(ptr nonnull %b)727 tail call void @fun1(ptr nonnull %a)728 br label %loop.header729loop.exit:730 tail call void @fun1(ptr nonnull %b)731 ret void732}733 734; Test propagation of nonnull callsite args back to caller.735 736declare void @use1(ptr %x)737declare void @use2(ptr %x, ptr %y);738declare void @use3(ptr %x, ptr %y, ptr %z);739 740declare void @use1nonnull(ptr nonnull %x);741declare void @use2nonnull(ptr nonnull %x, ptr nonnull %y);742declare void @use3nonnull(ptr nonnull %x, ptr nonnull %y, ptr nonnull %z);743 744declare i8 @use1safecall(ptr %x) readonly nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor745 746; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.747 748define void @parent1(ptr %a, ptr %b, ptr %c) {749; CHECK-LABEL: define {{[^@]+}}@parent1750; CHECK-SAME: (ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {751; CHECK-NEXT: call void @use3(ptr [[C]], ptr [[A]], ptr [[B]])752; CHECK-NEXT: call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])753; CHECK-NEXT: ret void754;755 call void @use3(ptr %c, ptr %a, ptr %b)756 call void @use3nonnull(ptr %b, ptr %c, ptr %a)757 ret void758}759 760; Extend non-null to parent for all arguments.761 762define void @parent2(ptr %a, ptr %b, ptr %c) {763; CHECK-LABEL: define {{[^@]+}}@parent2764; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {765; CHECK-NEXT: call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])766; CHECK-NEXT: call void @use3(ptr nonnull [[C]], ptr nonnull [[A]], ptr nonnull [[B]])767; CHECK-NEXT: ret void768;769 770 call void @use3nonnull(ptr %b, ptr %c, ptr %a)771 call void @use3(ptr %c, ptr %a, ptr %b)772 ret void773}774 775; Extend non-null to parent for 1st argument.776 777define void @parent3(ptr %a, ptr %b, ptr %c) {778; CHECK-LABEL: define {{[^@]+}}@parent3779; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {780; CHECK-NEXT: call void @use1nonnull(ptr nonnull [[A]])781; CHECK-NEXT: call void @use3(ptr [[C]], ptr [[B]], ptr nonnull [[A]])782; CHECK-NEXT: ret void783;784 785 786 call void @use1nonnull(ptr %a)787 call void @use3(ptr %c, ptr %b, ptr %a)788 ret void789}790 791; Extend non-null to parent for last 2 arguments.792 793define void @parent4(ptr %a, ptr %b, ptr %c) {794; CHECK-LABEL: define {{[^@]+}}@parent4795; CHECK-SAME: (ptr [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {796; CHECK-NEXT: call void @use2nonnull(ptr nonnull [[C]], ptr nonnull [[B]])797; CHECK-NEXT: call void @use2(ptr [[A]], ptr nonnull [[C]])798; CHECK-NEXT: call void @use1(ptr nonnull [[B]])799; CHECK-NEXT: ret void800;801 802 803 804 call void @use2nonnull(ptr %c, ptr %b)805 call void @use2(ptr %a, ptr %c)806 call void @use1(ptr %b)807 ret void808}809 810; The callsite must execute in order for the attribute to transfer to the parent.811; It appears benign to extend non-null to the parent in this case, but we can't do that812; because it would incorrectly propagate the wrong information to its callers.813 814define void @parent5(ptr %a, i1 %a_is_notnull) {815; CHECK-LABEL: define {{[^@]+}}@parent5816; CHECK-SAME: (ptr [[A:%.*]], i1 noundef [[A_IS_NOTNULL:%.*]]) {817; CHECK-NEXT: br i1 [[A_IS_NOTNULL]], label [[T:%.*]], label [[F:%.*]]818; CHECK: t:819; CHECK-NEXT: call void @use1nonnull(ptr nonnull [[A]])820; CHECK-NEXT: ret void821; CHECK: f:822; CHECK-NEXT: ret void823;824 825 br i1 %a_is_notnull, label %t, label %f826t:827 call void @use1nonnull(ptr %a)828 ret void829f:830 ret void831}832 833; The callsite must execute in order for the attribute to transfer to the parent.834; The volatile load can't trap, so we can guarantee that we'll get to the call.835 836define i8 @parent6(ptr %a, ptr %b) {837; CHECK-LABEL: define {{[^@]+}}@parent6838; CHECK-SAME: (ptr nonnull [[A:%.*]], ptr nofree noundef [[B:%.*]]) {839; CHECK-NEXT: [[C:%.*]] = load volatile i8, ptr [[B]], align 1840; CHECK-NEXT: call void @use1nonnull(ptr nonnull [[A]])841; CHECK-NEXT: ret i8 [[C]]842;843 844 %c = load volatile i8, ptr %b845 call void @use1nonnull(ptr %a)846 ret i8 %c847}848 849; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.850 851define i8 @parent7(ptr %a) {852; TUNIT-LABEL: define {{[^@]+}}@parent7853; TUNIT-SAME: (ptr nonnull [[A:%.*]]) {854; TUNIT-NEXT: [[RET:%.*]] = call i8 @use1safecall(ptr nonnull readonly [[A]]) #[[ATTR16:[0-9]+]]855; TUNIT-NEXT: call void @use1nonnull(ptr nonnull [[A]])856; TUNIT-NEXT: ret i8 [[RET]]857;858; CGSCC-LABEL: define {{[^@]+}}@parent7859; CGSCC-SAME: (ptr nonnull [[A:%.*]]) {860; CGSCC-NEXT: [[RET:%.*]] = call i8 @use1safecall(ptr nonnull readonly [[A]]) #[[ATTR17:[0-9]+]]861; CGSCC-NEXT: call void @use1nonnull(ptr nonnull [[A]])862; CGSCC-NEXT: ret i8 [[RET]]863;864 865 866 %ret = call i8 @use1safecall(ptr %a)867 call void @use1nonnull(ptr %a)868 ret i8 %ret869}870 871; Make sure that an invoke works similarly to a call.872 873declare i32 @esfp(...)874 875define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{876; TUNIT: Function Attrs: nounwind877; TUNIT-LABEL: define {{[^@]+}}@parent8878; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR5]] personality ptr @esfp {879; TUNIT-NEXT: entry:880; TUNIT-NEXT: invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])881; TUNIT-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]882; TUNIT: cont:883; TUNIT-NEXT: ret i1 false884; TUNIT: exc:885; TUNIT-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }886; TUNIT-NEXT: filter [0 x ptr] zeroinitializer887; TUNIT-NEXT: unreachable888;889; CGSCC: Function Attrs: nounwind890; CGSCC-LABEL: define {{[^@]+}}@parent8891; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR4]] personality ptr @esfp {892; CGSCC-NEXT: entry:893; CGSCC-NEXT: invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])894; CGSCC-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]]895; CGSCC: cont:896; CGSCC-NEXT: ret i1 false897; CGSCC: exc:898; CGSCC-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }899; CGSCC-NEXT: filter [0 x ptr] zeroinitializer900; CGSCC-NEXT: unreachable901;902 903entry:904 invoke void @use2nonnull(ptr %a, ptr %b)905 to label %cont unwind label %exc906 907cont:908 %null_check = icmp eq ptr %b, null909 ret i1 %null_check910 911exc:912 %lp = landingpad { ptr, i32 }913 filter [0 x ptr] zeroinitializer914 unreachable915}916 917define ptr @gep1(ptr %p) {918; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)919; CHECK-LABEL: define {{[^@]+}}@gep1920; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {921; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1922; CHECK-NEXT: ret ptr [[Q]]923;924 %q = getelementptr inbounds i32, ptr %p, i32 1925 ret ptr %q926}927 928define ptr @gep1_no_null_opt(ptr %p) #0 {929; Should't be able to derive nonnull based on gep.930; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)931; TUNIT-LABEL: define {{[^@]+}}@gep1_no_null_opt932; TUNIT-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR9:[0-9]+]] {933; TUNIT-NEXT: [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1934; TUNIT-NEXT: ret ptr [[Q]]935;936; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none)937; CGSCC-LABEL: define {{[^@]+}}@gep1_no_null_opt938; CGSCC-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR10:[0-9]+]] {939; CGSCC-NEXT: [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1940; CGSCC-NEXT: ret ptr [[Q]]941;942 %q = getelementptr inbounds i32, ptr %p, i32 1943 ret ptr %q944}945 946define ptr addrspace(3) @gep2(ptr addrspace(3) %p) {947; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)948; CHECK-LABEL: define {{[^@]+}}@gep2949; CHECK-SAME: (ptr addrspace(3) nofree readnone "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {950; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[P]], i32 1951; CHECK-NEXT: ret ptr addrspace(3) [[Q]]952;953 %q = getelementptr inbounds i32, ptr addrspace(3) %p, i32 1954 ret ptr addrspace(3) %q955}956 957; FIXME: We should propagate dereferenceable here but *not* nonnull958define ptr addrspace(3) @as(ptr addrspace(3) dereferenceable(4) %p) {959; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)960; CHECK-LABEL: define {{[^@]+}}@as961; CHECK-SAME: (ptr addrspace(3) nofree noundef readnone returned dereferenceable(4) dereferenceable_or_null(4) "no-capture-maybe-returned" [[P:%.*]]) #[[ATTR1]] {962; CHECK-NEXT: ret ptr addrspace(3) [[P]]963;964 ret ptr addrspace(3) %p965}966 967define internal ptr @g2() {968; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)969; CGSCC-LABEL: define {{[^@]+}}@g2970; CGSCC-SAME: () #[[ATTR1]] {971; CGSCC-NEXT: ret ptr inttoptr (i64 4 to ptr)972;973 ret ptr inttoptr (i64 4 to ptr)974}975 976define ptr @g1() {977; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)978; TUNIT-LABEL: define {{[^@]+}}@g1979; TUNIT-SAME: () #[[ATTR1]] {980; TUNIT-NEXT: ret ptr inttoptr (i64 4 to ptr)981;982; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)983; CGSCC-LABEL: define {{[^@]+}}@g1984; CGSCC-SAME: () #[[ATTR6]] {985; CGSCC-NEXT: [[C:%.*]] = call noundef nonnull align 4 ptr @g2() #[[ATTR18:[0-9]+]]986; CGSCC-NEXT: ret ptr [[C]]987;988 %c = call ptr @g2()989 ret ptr %c990}991 992declare void @use_i32_ptr(ptr readnone nocapture) nounwind993define internal void @called_by_weak(ptr %a) {994; TUNIT: Function Attrs: nounwind995; TUNIT-LABEL: define {{[^@]+}}@called_by_weak996; TUNIT-SAME: (ptr noalias nofree nonnull readnone captures(none) [[A:%.*]]) #[[ATTR5]] {997; TUNIT-NEXT: call void @use_i32_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR5]]998; TUNIT-NEXT: ret void999;1000; CGSCC: Function Attrs: nounwind1001; CGSCC-LABEL: define {{[^@]+}}@called_by_weak1002; CGSCC-SAME: (ptr noalias nofree nonnull readnone captures(none) [[A:%.*]]) #[[ATTR4]] {1003; CGSCC-NEXT: call void @use_i32_ptr(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR4]]1004; CGSCC-NEXT: ret void1005;1006 call void @use_i32_ptr(ptr %a)1007 ret void1008}1009 1010; Check we do not annotate the function interface of this weak function.1011define weak_odr void @weak_caller(ptr nonnull %a) {1012;1013; TUNIT-LABEL: define {{[^@]+}}@weak_caller1014; TUNIT-SAME: (ptr nonnull [[A:%.*]]) {1015; TUNIT-NEXT: call void @called_by_weak(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR5]]1016; TUNIT-NEXT: ret void1017;1018; CGSCC-LABEL: define {{[^@]+}}@weak_caller1019; CGSCC-SAME: (ptr nonnull [[A:%.*]]) {1020; CGSCC-NEXT: call void @called_by_weak(ptr noalias nofree nonnull readnone captures(none) [[A]]) #[[ATTR4]]1021; CGSCC-NEXT: ret void1022;1023 call void @called_by_weak(ptr %a)1024 ret void1025}1026 1027; Expect nonnull1028define internal void @control(ptr dereferenceable(4) %a) {1029; TUNIT: Function Attrs: nounwind1030; TUNIT-LABEL: define {{[^@]+}}@control1031; TUNIT-SAME: (ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A:%.*]]) #[[ATTR5]] {1032; TUNIT-NEXT: call void @use_i32_ptr(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR5]]1033; TUNIT-NEXT: ret void1034;1035; CGSCC: Function Attrs: nounwind1036; CGSCC-LABEL: define {{[^@]+}}@control1037; CGSCC-SAME: (ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A:%.*]]) #[[ATTR4]] {1038; CGSCC-NEXT: call void @use_i32_ptr(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR4]]1039; CGSCC-NEXT: ret void1040;1041 call void @use_i32_ptr(ptr %a)1042 ret void1043}1044; Avoid nonnull as we do not touch naked functions1045define internal void @naked(ptr dereferenceable(4) %a) naked {1046; TUNIT: Function Attrs: naked1047; TUNIT-LABEL: define {{[^@]+}}@naked1048; TUNIT-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR10:[0-9]+]] {1049; TUNIT-NEXT: ret void1050;1051; CGSCC: Function Attrs: naked1052; CGSCC-LABEL: define {{[^@]+}}@naked1053; CGSCC-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {1054; CGSCC-NEXT: ret void1055;1056 ret void1057}1058; Avoid nonnull as we do not touch optnone1059define internal void @optnone(ptr dereferenceable(4) %a) optnone noinline {1060;1061; TUNIT: Function Attrs: noinline optnone1062; TUNIT-LABEL: define {{[^@]+}}@optnone1063; TUNIT-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {1064; TUNIT-NEXT: call void @use_i32_ptr(ptr nofree noundef nonnull captures(none) [[A]])1065; TUNIT-NEXT: ret void1066;1067; CGSCC: Function Attrs: noinline optnone1068; CGSCC-LABEL: define {{[^@]+}}@optnone1069; CGSCC-SAME: (ptr noundef nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR12:[0-9]+]] {1070; CGSCC-NEXT: call void @use_i32_ptr(ptr nofree noundef nonnull captures(none) [[A]])1071; CGSCC-NEXT: ret void1072;1073 call void @use_i32_ptr(ptr %a)1074 ret void1075}1076define void @make_live(ptr nonnull dereferenceable(8) %a) {1077; TUNIT-LABEL: define {{[^@]+}}@make_live1078; TUNIT-SAME: (ptr noundef nonnull align 16 dereferenceable(8) [[A:%.*]]) {1079; TUNIT-NEXT: call void @naked(ptr noundef nonnull align 16 dereferenceable(8) [[A]])1080; TUNIT-NEXT: call void @control(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR5]]1081; TUNIT-NEXT: call void @optnone(ptr noundef nonnull align 16 dereferenceable(8) [[A]])1082; TUNIT-NEXT: ret void1083;1084; CGSCC-LABEL: define {{[^@]+}}@make_live1085; CGSCC-SAME: (ptr noundef nonnull align 16 dereferenceable(8) [[A:%.*]]) {1086; CGSCC-NEXT: call void @naked(ptr noundef nonnull align 16 dereferenceable(8) [[A]])1087; CGSCC-NEXT: call void @control(ptr noalias nofree noundef nonnull readnone align 16 captures(none) dereferenceable(8) [[A]]) #[[ATTR4]]1088; CGSCC-NEXT: call void @optnone(ptr noundef nonnull align 16 dereferenceable(8) [[A]])1089; CGSCC-NEXT: ret void1090;1091 call void @naked(ptr nonnull dereferenceable(8) align 16 %a)1092 call void @control(ptr nonnull dereferenceable(8) align 16 %a)1093 call void @optnone(ptr nonnull dereferenceable(8) align 16 %a)1094 ret void1095}1096 1097 1098;int f(int *u, int n){1099; for(int i = 0;i<n;i++){1100; h(u);1101; }1102; return g(nonnull u);1103;}1104declare void @h(ptr) willreturn nounwind1105declare i32 @g(ptr) willreturn nounwind1106define i32 @nonnull_exec_ctx_1(ptr %a, i32 %b) {1107;1108; TUNIT: Function Attrs: mustprogress nounwind willreturn1109; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_11110; TUNIT-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {1111; TUNIT-NEXT: en:1112; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01113; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1114; TUNIT: ex:1115; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]]1116; TUNIT-NEXT: ret i32 [[TMP5]]1117; TUNIT: hd:1118; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1119; TUNIT-NEXT: tail call void @h(ptr [[A]]) #[[ATTR6]]1120; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11121; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1122; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1123;1124; CGSCC: Function Attrs: mustprogress nounwind willreturn1125; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_11126; CGSCC-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {1127; CGSCC-NEXT: en:1128; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01129; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1130; CGSCC: ex:1131; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]]1132; CGSCC-NEXT: ret i32 [[TMP5]]1133; CGSCC: hd:1134; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1135; CGSCC-NEXT: tail call void @h(ptr [[A]]) #[[ATTR7]]1136; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11137; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1138; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1139;1140en:1141 %tmp3 = icmp eq i32 %b, 01142 br i1 %tmp3, label %ex, label %hd1143 1144ex:1145 %tmp5 = tail call i32 @g(ptr nonnull %a)1146 ret i32 %tmp51147 1148hd:1149 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]1150 tail call void @h(ptr %a)1151 %tmp8 = add nuw i32 %tmp7, 11152 %tmp9 = icmp eq i32 %tmp8, %b1153 br i1 %tmp9, label %ex, label %hd1154}1155 1156define i32 @nonnull_exec_ctx_1b(ptr %a, i32 %b) {1157;1158; TUNIT: Function Attrs: mustprogress nounwind willreturn1159; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b1160; TUNIT-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {1161; TUNIT-NEXT: en:1162; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01163; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1164; TUNIT: ex:1165; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]]1166; TUNIT-NEXT: ret i32 [[TMP5]]1167; TUNIT: hd:1168; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1169; TUNIT-NEXT: tail call void @h(ptr [[A]]) #[[ATTR6]]1170; TUNIT-NEXT: br label [[HD2]]1171; TUNIT: hd2:1172; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11173; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1174; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1175;1176; CGSCC: Function Attrs: mustprogress nounwind willreturn1177; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b1178; CGSCC-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {1179; CGSCC-NEXT: en:1180; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01181; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1182; CGSCC: ex:1183; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]]1184; CGSCC-NEXT: ret i32 [[TMP5]]1185; CGSCC: hd:1186; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1187; CGSCC-NEXT: tail call void @h(ptr [[A]]) #[[ATTR7]]1188; CGSCC-NEXT: br label [[HD2]]1189; CGSCC: hd2:1190; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11191; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1192; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1193;1194en:1195 %tmp3 = icmp eq i32 %b, 01196 br i1 %tmp3, label %ex, label %hd1197 1198ex:1199 %tmp5 = tail call i32 @g(ptr nonnull %a)1200 ret i32 %tmp51201 1202hd:1203 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]1204 tail call void @h(ptr %a)1205 br label %hd21206 1207hd2:1208 %tmp8 = add nuw i32 %tmp7, 11209 %tmp9 = icmp eq i32 %tmp8, %b1210 br i1 %tmp9, label %ex, label %hd1211}1212 1213define i32 @nonnull_exec_ctx_2(ptr %a, i32 %b) willreturn nounwind {1214;1215; TUNIT: Function Attrs: mustprogress nounwind willreturn1216; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_21217; TUNIT-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {1218; TUNIT-NEXT: en:1219; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01220; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1221; TUNIT: ex:1222; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]]1223; TUNIT-NEXT: ret i32 [[TMP5]]1224; TUNIT: hd:1225; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1226; TUNIT-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR5]]1227; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11228; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1229; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1230;1231; CGSCC: Function Attrs: mustprogress nounwind willreturn1232; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_21233; CGSCC-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {1234; CGSCC-NEXT: en:1235; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01236; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1237; CGSCC: ex:1238; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]]1239; CGSCC-NEXT: ret i32 [[TMP5]]1240; CGSCC: hd:1241; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1242; CGSCC-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR4]]1243; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11244; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1245; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1246;1247en:1248 %tmp3 = icmp eq i32 %b, 01249 br i1 %tmp3, label %ex, label %hd1250 1251ex:1252 %tmp5 = tail call i32 @g(ptr nonnull %a)1253 ret i32 %tmp51254 1255hd:1256 %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]1257 tail call void @h(ptr %a)1258 %tmp8 = add nuw i32 %tmp7, 11259 %tmp9 = icmp eq i32 %tmp8, %b1260 br i1 %tmp9, label %ex, label %hd1261}1262 1263define i32 @nonnull_exec_ctx_2b(ptr %a, i32 %b) willreturn nounwind {1264;1265; TUNIT: Function Attrs: mustprogress nounwind willreturn1266; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b1267; TUNIT-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {1268; TUNIT-NEXT: en:1269; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01270; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1271; TUNIT: ex:1272; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]]1273; TUNIT-NEXT: ret i32 [[TMP5]]1274; TUNIT: hd:1275; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1276; TUNIT-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR5]]1277; TUNIT-NEXT: br label [[HD2]]1278; TUNIT: hd2:1279; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11280; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1281; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1282;1283; CGSCC: Function Attrs: mustprogress nounwind willreturn1284; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b1285; CGSCC-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] {1286; CGSCC-NEXT: en:1287; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 01288; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1289; CGSCC: ex:1290; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]]1291; CGSCC-NEXT: ret i32 [[TMP5]]1292; CGSCC: hd:1293; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1294; CGSCC-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR4]]1295; CGSCC-NEXT: br label [[HD2]]1296; CGSCC: hd2:1297; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 11298; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1299; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]]1300;1301en:1302 %tmp3 = icmp eq i32 %b, 01303 br i1 %tmp3, label %ex, label %hd1304 1305ex:1306 %tmp5 = tail call i32 @g(ptr nonnull %a)1307 ret i32 %tmp51308 1309hd:1310 %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]1311 tail call void @h(ptr %a)1312 br label %hd21313 1314hd2:1315 %tmp8 = add nuw i32 %tmp7, 11316 %tmp9 = icmp eq i32 %tmp8, %b1317 br i1 %tmp9, label %ex, label %hd1318}1319 1320; Original from PR438331321declare void @sink(ptr)1322 1323define void @PR43833(ptr %0, i32 %1) {1324; CHECK-LABEL: define {{[^@]+}}@PR438331325; CHECK-SAME: (ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) {1326; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP1]], 11327; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]1328; CHECK: 4:1329; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i641330; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[TMP5]]1331; CHECK-NEXT: br label [[TMP8:%.*]]1332; CHECK: 7:1333; CHECK-NEXT: ret void1334; CHECK: 8:1335; CHECK-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]1336; CHECK-NEXT: tail call void @sink(ptr nonnull [[TMP6]])1337; CHECK-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 11338; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]1339; CHECK-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]1340;1341 %3 = icmp sgt i32 %1, 11342 br i1 %3, label %4, label %71343 13444: ; preds = %21345 %5 = zext i32 %1 to i641346 %6 = getelementptr inbounds i32, ptr %0, i64 %51347 br label %81348 13497: ; preds = %8, %21350 ret void1351 13528: ; preds = %8, %41353 %9 = phi i32 [ 1, %4 ], [ %10, %8 ]1354 tail call void @sink(ptr %6)1355 %10 = add nuw nsw i32 %9, 11356 %11 = icmp eq i32 %10, %11357 br i1 %11, label %7, label %81358}1359 1360; Adjusted from PR438331361define void @PR43833_simple(ptr %0, i32 %1) {1362; CHECK-LABEL: define {{[^@]+}}@PR43833_simple1363; CHECK-SAME: (ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) {1364; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 01365; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]1366; CHECK: 4:1367; CHECK-NEXT: [[TMP5:%.*]] = zext i32 [[TMP1]] to i641368; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[TMP5]]1369; CHECK-NEXT: br label [[TMP8:%.*]]1370; CHECK: 7:1371; CHECK-NEXT: ret void1372; CHECK: 8:1373; CHECK-NEXT: [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]1374; CHECK-NEXT: tail call void @sink(ptr nonnull [[TMP6]])1375; CHECK-NEXT: [[TMP10]] = add nuw nsw i32 [[TMP9]], 11376; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]1377; CHECK-NEXT: br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]1378;1379 %3 = icmp ne i32 %1, 01380 br i1 %3, label %4, label %71381 13824: ; preds = %21383 %5 = zext i32 %1 to i641384 %6 = getelementptr inbounds i32, ptr %0, i64 %51385 br label %81386 13877: ; preds = %8, %21388 ret void1389 13908: ; preds = %8, %41391 %9 = phi i32 [ 1, %4 ], [ %10, %8 ]1392 tail call void @sink(ptr %6)1393 %10 = add nuw nsw i32 %9, 11394 %11 = icmp eq i32 %10, %11395 br i1 %11, label %7, label %81396}1397 1398declare ptr @strrchr(ptr %0, i32 %1) nofree nounwind readonly willreturn1399 1400; We should not mark the return of @strrchr as `nonnull`, it may well be NULL!1401define ptr @mybasename(ptr nofree readonly %str) {1402; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)1403; TUNIT-LABEL: define {{[^@]+}}@mybasename1404; TUNIT-SAME: (ptr nofree readonly [[STR:%.*]]) #[[ATTR13:[0-9]+]] {1405; TUNIT-NEXT: [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR17:[0-9]+]]1406; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[CALL]], null1407; TUNIT-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 11408; TUNIT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], ptr [[ADD_PTR]], ptr [[STR]]1409; TUNIT-NEXT: ret ptr [[COND]]1410;1411; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read)1412; CGSCC-LABEL: define {{[^@]+}}@mybasename1413; CGSCC-SAME: (ptr nofree readonly [[STR:%.*]]) #[[ATTR14:[0-9]+]] {1414; CGSCC-NEXT: [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR19:[0-9]+]]1415; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[CALL]], null1416; CGSCC-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 11417; CGSCC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], ptr [[ADD_PTR]], ptr [[STR]]1418; CGSCC-NEXT: ret ptr [[COND]]1419;1420 %call = call ptr @strrchr(ptr %str, i32 47)1421 %tobool = icmp ne ptr %call, null1422 %add.ptr = getelementptr inbounds i8, ptr %call, i64 11423 %cond = select i1 %tobool, ptr %add.ptr, ptr %str1424 ret ptr %cond1425}1426 1427define void @nonnull_assume_pos(ptr %arg) {1428; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_pos1429; ATTRIBUTOR-SAME: (ptr nocapture nofree nonnull readnone [[ARG:%.*]])1430; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) #11 [ "nonnull"(ptr [[ARG]]) ]1431; ATTRIBUTOR-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[ARG]])1432; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call ptr @unknown()1433; ATTRIBUTOR-NEXT: ret void1434;1435; TUNIT-LABEL: define {{[^@]+}}@nonnull_assume_pos1436; TUNIT-SAME: (ptr nofree nonnull readnone captures(none) [[ARG:%.*]]) {1437; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "nonnull"(ptr [[ARG]]) ]1438; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]1439; TUNIT-NEXT: [[TMP1:%.*]] = call ptr @unknown()1440; TUNIT-NEXT: ret void1441;1442; CGSCC-LABEL: define {{[^@]+}}@nonnull_assume_pos1443; CGSCC-SAME: (ptr nofree nonnull readnone captures(none) [[ARG:%.*]]) {1444; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[ARG]]) ]1445; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]1446; CGSCC-NEXT: [[TMP1:%.*]] = call ptr @unknown()1447; CGSCC-NEXT: ret void1448;1449 call void @llvm.assume(i1 true) ["nonnull"(ptr %arg)]1450 call void @use_i8_ptr(ptr %arg)1451 call ptr @unknown()1452 ret void1453}1454define void @nonnull_assume_neg(ptr %arg) {1455; ATTRIBUTOR-LABEL: define {{[^@]+}}@nonnull_assume_neg1456; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[ARG:%.*]])1457; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call ptr @unknown()1458; ATTRIBUTOR-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[ARG]])1459; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]) ]1460; ATTRIBUTOR-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[ARG]])1461; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = call ptr @unknown()1462; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(ptr noalias nocapture nofree nonnull readnone [[ARG]])1463; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]) ]1464; ATTRIBUTOR-NEXT: call void @use_i8_ptr_ret(ptr noalias nocapture nofree nonnull readnone [[ARG]])1465; ATTRIBUTOR-NEXT: ret void1466;1467;1468; TUNIT-LABEL: define {{[^@]+}}@nonnull_assume_neg1469; TUNIT-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]]) {1470; TUNIT-NEXT: [[TMP1:%.*]] = call ptr @unknown()1471; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[ARG]]) #[[ATTR5]]1472; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]1473; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]1474; TUNIT-NEXT: [[TMP2:%.*]] = call ptr @unknown()1475; TUNIT-NEXT: call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]1476; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]1477; TUNIT-NEXT: call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR5]]1478; TUNIT-NEXT: ret void1479;1480; CGSCC-LABEL: define {{[^@]+}}@nonnull_assume_neg1481; CGSCC-SAME: (ptr nofree readnone captures(none) [[ARG:%.*]]) {1482; CGSCC-NEXT: [[TMP1:%.*]] = call ptr @unknown()1483; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree readnone captures(none) [[ARG]]) #[[ATTR4]]1484; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]1485; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]1486; CGSCC-NEXT: [[TMP2:%.*]] = call ptr @unknown()1487; CGSCC-NEXT: call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]1488; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) [ "nonnull"(ptr [[ARG]]) ]1489; CGSCC-NEXT: call void @use_i8_ptr_ret(ptr noalias nofree nonnull readnone captures(none) [[ARG]]) #[[ATTR4]]1490; CGSCC-NEXT: ret void1491;1492 call ptr @unknown()1493 call void @use_i8_ptr(ptr %arg)1494 call void @llvm.assume(i1 true) ["nonnull"(ptr %arg)]1495 call void @use_i8_ptr(ptr %arg)1496 call ptr @unknown()1497 call void @use_i8_ptr_ret(ptr %arg)1498 call void @llvm.assume(i1 true) ["nonnull"(ptr %arg)]1499 call void @use_i8_ptr_ret(ptr %arg)1500 ret void1501}1502declare void @use_i8_ptr(ptr nofree nocapture readnone) nounwind1503declare void @use_i8_ptr_ret(ptr nofree nocapture readnone) nounwind willreturn1504 1505define ptr @nonnull_function_ptr_1() {1506; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)1507; CHECK-LABEL: define {{[^@]+}}@nonnull_function_ptr_11508; CHECK-SAME: () #[[ATTR1]] {1509; CHECK-NEXT: ret ptr @nonnull_function_ptr_11510;1511 ret ptr @nonnull_function_ptr_11512}1513 1514declare ptr @function_decl()1515define ptr @nonnull_function_ptr_2() {1516; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)1517; CHECK-LABEL: define {{[^@]+}}@nonnull_function_ptr_21518; CHECK-SAME: () #[[ATTR1]] {1519; CHECK-NEXT: ret ptr @function_decl1520;1521 ret ptr @function_decl1522}1523 1524; FIXME: nonnull should not be propagated to the caller's p unless there is noundef1525define void @nonnull_caller(ptr %p) {1526; CHECK-LABEL: define {{[^@]+}}@nonnull_caller1527; CHECK-SAME: (ptr nonnull [[P:%.*]]) {1528; CHECK-NEXT: call void @nonnull_callee(ptr nonnull [[P]])1529; CHECK-NEXT: ret void1530;1531 call void @nonnull_callee(ptr %p)1532 ret void1533}1534declare void @nonnull_callee(ptr nonnull %p)1535 1536define ptr @phi(ptr %p) {1537; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)1538; CHECK-LABEL: define {{[^@]+}}@phi1539; CHECK-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR1]] {1540; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P]], null1541; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 11542; CHECK-NEXT: br i1 [[C]], label [[NULL:%.*]], label [[NNULL:%.*]]1543; CHECK: NNULL:1544; CHECK-NEXT: br label [[MERGE:%.*]]1545; CHECK: NULL:1546; CHECK-NEXT: br label [[MERGE]]1547; CHECK: merge:1548; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[P]], [[NNULL]] ], [ [[G]], [[NULL]] ]1549; CHECK-NEXT: ret ptr [[PHI]]1550;1551 %c = icmp eq ptr %p, null1552 %g = getelementptr inbounds i8, ptr %p, i64 11553 br i1 %c, label %NULL, label %NNULL1554NNULL:1555 br label %merge1556NULL:1557 br label %merge1558merge:1559 %phi = phi ptr [%p, %NNULL], [%g, %NULL]1560 ret ptr %phi1561}1562define void @phi_caller(ptr %p) {1563; TUNIT: Function Attrs: nounwind1564; TUNIT-LABEL: define {{[^@]+}}@phi_caller1565; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {1566; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR18:[0-9]+]]1567; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR5]]1568; TUNIT-NEXT: ret void1569;1570; CGSCC: Function Attrs: nounwind1571; CGSCC-LABEL: define {{[^@]+}}@phi_caller1572; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] {1573; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR20:[0-9]+]]1574; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR4]]1575; CGSCC-NEXT: ret void1576;1577 %c = call ptr @phi(ptr %p)1578 call void @use_i8_ptr(ptr %c)1579 ret void1580}1581 1582define ptr @multi_ret(ptr %p) {1583; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)1584; CHECK-LABEL: define {{[^@]+}}@multi_ret1585; CHECK-SAME: (ptr nofree readnone [[P:%.*]]) #[[ATTR1]] {1586; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[P]], null1587; CHECK-NEXT: br i1 [[C]], label [[NULL:%.*]], label [[NNULL:%.*]]1588; CHECK: NNULL:1589; CHECK-NEXT: ret ptr [[P]]1590; CHECK: NULL:1591; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 11592; CHECK-NEXT: ret ptr [[G]]1593;1594 %c = icmp eq ptr %p, null1595 br i1 %c, label %NULL, label %NNULL1596NNULL:1597 ret ptr %p1598NULL:1599 %g = getelementptr inbounds i8, ptr %p, i64 11600 ret ptr %g1601}1602define void @multi_ret_caller(ptr %p) {1603; TUNIT: Function Attrs: nounwind1604; TUNIT-LABEL: define {{[^@]+}}@multi_ret_caller1605; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] {1606; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR18]]1607; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR5]]1608; TUNIT-NEXT: ret void1609;1610; CGSCC: Function Attrs: nounwind1611; CGSCC-LABEL: define {{[^@]+}}@multi_ret_caller1612; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] {1613; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR20]]1614; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nofree nonnull readnone captures(none) [[C]]) #[[ATTR4]]1615; CGSCC-NEXT: ret void1616;1617 %c = call ptr @multi_ret(ptr %p)1618 call void @use_i8_ptr(ptr %c)1619 ret void1620}1621 1622; From https://github.com/llvm/llvm-project/pull/858101623@G = internal global i64 1, align 81624define dso_local ptr @update_global_in_alive_bb() {1625; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn1626; TUNIT-LABEL: define {{[^@]+}}@update_global_in_alive_bb1627; TUNIT-SAME: () #[[ATTR14:[0-9]+]] {1628; TUNIT-NEXT: entry:1629; TUNIT-NEXT: [[TMP0:%.*]] = load i64, ptr @G, align 81630; TUNIT-NEXT: [[CMP:%.*]] = icmp ne i64 [[TMP0]], 01631; TUNIT-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]1632; TUNIT: if.then:1633; TUNIT-NEXT: store i64 0, ptr @G, align 81634; TUNIT-NEXT: ret ptr inttoptr (i64 5 to ptr)1635; TUNIT: if.else:1636; TUNIT-NEXT: ret ptr null1637;1638; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn1639; CGSCC-LABEL: define {{[^@]+}}@update_global_in_alive_bb1640; CGSCC-SAME: () #[[ATTR15:[0-9]+]] {1641; CGSCC-NEXT: entry:1642; CGSCC-NEXT: [[TMP0:%.*]] = load i64, ptr @G, align 81643; CGSCC-NEXT: [[CMP:%.*]] = icmp ne i64 [[TMP0]], 01644; CGSCC-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]1645; CGSCC: if.then:1646; CGSCC-NEXT: store i64 0, ptr @G, align 81647; CGSCC-NEXT: ret ptr inttoptr (i64 5 to ptr)1648; CGSCC: if.else:1649; CGSCC-NEXT: ret ptr null1650;1651entry:1652 %0 = load i64, ptr @G, align 81653 %cmp = icmp ne i64 %0, 01654 br i1 %cmp, label %if.then, label %if.else1655if.then:1656 store i64 0, ptr @G, align 81657 ret ptr inttoptr (i64 5 to ptr)1658if.else:1659 ret ptr null1660}1661 1662attributes #0 = { null_pointer_is_valid }1663attributes #1 = { nounwind willreturn}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]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: read) }1671; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree nosync nounwind willreturn memory(none) }1672; CGSCC: attributes #[[ATTR7]] = { nounwind willreturn }1673; CGSCC: attributes #[[ATTR8]] = { mustprogress nounwind willreturn }1674; CGSCC: attributes #[[ATTR9:[0-9]+]] = { nounwind willreturn memory(read) }1675; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid 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]] = { nosync willreturn memory(read) }1683; CGSCC: attributes #[[ATTR18]] = { nofree nosync willreturn }1684; CGSCC: attributes #[[ATTR19]] = { nofree nosync willreturn memory(read) }1685; CGSCC: attributes #[[ATTR20]] = { nofree willreturn }1686;.1687; TUNIT: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }1688; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }1689; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) }1690; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn memory(none) }1691; TUNIT: attributes #[[ATTR4]] = { noreturn }1692; TUNIT: attributes #[[ATTR5]] = { nounwind }1693; TUNIT: attributes #[[ATTR6]] = { nounwind willreturn }1694; TUNIT: attributes #[[ATTR7]] = { mustprogress nounwind willreturn }1695; TUNIT: attributes #[[ATTR8:[0-9]+]] = { nounwind willreturn memory(read) }1696; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind null_pointer_is_valid willreturn memory(none) }1697; TUNIT: attributes #[[ATTR10]] = { naked }1698; TUNIT: attributes #[[ATTR11]] = { noinline optnone }1699; TUNIT: attributes #[[ATTR12:[0-9]+]] = { nofree nounwind willreturn memory(read) }1700; TUNIT: attributes #[[ATTR13]] = { mustprogress nofree nosync nounwind willreturn memory(read) }1701; TUNIT: attributes #[[ATTR14]] = { mustprogress nofree norecurse nosync nounwind willreturn }1702; TUNIT: attributes #[[ATTR15]] = { nofree willreturn memory(write) }1703; TUNIT: attributes #[[ATTR16]] = { nosync willreturn memory(read) }1704; TUNIT: attributes #[[ATTR17]] = { nofree nosync willreturn memory(read) }1705; TUNIT: attributes #[[ATTR18]] = { nofree nosync nounwind willreturn memory(none) }1706;.1707; CGSCC: [[META0]] = !{}1708;.1709