brintos

brintos / llvm-project-archived public Read only

0
0
Text · 51.5 KiB · e06fb1c Raw
1430 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 32; RUN: opt -S -passes=function-attrs -enable-nonnull-arg-prop %s | FileCheck %s --check-prefixes=COMMON,FNATTRS3; RUN: opt -S -passes=attributor-light %s | FileCheck %s --check-prefixes=COMMON,ATTRIBUTOR4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6 7declare nonnull ptr @ret_nonnull()8 9; Return a pointer trivially nonnull (call return attribute)10define ptr @test1() {11; COMMON-LABEL: define nonnull ptr @test1() {12; COMMON-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()13; COMMON-NEXT:    ret ptr [[RET]]14;15  %ret = call ptr @ret_nonnull()16  ret ptr %ret17}18 19; Return a pointer trivially nonnull (argument attribute)20define ptr @test2(ptr nonnull %p) {21; FNATTRS-LABEL: define nonnull ptr @test2(22; FNATTRS-SAME: ptr nonnull readnone returned captures(ret: address, provenance) [[P:%.*]]) #[[ATTR0:[0-9]+]] {23; FNATTRS-NEXT:    ret ptr [[P]]24;25; ATTRIBUTOR-LABEL: define nonnull ptr @test2(26; ATTRIBUTOR-SAME: ptr nofree nonnull readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] {27; ATTRIBUTOR-NEXT:    ret ptr [[P]]28;29  ret ptr %p30}31 32; Given an SCC where one of the functions can not be marked nonnull,33; can we still mark the other one which is trivially nonnull34define ptr @scc_binder(i1 %c) {35; FNATTRS-LABEL: define noundef ptr @scc_binder(36; FNATTRS-SAME: i1 [[C:%.*]]) {37; FNATTRS-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]38; FNATTRS:       rec:39; FNATTRS-NEXT:    [[TMP1:%.*]] = call ptr @test3(i1 [[C]])40; FNATTRS-NEXT:    br label [[END]]41; FNATTRS:       end:42; FNATTRS-NEXT:    ret ptr null43;44; ATTRIBUTOR-LABEL: define ptr @scc_binder(45; ATTRIBUTOR-SAME: i1 [[C:%.*]]) {46; ATTRIBUTOR-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]47; ATTRIBUTOR:       rec:48; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = call ptr @test3(i1 [[C]])49; ATTRIBUTOR-NEXT:    br label [[END]]50; ATTRIBUTOR:       end:51; ATTRIBUTOR-NEXT:    ret ptr null52;53  br i1 %c, label %rec, label %end54rec:55  call ptr @test3(i1 %c)56  br label %end57end:58  ret ptr null59}60 61define ptr @test3(i1 %c) {62; COMMON-LABEL: define nonnull ptr @test3(63; COMMON-SAME: i1 [[C:%.*]]) {64; COMMON-NEXT:    [[TMP1:%.*]] = call ptr @scc_binder(i1 [[C]])65; COMMON-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()66; COMMON-NEXT:    ret ptr [[RET]]67;68  call ptr @scc_binder(i1 %c)69  %ret = call ptr @ret_nonnull()70  ret ptr %ret71}72 73; Given a mutual recursive set of functions, we can mark them74; nonnull if neither can ever return null.  (In this case, they75; just never return period.)76define ptr @test4_helper() {77; FNATTRS-LABEL: define noalias nonnull ptr @test4_helper(78; FNATTRS-SAME: ) #[[ATTR1:[0-9]+]] {79; FNATTRS-NEXT:    [[RET:%.*]] = call ptr @test4()80; FNATTRS-NEXT:    ret ptr [[RET]]81;82; ATTRIBUTOR-LABEL: define ptr @test4_helper(83; ATTRIBUTOR-SAME: ) #[[ATTR1:[0-9]+]] {84; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call ptr @test4() #[[ATTR1]]85; ATTRIBUTOR-NEXT:    ret ptr [[RET]]86;87  %ret = call ptr @test4()88  ret ptr %ret89}90 91define ptr @test4() {92; FNATTRS-LABEL: define noalias nonnull ptr @test4(93; FNATTRS-SAME: ) #[[ATTR1]] {94; FNATTRS-NEXT:    [[RET:%.*]] = call ptr @test4_helper()95; FNATTRS-NEXT:    ret ptr [[RET]]96;97; ATTRIBUTOR-LABEL: define ptr @test4(98; ATTRIBUTOR-SAME: ) #[[ATTR1]] {99; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call ptr @test4_helper() #[[ATTR1]]100; ATTRIBUTOR-NEXT:    ret ptr [[RET]]101;102  %ret = call ptr @test4_helper()103  ret ptr %ret104}105 106; Given a mutual recursive set of functions which *can* return null107; make sure we haven't marked them as nonnull.108define ptr @test5_helper(i1 %c) {109; FNATTRS-LABEL: define noalias noundef ptr @test5_helper(110; FNATTRS-SAME: i1 [[C:%.*]]) #[[ATTR1]] {111; FNATTRS-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]112; FNATTRS:       rec:113; FNATTRS-NEXT:    [[RET:%.*]] = call ptr @test5(i1 [[C]])114; FNATTRS-NEXT:    br label [[END]]115; FNATTRS:       end:116; FNATTRS-NEXT:    ret ptr null117;118; ATTRIBUTOR-LABEL: define ptr @test5_helper(119; ATTRIBUTOR-SAME: i1 [[C:%.*]]) #[[ATTR1]] {120; ATTRIBUTOR-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[END:%.*]]121; ATTRIBUTOR:       rec:122; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call ptr @test5(i1 [[C]]) #[[ATTR1]]123; ATTRIBUTOR-NEXT:    br label [[END]]124; ATTRIBUTOR:       end:125; ATTRIBUTOR-NEXT:    ret ptr null126;127  br i1 %c, label %rec, label %end128rec:129  %ret = call ptr @test5(i1 %c)130  br label %end131end:132  ret ptr null133}134 135define ptr @test5(i1 %c) {136; FNATTRS-LABEL: define noalias noundef ptr @test5(137; FNATTRS-SAME: i1 [[C:%.*]]) #[[ATTR1]] {138; FNATTRS-NEXT:    [[RET:%.*]] = call ptr @test5_helper(i1 [[C]])139; FNATTRS-NEXT:    ret ptr [[RET]]140;141; ATTRIBUTOR-LABEL: define ptr @test5(142; ATTRIBUTOR-SAME: i1 [[C:%.*]]) #[[ATTR1]] {143; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call ptr @test5_helper(i1 [[C]]) #[[ATTR1]]144; ATTRIBUTOR-NEXT:    ret ptr [[RET]]145;146  %ret = call ptr @test5_helper(i1 %c)147  ret ptr %ret148}149 150; Local analysis, but going through a self recursive phi151define ptr @test6a(i1 %arg) {152; COMMON-LABEL: define nonnull ptr @test6a(153; COMMON-SAME: i1 [[ARG:%.*]]) {154; COMMON-NEXT:  entry:155; COMMON-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()156; COMMON-NEXT:    br label [[LOOP:%.*]]157; COMMON:       loop:158; COMMON-NEXT:    [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ]159; COMMON-NEXT:    br i1 [[ARG]], label [[LOOP]], label [[EXIT:%.*]]160; COMMON:       exit:161; COMMON-NEXT:    ret ptr [[PHI]]162;163entry:164  %ret = call ptr @ret_nonnull()165  br label %loop166loop:167  %phi = phi ptr [%ret, %entry], [%phi, %loop]168  br i1 %arg, label %loop, label %exit169exit:170  ret ptr %phi171}172 173define ptr @test6b(i1 %c) {174; COMMON-LABEL: define nonnull ptr @test6b(175; COMMON-SAME: i1 [[C:%.*]]) {176; COMMON-NEXT:  entry:177; COMMON-NEXT:    [[RET:%.*]] = call ptr @ret_nonnull()178; COMMON-NEXT:    br label [[LOOP:%.*]]179; COMMON:       loop:180; COMMON-NEXT:    [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ]181; COMMON-NEXT:    br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]]182; COMMON:       exit:183; COMMON-NEXT:    ret ptr [[PHI]]184;185entry:186  %ret = call ptr @ret_nonnull()187  br label %loop188loop:189  %phi = phi ptr [%ret, %entry], [%phi, %loop]190  br i1 %c, label %loop, label %exit191exit:192  ret ptr %phi193}194 195define ptr @test7(ptr %a) {196; FNATTRS-LABEL: define ptr @test7(197; FNATTRS-SAME: ptr readnone returned captures(ret: address, provenance) [[A:%.*]]) #[[ATTR0]] {198; FNATTRS-NEXT:    ret ptr [[A]]199;200; ATTRIBUTOR-LABEL: define ptr @test7(201; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]]) #[[ATTR0]] {202; ATTRIBUTOR-NEXT:    ret ptr [[A]]203;204  ret ptr %a205}206 207define ptr @test8(ptr %a) {208; FNATTRS-LABEL: define nonnull ptr @test8(209; FNATTRS-SAME: ptr readnone captures(ret: address, provenance) [[A:%.*]]) #[[ATTR0]] {210; FNATTRS-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1211; FNATTRS-NEXT:    ret ptr [[B]]212;213; ATTRIBUTOR-LABEL: define nonnull ptr @test8(214; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]]) #[[ATTR0]] {215; ATTRIBUTOR-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1216; ATTRIBUTOR-NEXT:    ret ptr [[B]]217;218  %b = getelementptr inbounds i8, ptr %a, i64 1219  ret ptr %b220}221 222define ptr @test9(ptr %a, i64 %n) {223; FNATTRS-LABEL: define ptr @test9(224; FNATTRS-SAME: ptr readnone captures(ret: address, provenance) [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {225; FNATTRS-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]226; FNATTRS-NEXT:    ret ptr [[B]]227;228; ATTRIBUTOR-LABEL: define ptr @test9(229; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]], i64 [[N:%.*]]) #[[ATTR0]] {230; ATTRIBUTOR-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]231; ATTRIBUTOR-NEXT:    ret ptr [[B]]232;233  %b = getelementptr inbounds i8, ptr %a, i64 %n234  ret ptr %b235}236 237declare void @llvm.assume(i1)238; FIXME: missing nonnull239define ptr @test10(ptr %a, i64 %n) {240; FNATTRS-LABEL: define ptr @test10(241; FNATTRS-SAME: ptr readnone captures(ret: address, provenance) [[A:%.*]], i64 [[N:%.*]]) #[[ATTR3:[0-9]+]] {242; FNATTRS-NEXT:    [[CMP:%.*]] = icmp ne i64 [[N]], 0243; FNATTRS-NEXT:    call void @llvm.assume(i1 [[CMP]])244; FNATTRS-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]245; FNATTRS-NEXT:    ret ptr [[B]]246;247; ATTRIBUTOR-LABEL: define ptr @test10(248; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]], i64 [[N:%.*]]) #[[ATTR3:[0-9]+]] {249; ATTRIBUTOR-NEXT:    [[CMP:%.*]] = icmp ne i64 [[N]], 0250; ATTRIBUTOR-NEXT:    call void @llvm.assume(i1 [[CMP]]) #[[ATTR13:[0-9]+]]251; ATTRIBUTOR-NEXT:    [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]]252; ATTRIBUTOR-NEXT:    ret ptr [[B]]253;254  %cmp = icmp ne i64 %n, 0255  call void @llvm.assume(i1 %cmp)256  %b = getelementptr inbounds i8, ptr %a, i64 %n257  ret ptr %b258}259 260; TEST 11261; char* test11(char *p) {262;   return p? p: nonnull();263; }264define ptr @test11(ptr) local_unnamed_addr {265; FNATTRS-LABEL: define nonnull ptr @test11(266; FNATTRS-SAME: ptr readnone captures(address_is_null, ret: address, provenance) [[TMP0:%.*]]) local_unnamed_addr {267; FNATTRS-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null268; FNATTRS-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]269; FNATTRS:       3:270; FNATTRS-NEXT:    [[TMP4:%.*]] = tail call ptr @ret_nonnull()271; FNATTRS-NEXT:    br label [[TMP5]]272; FNATTRS:       5:273; FNATTRS-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]274; FNATTRS-NEXT:    ret ptr [[TMP6]]275;276; ATTRIBUTOR-LABEL: define nonnull ptr @test11(277; ATTRIBUTOR-SAME: ptr [[TMP0:%.*]]) local_unnamed_addr {278; ATTRIBUTOR-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null279; ATTRIBUTOR-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]]280; ATTRIBUTOR:       3:281; ATTRIBUTOR-NEXT:    [[TMP4:%.*]] = tail call ptr @ret_nonnull()282; ATTRIBUTOR-NEXT:    br label [[TMP5]]283; ATTRIBUTOR:       5:284; ATTRIBUTOR-NEXT:    [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ]285; ATTRIBUTOR-NEXT:    ret ptr [[TMP6]]286;287  %2 = icmp eq ptr %0, null288  br i1 %2, label %3, label %5289 290; <label>:3:                                      ; preds = %1291  %4 = tail call ptr @ret_nonnull()292  br label %5293 294; <label>:5:                                      ; preds = %3, %1295  %6 = phi ptr [ %4, %3 ], [ %0, %1 ]296  ret ptr %6297}298 299; TEST 12300; Simple CallSite Test301declare void @test12_helper(ptr)302define void @test12(ptr nonnull %a) {303; COMMON-LABEL: define void @test12(304; COMMON-SAME: ptr nonnull [[A:%.*]]) {305; COMMON-NEXT:    tail call void @test12_helper(ptr [[A]])306; COMMON-NEXT:    ret void307;308  tail call void @test12_helper(ptr %a)309  ret void310}311 312; TEST 13313; Simple Argument Tests314declare ptr @unknown()315define void @test13_helper() {316; FNATTRS-LABEL: define void @test13_helper() {317; FNATTRS-NEXT:    [[NONNULLPTR:%.*]] = tail call ptr @ret_nonnull()318; FNATTRS-NEXT:    [[MAYBENULLPTR:%.*]] = tail call ptr @unknown()319; FNATTRS-NEXT:    tail call void @test13(ptr [[NONNULLPTR]], ptr [[NONNULLPTR]], ptr [[MAYBENULLPTR]])320; FNATTRS-NEXT:    tail call void @test13(ptr [[NONNULLPTR]], ptr [[MAYBENULLPTR]], ptr [[NONNULLPTR]])321; FNATTRS-NEXT:    ret void322;323; ATTRIBUTOR-LABEL: define void @test13_helper() {324; ATTRIBUTOR-NEXT:    [[NONNULLPTR:%.*]] = tail call ptr @ret_nonnull()325; ATTRIBUTOR-NEXT:    [[MAYBENULLPTR:%.*]] = tail call ptr @unknown()326; ATTRIBUTOR-NEXT:    tail call void @test13(ptr nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr nofree readnone captures(none) [[MAYBENULLPTR]])327; ATTRIBUTOR-NEXT:    tail call void @test13(ptr nofree nonnull readnone captures(none) [[NONNULLPTR]], ptr nofree readnone captures(none) [[MAYBENULLPTR]], ptr nofree nonnull readnone captures(none) [[NONNULLPTR]])328; ATTRIBUTOR-NEXT:    ret void329;330  %nonnullptr = tail call ptr @ret_nonnull()331  %maybenullptr = tail call ptr @unknown()332  tail call void @test13(ptr %nonnullptr, ptr %nonnullptr, ptr %maybenullptr)333  tail call void @test13(ptr %nonnullptr, ptr %maybenullptr, ptr %nonnullptr)334  ret void335}336define internal void @test13(ptr %a, ptr %b, ptr %c) {337; FNATTRS-LABEL: define internal void @test13(338; FNATTRS-SAME: ptr readnone captures(none) [[A:%.*]], ptr readnone captures(none) [[B:%.*]], ptr readnone captures(none) [[C:%.*]]) #[[ATTR0]] {339; FNATTRS-NEXT:    ret void340;341; ATTRIBUTOR-LABEL: define internal void @test13(342; ATTRIBUTOR-SAME: ptr nofree nonnull readnone captures(none) [[A:%.*]], ptr nofree readnone captures(none) [[B:%.*]], ptr nofree readnone captures(none) [[C:%.*]]) #[[ATTR0]] {343; ATTRIBUTOR-NEXT:    ret void344;345  ret void346}347 348declare nonnull ptr @nonnull()349 350; TEST 14351; Complex propagation352; Argument of f1, f2, f3 can be marked with nonnull.353 354; * Argument355; 1. In f1:bb6, %arg can be marked with nonnull because of the comparison in bb1356; 2. Because f2 is internal function, f2(ptr %arg) -> @f2(ptr nonnull %arg)357; 3. In f1:bb4 %tmp5 is nonnull and f3 is internal function.358;    Then, f3(ptr %arg) -> @f3(ptr nonnull %arg)359; 4. We get nonnull in whole f1 call sites so f1(ptr %arg) -> @f1(ptr nonnull %arg)360 361 362define internal ptr @f1(ptr %arg) {363; FNATTRS-LABEL: define internal nonnull ptr @f1(364; FNATTRS-SAME: ptr readonly captures(address_is_null) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {365; FNATTRS-NEXT:  bb:366; FNATTRS-NEXT:    [[TMP:%.*]] = icmp eq ptr [[ARG]], null367; FNATTRS-NEXT:    br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]]368; FNATTRS:       bb1:369; FNATTRS-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4370; FNATTRS-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0371; FNATTRS-NEXT:    br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]]372; FNATTRS:       bb4:373; FNATTRS-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1374; FNATTRS-NEXT:    [[TMP5B:%.*]] = tail call ptr @f3(ptr [[TMP5]])375; FNATTRS-NEXT:    [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1376; FNATTRS-NEXT:    br label [[BB9]]377; FNATTRS:       bb6:378; FNATTRS-NEXT:    [[TMP7:%.*]] = tail call ptr @f2(ptr [[ARG]])379; FNATTRS-NEXT:    ret ptr [[TMP7]]380; FNATTRS:       bb9:381; FNATTRS-NEXT:    [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ]382; FNATTRS-NEXT:    ret ptr [[TMP10]]383;384; ATTRIBUTOR-LABEL: define internal ptr @f1(385; ATTRIBUTOR-SAME: ptr nofree nonnull readonly [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {386; ATTRIBUTOR-NEXT:  bb:387; ATTRIBUTOR-NEXT:    [[TMP:%.*]] = icmp eq ptr [[ARG]], null388; ATTRIBUTOR-NEXT:    br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]]389; ATTRIBUTOR:       bb1:390; ATTRIBUTOR-NEXT:    [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4391; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0392; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]]393; ATTRIBUTOR:       bb4:394; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1395; ATTRIBUTOR-NEXT:    [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TMP5]]) #[[ATTR14:[0-9]+]]396; ATTRIBUTOR-NEXT:    [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1397; ATTRIBUTOR-NEXT:    br label [[BB9]]398; ATTRIBUTOR:       bb6:399; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly [[ARG]]) #[[ATTR14]]400; ATTRIBUTOR-NEXT:    ret ptr [[TMP7]]401; ATTRIBUTOR:       bb9:402; ATTRIBUTOR-NEXT:    [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ]403; ATTRIBUTOR-NEXT:    ret ptr [[TMP10]]404;405bb:406  %tmp = icmp eq ptr %arg, null407  br i1 %tmp, label %bb9, label %bb1408 409bb1:                                              ; preds = %bb410  %tmp2 = load i32, ptr %arg, align 4411  %tmp3 = icmp eq i32 %tmp2, 0412  br i1 %tmp3, label %bb6, label %bb4413 414bb4:                                              ; preds = %bb1415  %tmp5 = getelementptr inbounds i32, ptr %arg, i64 1416  %tmp5b = tail call ptr @f3(ptr %tmp5)417  %tmp5c = getelementptr inbounds i32, ptr %tmp5b, i64 -1418  br label %bb9419 420bb6:                                              ; preds = %bb1421; FIXME: missing nonnull. It should be @f2(ptr nonnull %arg)422  %tmp7 = tail call ptr @f2(ptr %arg)423  ret ptr %tmp7424 425bb9:                                              ; preds = %bb4, %bb426  %tmp10 = phi ptr [ %tmp5c, %bb4 ], [ inttoptr (i64 4 to ptr), %bb ]427  ret ptr %tmp10428}429 430define internal ptr @f2(ptr %arg) {431; FIXME: missing nonnull. It should be nonnull @f2(ptr nonnull %arg)432; FNATTRS-LABEL: define internal nonnull ptr @f2(433; FNATTRS-SAME: ptr readonly captures(address_is_null) [[ARG:%.*]]) #[[ATTR4]] {434; FNATTRS-NEXT:  bb:435; FNATTRS-NEXT:    [[TMP:%.*]] = tail call ptr @f1(ptr [[ARG]])436; FNATTRS-NEXT:    ret ptr [[TMP]]437;438; ATTRIBUTOR-LABEL: define internal ptr @f2(439; ATTRIBUTOR-SAME: ptr nofree nonnull readonly [[ARG:%.*]]) #[[ATTR4]] {440; ATTRIBUTOR-NEXT:  bb:441; ATTRIBUTOR-NEXT:    [[TMP:%.*]] = tail call ptr @f1(ptr nofree nonnull readonly [[ARG]]) #[[ATTR14]]442; ATTRIBUTOR-NEXT:    ret ptr [[TMP]]443;444bb:445 446; FIXME: missing nonnull. It should be @f1(ptr nonnull readonly %arg)447  %tmp = tail call ptr @f1(ptr %arg)448  ret ptr %tmp449}450 451define dso_local noalias ptr @f3(ptr %arg) {452; FIXME: missing nonnull. It should be nonnull @f3(ptr nonnull readonly %arg)453; FNATTRS-LABEL: define dso_local noalias nonnull ptr @f3(454; FNATTRS-SAME: ptr readonly captures(address_is_null) [[ARG:%.*]]) #[[ATTR4]] {455; FNATTRS-NEXT:  bb:456; FNATTRS-NEXT:    [[TMP:%.*]] = call ptr @f1(ptr [[ARG]])457; FNATTRS-NEXT:    ret ptr [[TMP]]458;459; ATTRIBUTOR-LABEL: define dso_local noalias ptr @f3(460; ATTRIBUTOR-SAME: ptr nofree readonly [[ARG:%.*]]) #[[ATTR4]] {461; ATTRIBUTOR-NEXT:  bb:462; ATTRIBUTOR-NEXT:    [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR14]]463; ATTRIBUTOR-NEXT:    ret ptr [[TMP]]464;465bb:466; FIXME: missing nonnull. It should be @f1(ptr nonnull readonly %arg)467  %tmp = call ptr @f1(ptr %arg)468  ret ptr %tmp469}470 471; TEST 15472define void @f15(ptr %arg) {473; FNATTRS-LABEL: define void @f15(474; FNATTRS-SAME: ptr [[ARG:%.*]]) {475; FNATTRS-NEXT:    tail call void @use1(ptr dereferenceable(4) [[ARG]])476; FNATTRS-NEXT:    ret void477;478; ATTRIBUTOR-LABEL: define void @f15(479; ATTRIBUTOR-SAME: ptr nonnull [[ARG:%.*]]) {480; ATTRIBUTOR-NEXT:    tail call void @use1(ptr nonnull dereferenceable(4) [[ARG]])481; ATTRIBUTOR-NEXT:    ret void482;483  tail call void @use1(ptr dereferenceable(4) %arg)484  ret void485}486 487declare void @fun0() #1488declare void @fun1(ptr) #1489declare void @fun2(ptr, ptr) #1490declare void @fun3(ptr, ptr, ptr) #1491; TEST 16 simple path test492; if(..)493;   fun2(nonnull %a, nonnull %b)494; else495;   fun2(nonnull %a, %b)496; We can say that %a is nonnull but %b is not.497define void @f16(ptr %a, ptr %b, i8 %c) {498; FIXME: missing nonnull on %a499; FNATTRS-LABEL: define void @f16(500; FNATTRS-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR6:[0-9]+]] {501; FNATTRS-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0502; FNATTRS-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]503; FNATTRS:       if.then:504; FNATTRS-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]])505; FNATTRS-NEXT:    ret void506; FNATTRS:       if.else:507; FNATTRS-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr [[B]])508; FNATTRS-NEXT:    ret void509;510; ATTRIBUTOR-LABEL: define void @f16(511; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR6:[0-9]+]] {512; ATTRIBUTOR-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0513; ATTRIBUTOR-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]514; ATTRIBUTOR:       if.then:515; ATTRIBUTOR-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR15:[0-9]+]]516; ATTRIBUTOR-NEXT:    ret void517; ATTRIBUTOR:       if.else:518; ATTRIBUTOR-NEXT:    tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR15]]519; ATTRIBUTOR-NEXT:    ret void520;521  %cmp = icmp eq i8 %c, 0522  br i1 %cmp, label %if.then, label %if.else523if.then:524  tail call void @fun2(ptr nonnull %a, ptr nonnull %b)525  ret void526if.else:527  tail call void @fun2(ptr nonnull %a, ptr %b)528  ret void529}530; TEST 17 explore child BB test531; if(..)532;    ... (willreturn & nounwind)533; else534;    ... (willreturn & nounwind)535; fun1(nonnull %a)536; We can say that %a is nonnull537define void @f17(ptr %a, i8 %c) {538; FNATTRS-LABEL: define void @f17(539; FNATTRS-SAME: ptr [[A:%.*]], i8 [[C:%.*]]) #[[ATTR6]] {540; FNATTRS-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0541; FNATTRS-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]542; FNATTRS:       if.then:543; FNATTRS-NEXT:    tail call void @fun0()544; FNATTRS-NEXT:    br label [[CONT:%.*]]545; FNATTRS:       if.else:546; FNATTRS-NEXT:    tail call void @fun0()547; FNATTRS-NEXT:    br label [[CONT]]548; FNATTRS:       cont:549; FNATTRS-NEXT:    tail call void @fun1(ptr nonnull [[A]])550; FNATTRS-NEXT:    ret void551;552; ATTRIBUTOR-LABEL: define void @f17(553; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], i8 [[C:%.*]]) #[[ATTR6]] {554; ATTRIBUTOR-NEXT:    [[CMP:%.*]] = icmp eq i8 [[C]], 0555; ATTRIBUTOR-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]556; ATTRIBUTOR:       if.then:557; ATTRIBUTOR-NEXT:    tail call void @fun0() #[[ATTR15]]558; ATTRIBUTOR-NEXT:    br label [[CONT:%.*]]559; ATTRIBUTOR:       if.else:560; ATTRIBUTOR-NEXT:    tail call void @fun0() #[[ATTR15]]561; ATTRIBUTOR-NEXT:    br label [[CONT]]562; ATTRIBUTOR:       cont:563; ATTRIBUTOR-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR15]]564; ATTRIBUTOR-NEXT:    ret void565;566  %cmp = icmp eq i8 %c, 0567  br i1 %cmp, label %if.then, label %if.else568if.then:569  tail call void @fun0()570  br label %cont571if.else:572  tail call void @fun0()573  br label %cont574cont:575  tail call void @fun1(ptr nonnull %a)576  ret void577}578; TEST 18 More complex test579; if(..)580;    ... (willreturn & nounwind)581; else582;    ... (willreturn & nounwind)583; if(..)584;    ... (willreturn & nounwind)585; else586;    ... (willreturn & nounwind)587; fun1(nonnull %a)588 589define void @f18(ptr %a, ptr %b, i8 %c) {590; FNATTRS-LABEL: define void @f18(591; FNATTRS-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR6]] {592; FNATTRS-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[C]], 0593; FNATTRS-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]594; FNATTRS:       if.then:595; FNATTRS-NEXT:    tail call void @fun0()596; FNATTRS-NEXT:    br label [[CONT:%.*]]597; FNATTRS:       if.else:598; FNATTRS-NEXT:    tail call void @fun0()599; FNATTRS-NEXT:    br label [[CONT]]600; FNATTRS:       cont:601; FNATTRS-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 1602; FNATTRS-NEXT:    br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]603; FNATTRS:       cont.then:604; FNATTRS-NEXT:    tail call void @fun1(ptr nonnull [[B]])605; FNATTRS-NEXT:    br label [[CONT2:%.*]]606; FNATTRS:       cont.else:607; FNATTRS-NEXT:    tail call void @fun0()608; FNATTRS-NEXT:    br label [[CONT2]]609; FNATTRS:       cont2:610; FNATTRS-NEXT:    tail call void @fun1(ptr nonnull [[A]])611; FNATTRS-NEXT:    ret void612;613; ATTRIBUTOR-LABEL: define void @f18(614; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR6]] {615; ATTRIBUTOR-NEXT:    [[CMP1:%.*]] = icmp eq i8 [[C]], 0616; ATTRIBUTOR-NEXT:    br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]617; ATTRIBUTOR:       if.then:618; ATTRIBUTOR-NEXT:    tail call void @fun0() #[[ATTR15]]619; ATTRIBUTOR-NEXT:    br label [[CONT:%.*]]620; ATTRIBUTOR:       if.else:621; ATTRIBUTOR-NEXT:    tail call void @fun0() #[[ATTR15]]622; ATTRIBUTOR-NEXT:    br label [[CONT]]623; ATTRIBUTOR:       cont:624; ATTRIBUTOR-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 1625; ATTRIBUTOR-NEXT:    br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]]626; ATTRIBUTOR:       cont.then:627; ATTRIBUTOR-NEXT:    tail call void @fun1(ptr nonnull [[B]]) #[[ATTR15]]628; ATTRIBUTOR-NEXT:    br label [[CONT2:%.*]]629; ATTRIBUTOR:       cont.else:630; ATTRIBUTOR-NEXT:    tail call void @fun0() #[[ATTR15]]631; ATTRIBUTOR-NEXT:    br label [[CONT2]]632; ATTRIBUTOR:       cont2:633; ATTRIBUTOR-NEXT:    tail call void @fun1(ptr nonnull [[A]]) #[[ATTR15]]634; ATTRIBUTOR-NEXT:    ret void635;636  %cmp1 = icmp eq i8 %c, 0637  br i1 %cmp1, label %if.then, label %if.else638if.then:639  tail call void @fun0()640  br label %cont641if.else:642  tail call void @fun0()643  br label %cont644cont:645  %cmp2 = icmp eq i8 %c, 1646  br i1 %cmp2, label %cont.then, label %cont.else647cont.then:648  tail call void @fun1(ptr nonnull %b)649  br label %cont2650cont.else:651  tail call void @fun0()652  br label %cont2653cont2:654  tail call void @fun1(ptr nonnull %a)655  ret void656}657 658; TEST 19: Loop659 660define void @f19(ptr %a, ptr %b, i8 %c) {661; FIXME: missing nonnull on %b662; FNATTRS-LABEL: define void @f19(663; FNATTRS-SAME: ptr [[A:%.*]], ptr [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7:[0-9]+]] {664; FNATTRS-NEXT:    br label [[LOOP_HEADER:%.*]]665; FNATTRS:       loop.header:666; FNATTRS-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 0667; FNATTRS-NEXT:    br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]668; FNATTRS:       loop.body:669; FNATTRS-NEXT:    tail call void @fun1(ptr nonnull [[B]])670; FNATTRS-NEXT:    tail call void @fun1(ptr nonnull [[A]])671; FNATTRS-NEXT:    br label [[LOOP_HEADER]]672; FNATTRS:       loop.exit:673; FNATTRS-NEXT:    tail call void @fun1(ptr nonnull [[B]])674; FNATTRS-NEXT:    ret void675;676; ATTRIBUTOR-LABEL: define void @f19(677; ATTRIBUTOR-SAME: ptr [[A:%.*]], ptr nonnull [[B:%.*]], i8 [[C:%.*]]) #[[ATTR7:[0-9]+]] {678; ATTRIBUTOR-NEXT:    br label [[LOOP_HEADER:%.*]]679; ATTRIBUTOR:       loop.header:680; ATTRIBUTOR-NEXT:    [[CMP2:%.*]] = icmp eq i8 [[C]], 0681; ATTRIBUTOR-NEXT:    br i1 [[CMP2]], label [[LOOP_BODY:%.*]], label [[LOOP_EXIT:%.*]]682; ATTRIBUTOR:       loop.body:683; ATTRIBUTOR-NEXT:    tail call void @fun1(ptr nonnull [[B]])684; ATTRIBUTOR-NEXT:    tail call void @fun1(ptr nonnull [[A]])685; ATTRIBUTOR-NEXT:    br label [[LOOP_HEADER]]686; ATTRIBUTOR:       loop.exit:687; ATTRIBUTOR-NEXT:    tail call void @fun1(ptr nonnull [[B]])688; ATTRIBUTOR-NEXT:    ret void689;690  br label %loop.header691loop.header:692  %cmp2 = icmp eq i8 %c, 0693  br i1 %cmp2, label %loop.body, label %loop.exit694loop.body:695  tail call void @fun1(ptr nonnull %b)696  tail call void @fun1(ptr nonnull %a)697  br label %loop.header698loop.exit:699  tail call void @fun1(ptr nonnull %b)700  ret void701}702 703; Test propagation of nonnull callsite args back to caller.704 705declare void @use1(ptr %x)706declare void @use2(ptr %x, ptr %y);707declare void @use3(ptr %x, ptr %y, ptr %z);708 709declare void @use1nonnull(ptr nonnull noundef %x);710declare void @use1nonnull_without_noundef(ptr nonnull %x);711declare void @use2nonnull(ptr nonnull noundef %x, ptr nonnull noundef %y);712declare void @use3nonnull(ptr nonnull noundef %x, ptr nonnull noundef %y, ptr nonnull noundef %z);713 714declare i8 @use1safecall(ptr %x) nounwind willreturn ; nounwind+willreturn guarantees that execution continues to successor715 716; Without noundef, nonnull cannot be propagated to the parent717 718define void @parent_poison(ptr %a) {719; FNATTR-LABEL: @parent_poison(ptr %a)720; FNATTRS-LABEL: define void @parent_poison(721; FNATTRS-SAME: ptr [[A:%.*]]) {722; FNATTRS-NEXT:    call void @use1nonnull_without_noundef(ptr [[A]])723; FNATTRS-NEXT:    ret void724;725; ATTRIBUTOR-LABEL: define void @parent_poison(726; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]]) {727; ATTRIBUTOR-NEXT:    call void @use1nonnull_without_noundef(ptr nonnull [[A]])728; ATTRIBUTOR-NEXT:    ret void729;730  call void @use1nonnull_without_noundef(ptr %a)731  ret void732}733 734; Can't extend non-null to parent for any argument because the 2nd call is not guaranteed to execute.735 736define void @parent1(ptr %a, ptr %b, ptr %c) {737; COMMON-LABEL: define void @parent1(738; COMMON-SAME: ptr [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {739; COMMON-NEXT:    call void @use3(ptr [[C]], ptr [[A]], ptr [[B]])740; COMMON-NEXT:    call void @use3nonnull(ptr [[B]], ptr [[C]], ptr [[A]])741; COMMON-NEXT:    ret void742;743  call void @use3(ptr %c, ptr %a, ptr %b)744  call void @use3nonnull(ptr %b, ptr %c, ptr %a)745  ret void746}747 748; Extend non-null to parent for all arguments.749 750define void @parent2(ptr %a, ptr %b, ptr %c) {751; FNATTRS-LABEL: define void @parent2(752; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {753; FNATTRS-NEXT:    call void @use3nonnull(ptr [[B]], ptr [[C]], ptr [[A]])754; FNATTRS-NEXT:    call void @use3(ptr [[C]], ptr [[A]], ptr [[B]])755; FNATTRS-NEXT:    ret void756;757; ATTRIBUTOR-LABEL: define void @parent2(758; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {759; ATTRIBUTOR-NEXT:    call void @use3nonnull(ptr nonnull [[B]], ptr nonnull [[C]], ptr nonnull [[A]])760; ATTRIBUTOR-NEXT:    call void @use3(ptr [[C]], ptr [[A]], ptr [[B]])761; ATTRIBUTOR-NEXT:    ret void762;763 764 765  call void @use3nonnull(ptr %b, ptr %c, ptr %a)766  call void @use3(ptr %c, ptr %a, ptr %b)767  ret void768}769 770; Extend non-null to parent for 1st argument.771 772define void @parent3(ptr %a, ptr %b, ptr %c) {773; FNATTRS-LABEL: define void @parent3(774; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {775; FNATTRS-NEXT:    call void @use1nonnull(ptr [[A]])776; FNATTRS-NEXT:    call void @use3(ptr [[C]], ptr [[B]], ptr [[A]])777; FNATTRS-NEXT:    ret void778;779; ATTRIBUTOR-LABEL: define void @parent3(780; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr [[B:%.*]], ptr [[C:%.*]]) {781; ATTRIBUTOR-NEXT:    call void @use1nonnull(ptr nonnull [[A]])782; ATTRIBUTOR-NEXT:    call void @use3(ptr [[C]], ptr [[B]], ptr [[A]])783; ATTRIBUTOR-NEXT:    ret void784;785 786 787 788  call void @use1nonnull(ptr %a)789  call void @use3(ptr %c, ptr %b, ptr %a)790  ret void791}792 793; Extend non-null to parent for last 2 arguments.794 795define void @parent4(ptr %a, ptr %b, ptr %c) {796; CHECK-LABEL: @parent4(ptr %a, ptr nonnull %b, ptr nonnull %c)797; CHECK-NEXT:    call void @use2nonnull(ptr %c, ptr %b)798; CHECK-NEXT:    call void @use2(ptr %a, ptr %c)799; CHECK-NEXT:    call void @use1(ptr %b)800; FNATTRS-LABEL: define void @parent4(801; FNATTRS-SAME: ptr [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {802; FNATTRS-NEXT:    call void @use2nonnull(ptr [[C]], ptr [[B]])803; FNATTRS-NEXT:    call void @use2(ptr [[A]], ptr [[C]])804; FNATTRS-NEXT:    call void @use1(ptr [[B]])805; FNATTRS-NEXT:    ret void806;807; ATTRIBUTOR-LABEL: define void @parent4(808; ATTRIBUTOR-SAME: ptr [[A:%.*]], ptr nonnull [[B:%.*]], ptr nonnull [[C:%.*]]) {809; ATTRIBUTOR-NEXT:    call void @use2nonnull(ptr nonnull [[C]], ptr nonnull [[B]])810; ATTRIBUTOR-NEXT:    call void @use2(ptr [[A]], ptr [[C]])811; ATTRIBUTOR-NEXT:    call void @use1(ptr [[B]])812; ATTRIBUTOR-NEXT:    ret void813;814 815  call void @use2nonnull(ptr %c, ptr %b)816  call void @use2(ptr %a, ptr %c)817  call void @use1(ptr %b)818  ret void819}820 821; The callsite must execute in order for the attribute to transfer to the parent.822; It appears benign to extend non-null to the parent in this case, but we can't do that823; because it would incorrectly propagate the wrong information to its callers.824 825define void @parent5(ptr %a, i1 %a_is_notnull) {826; FNATTRS-LABEL: define void @parent5(827; FNATTRS-SAME: ptr [[A:%.*]], i1 [[A_IS_NOTNULL:%.*]]) {828; FNATTRS-NEXT:    br i1 [[A_IS_NOTNULL]], label [[T:%.*]], label [[F:%.*]]829; FNATTRS:       t:830; FNATTRS-NEXT:    call void @use1nonnull(ptr [[A]])831; FNATTRS-NEXT:    ret void832; FNATTRS:       f:833; FNATTRS-NEXT:    ret void834;835; ATTRIBUTOR-LABEL: define void @parent5(836; ATTRIBUTOR-SAME: ptr [[A:%.*]], i1 [[A_IS_NOTNULL:%.*]]) {837; ATTRIBUTOR-NEXT:    br i1 [[A_IS_NOTNULL]], label [[T:%.*]], label [[F:%.*]]838; ATTRIBUTOR:       t:839; ATTRIBUTOR-NEXT:    call void @use1nonnull(ptr nonnull [[A]])840; ATTRIBUTOR-NEXT:    ret void841; ATTRIBUTOR:       f:842; ATTRIBUTOR-NEXT:    ret void843;844 845  br i1 %a_is_notnull, label %t, label %f846t:847  call void @use1nonnull(ptr %a)848  ret void849f:850  ret void851}852 853; The callsite must execute in order for the attribute to transfer to the parent.854; The volatile load can't trap, so we can guarantee that we'll get to the call.855 856define i8 @parent6(ptr %a, ptr %b) {857; FNATTRS-LABEL: define i8 @parent6(858; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr [[B:%.*]]) {859; FNATTRS-NEXT:    [[C:%.*]] = load volatile i8, ptr [[B]], align 1860; FNATTRS-NEXT:    call void @use1nonnull(ptr [[A]])861; FNATTRS-NEXT:    ret i8 [[C]]862;863; ATTRIBUTOR-LABEL: define i8 @parent6(864; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nofree [[B:%.*]]) {865; ATTRIBUTOR-NEXT:    [[C:%.*]] = load volatile i8, ptr [[B]], align 1866; ATTRIBUTOR-NEXT:    call void @use1nonnull(ptr nonnull [[A]])867; ATTRIBUTOR-NEXT:    ret i8 [[C]]868;869 870  %c = load volatile i8, ptr %b871  call void @use1nonnull(ptr %a)872  ret i8 %c873}874 875; The nonnull callsite is guaranteed to execute, so the argument must be nonnull throughout the parent.876 877define i8 @parent7(ptr %a) {878; FNATTRS-LABEL: define i8 @parent7(879; FNATTRS-SAME: ptr nonnull [[A:%.*]]) {880; FNATTRS-NEXT:    [[RET:%.*]] = call i8 @use1safecall(ptr [[A]])881; FNATTRS-NEXT:    call void @use1nonnull(ptr [[A]])882; FNATTRS-NEXT:    ret i8 [[RET]]883;884; ATTRIBUTOR-LABEL: define i8 @parent7(885; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]]) {886; ATTRIBUTOR-NEXT:    [[RET:%.*]] = call i8 @use1safecall(ptr nonnull [[A]]) #[[ATTR15]]887; ATTRIBUTOR-NEXT:    call void @use1nonnull(ptr nonnull [[A]])888; ATTRIBUTOR-NEXT:    ret i8 [[RET]]889;890 891 892 893 894  %ret = call i8 @use1safecall(ptr %a)895  call void @use1nonnull(ptr %a)896  ret i8 %ret897}898 899; Make sure that an invoke works similarly to a call.900 901declare i32 @esfp(...)902 903define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{904; FNATTRS-LABEL: define noundef i1 @parent8(905; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR7]] personality ptr @esfp {906; FNATTRS-NEXT:  entry:907; FNATTRS-NEXT:    invoke void @use2nonnull(ptr [[A]], ptr [[B]])908; FNATTRS-NEXT:            to label [[CONT:%.*]] unwind label [[EXC:%.*]]909; FNATTRS:       cont:910; FNATTRS-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[B]], null911; FNATTRS-NEXT:    ret i1 [[NULL_CHECK]]912; FNATTRS:       exc:913; FNATTRS-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }914; FNATTRS-NEXT:            filter [0 x ptr] zeroinitializer915; FNATTRS-NEXT:    unreachable916;917; ATTRIBUTOR-LABEL: define i1 @parent8(918; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nofree readnone captures(none) [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR7]] personality ptr @esfp {919; ATTRIBUTOR-NEXT:  entry:920; ATTRIBUTOR-NEXT:    invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]])921; ATTRIBUTOR-NEXT:            to label [[CONT:%.*]] unwind label [[EXC:%.*]]922; ATTRIBUTOR:       cont:923; ATTRIBUTOR-NEXT:    [[NULL_CHECK:%.*]] = icmp eq ptr [[B]], null924; ATTRIBUTOR-NEXT:    ret i1 [[NULL_CHECK]]925; ATTRIBUTOR:       exc:926; ATTRIBUTOR-NEXT:    [[LP:%.*]] = landingpad { ptr, i32 }927; ATTRIBUTOR-NEXT:            filter [0 x ptr] zeroinitializer928; ATTRIBUTOR-NEXT:    unreachable929;930 931entry:932  invoke void @use2nonnull(ptr %a, ptr %b)933  to label %cont unwind label %exc934 935cont:936  %null_check = icmp eq ptr %b, null937  ret i1 %null_check938 939exc:940  %lp = landingpad { ptr, i32 }941  filter [0 x ptr] zeroinitializer942  unreachable943}944 945define ptr @gep1(ptr %p) {946; FNATTRS-LABEL: define nonnull ptr @gep1(947; FNATTRS-SAME: ptr readnone captures(ret: address, provenance) [[P:%.*]]) #[[ATTR0]] {948; FNATTRS-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1949; FNATTRS-NEXT:    ret ptr [[Q]]950;951; ATTRIBUTOR-LABEL: define nonnull ptr @gep1(952; ATTRIBUTOR-SAME: ptr nofree readnone [[P:%.*]]) #[[ATTR0]] {953; ATTRIBUTOR-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1954; ATTRIBUTOR-NEXT:    ret ptr [[Q]]955;956  %q = getelementptr inbounds i32, ptr %p, i32 1957  ret ptr %q958}959 960define ptr @gep1_no_null_opt(ptr %p) #0 {961; Should't be able to derive nonnull based on gep.962; FNATTRS-LABEL: define ptr @gep1_no_null_opt(963; FNATTRS-SAME: ptr readnone captures(ret: address, provenance) [[P:%.*]]) #[[ATTR8:[0-9]+]] {964; FNATTRS-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1965; FNATTRS-NEXT:    ret ptr [[Q]]966;967; ATTRIBUTOR-LABEL: define ptr @gep1_no_null_opt(968; ATTRIBUTOR-SAME: ptr nofree readnone [[P:%.*]]) #[[ATTR8:[0-9]+]] {969; ATTRIBUTOR-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1970; ATTRIBUTOR-NEXT:    ret ptr [[Q]]971;972  %q = getelementptr inbounds i32, ptr %p, i32 1973  ret ptr %q974}975 976define ptr addrspace(3) @gep2(ptr addrspace(3) %p) {977; FNATTRS-LABEL: define ptr addrspace(3) @gep2(978; FNATTRS-SAME: ptr addrspace(3) readnone captures(ret: address, provenance) [[P:%.*]]) #[[ATTR0]] {979; FNATTRS-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[P]], i32 1980; FNATTRS-NEXT:    ret ptr addrspace(3) [[Q]]981;982; ATTRIBUTOR-LABEL: define ptr addrspace(3) @gep2(983; ATTRIBUTOR-SAME: ptr addrspace(3) nofree readnone [[P:%.*]]) #[[ATTR0]] {984; ATTRIBUTOR-NEXT:    [[Q:%.*]] = getelementptr inbounds i32, ptr addrspace(3) [[P]], i32 1985; ATTRIBUTOR-NEXT:    ret ptr addrspace(3) [[Q]]986;987  %q = getelementptr inbounds i32, ptr addrspace(3) %p, i32 1988  ret ptr addrspace(3) %q989}990 991; FIXME: We should propagate dereferenceable here but *not* nonnull992define ptr addrspace(3) @as(ptr addrspace(3) dereferenceable(4) %p) {993; FNATTRS-LABEL: define noundef ptr addrspace(3) @as(994; FNATTRS-SAME: ptr addrspace(3) readnone returned captures(ret: address, provenance) dereferenceable(4) [[P:%.*]]) #[[ATTR0]] {995; FNATTRS-NEXT:    ret ptr addrspace(3) [[P]]996;997; ATTRIBUTOR-LABEL: define ptr addrspace(3) @as(998; ATTRIBUTOR-SAME: ptr addrspace(3) nofree readnone dereferenceable(4) [[P:%.*]]) #[[ATTR0]] {999; ATTRIBUTOR-NEXT:    ret ptr addrspace(3) [[P]]1000;1001  ret ptr addrspace(3) %p1002}1003 1004define internal ptr @g2() {1005; FNATTRS-LABEL: define internal noundef nonnull ptr @g2(1006; FNATTRS-SAME: ) #[[ATTR0]] {1007; FNATTRS-NEXT:    ret ptr inttoptr (i64 4 to ptr)1008;1009; ATTRIBUTOR-LABEL: define internal nonnull ptr @g2(1010; ATTRIBUTOR-SAME: ) #[[ATTR0]] {1011; ATTRIBUTOR-NEXT:    ret ptr inttoptr (i64 4 to ptr)1012;1013  ret ptr inttoptr (i64 4 to ptr)1014}1015 1016define  ptr @g1() {1017; FNATTRS-LABEL: define noundef nonnull ptr @g1(1018; FNATTRS-SAME: ) #[[ATTR0]] {1019; FNATTRS-NEXT:    [[C:%.*]] = call ptr @g2()1020; FNATTRS-NEXT:    ret ptr [[C]]1021;1022; ATTRIBUTOR-LABEL: define ptr @g1(1023; ATTRIBUTOR-SAME: ) #[[ATTR0]] {1024; ATTRIBUTOR-NEXT:    [[C:%.*]] = call ptr @g2() #[[ATTR16:[0-9]+]]1025; ATTRIBUTOR-NEXT:    ret ptr [[C]]1026;1027  %c = call ptr @g2()1028  ret ptr %c1029}1030 1031declare void @use_i32_ptr(ptr) readnone nounwind willreturn1032define internal void @called_by_weak(ptr %a) {1033; FNATTRS-LABEL: define internal void @called_by_weak(1034; FNATTRS-SAME: ptr readnone captures(address) [[A:%.*]]) #[[ATTR10:[0-9]+]] {1035; FNATTRS-NEXT:    call void @use_i32_ptr(ptr [[A]])1036; FNATTRS-NEXT:    ret void1037;1038; ATTRIBUTOR-LABEL: define internal void @called_by_weak(1039; ATTRIBUTOR-SAME: ptr nonnull readnone captures(none) [[A:%.*]]) #[[ATTR10:[0-9]+]] {1040; ATTRIBUTOR-NEXT:    call void @use_i32_ptr(ptr nonnull [[A]]) #[[ATTR17:[0-9]+]]1041; ATTRIBUTOR-NEXT:    ret void1042;1043  call void @use_i32_ptr(ptr %a)1044  ret void1045}1046 1047; Check we do not annotate the function interface of this weak function.1048define weak_odr void @weak_caller(ptr nonnull %a) {1049; FNATTRS-LABEL: define weak_odr void @weak_caller(1050; FNATTRS-SAME: ptr nonnull [[A:%.*]]) {1051; FNATTRS-NEXT:    call void @called_by_weak(ptr [[A]])1052; FNATTRS-NEXT:    ret void1053;1054; ATTRIBUTOR-LABEL: define weak_odr void @weak_caller(1055; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]]) {1056; ATTRIBUTOR-NEXT:    call void @called_by_weak(ptr nonnull readnone captures(none) [[A]])1057; ATTRIBUTOR-NEXT:    ret void1058;1059  call void @called_by_weak(ptr %a)1060  ret void1061}1062 1063; Expect nonnull1064define internal void @control(ptr dereferenceable(4) %a) {1065; FNATTRS-LABEL: define internal void @control(1066; FNATTRS-SAME: ptr readnone captures(address) dereferenceable(4) [[A:%.*]]) #[[ATTR10]] {1067; FNATTRS-NEXT:    call void @use_i32_ptr(ptr [[A]])1068; FNATTRS-NEXT:    ret void1069;1070; ATTRIBUTOR-LABEL: define internal void @control(1071; ATTRIBUTOR-SAME: ptr nonnull readnone captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR10]] {1072; ATTRIBUTOR-NEXT:    call void @use_i32_ptr(ptr [[A]]) #[[ATTR17]]1073; ATTRIBUTOR-NEXT:    ret void1074;1075  call void @use_i32_ptr(ptr %a)1076  ret void1077}1078; Avoid nonnull as we do not touch naked functions1079define internal void @naked(ptr dereferenceable(4) %a) naked {1080; FNATTRS-LABEL: define internal void @naked(1081; FNATTRS-SAME: ptr dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {1082; FNATTRS-NEXT:    ret void1083;1084; ATTRIBUTOR-LABEL: define internal void @naked(1085; ATTRIBUTOR-SAME: ptr nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR11:[0-9]+]] {1086; ATTRIBUTOR-NEXT:    ret void1087;1088  ret void1089}1090; Avoid nonnull as we do not touch optnone1091define internal void @optnone(ptr dereferenceable(4) %a) optnone noinline {1092; FNATTRS-LABEL: define internal void @optnone(1093; FNATTRS-SAME: ptr dereferenceable(4) [[A:%.*]]) #[[ATTR12:[0-9]+]] {1094; FNATTRS-NEXT:    call void @use_i32_ptr(ptr [[A]])1095; FNATTRS-NEXT:    ret void1096;1097; ATTRIBUTOR-LABEL: define internal void @optnone(1098; ATTRIBUTOR-SAME: ptr nonnull dereferenceable(4) [[A:%.*]]) #[[ATTR12:[0-9]+]] {1099; ATTRIBUTOR-NEXT:    call void @use_i32_ptr(ptr [[A]])1100; ATTRIBUTOR-NEXT:    ret void1101;1102  call void @use_i32_ptr(ptr %a)1103  ret void1104}1105define void @make_live(ptr nonnull dereferenceable(8) %a) {1106; FNATTRS-LABEL: define void @make_live(1107; FNATTRS-SAME: ptr nonnull dereferenceable(8) [[A:%.*]]) {1108; FNATTRS-NEXT:    call void @naked(ptr nonnull align 16 dereferenceable(8) [[A]])1109; FNATTRS-NEXT:    call void @control(ptr nonnull align 16 dereferenceable(8) [[A]])1110; FNATTRS-NEXT:    call void @optnone(ptr nonnull align 16 dereferenceable(8) [[A]])1111; FNATTRS-NEXT:    ret void1112;1113; ATTRIBUTOR-LABEL: define void @make_live(1114; ATTRIBUTOR-SAME: ptr nonnull dereferenceable(8) [[A:%.*]]) {1115; ATTRIBUTOR-NEXT:    call void @naked(ptr nonnull align 16 dereferenceable(8) [[A]])1116; ATTRIBUTOR-NEXT:    call void @control(ptr nonnull readnone align 16 captures(none) dereferenceable(8) [[A]])1117; ATTRIBUTOR-NEXT:    call void @optnone(ptr nonnull align 16 dereferenceable(8) [[A]])1118; ATTRIBUTOR-NEXT:    ret void1119;1120  call void @naked(ptr nonnull dereferenceable(8) align 16 %a)1121  call void @control(ptr nonnull dereferenceable(8) align 16 %a)1122  call void @optnone(ptr nonnull dereferenceable(8) align 16 %a)1123  ret void1124}1125 1126;int f(int *u, int n){1127;  for(int i = 0;i<n;i++){1128;    h(u);1129;  }1130;  return g(nonnull u);1131;}1132declare void @h(ptr) willreturn nounwind1133declare i32 @g(ptr) willreturn nounwind1134define i32 @nonnull_exec_ctx_1(ptr %a, i32 %b) {1135; COMMON-LABEL: define i32 @nonnull_exec_ctx_1(1136; COMMON-SAME: ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7:[0-9]+]] {1137; COMMON-NEXT:  en:1138; COMMON-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 01139; COMMON-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1140; COMMON:       ex:1141; COMMON-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]])1142; COMMON-NEXT:    ret i32 [[TMP5]]1143; COMMON:       hd:1144; COMMON-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1145; COMMON-NEXT:    tail call void @h(ptr [[A]])1146; COMMON-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 11147; COMMON-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1148; COMMON-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]1149;1150en:1151  %tmp3 = icmp eq i32 %b, 01152  br i1 %tmp3, label %ex, label %hd1153 1154ex:1155  %tmp5 = tail call i32 @g(ptr nonnull %a)1156  ret i32 %tmp51157 1158hd:1159  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]1160  tail call void @h(ptr %a)1161  %tmp8 = add nuw i32 %tmp7, 11162  %tmp9 = icmp eq i32 %tmp8, %b1163  br i1 %tmp9, label %ex, label %hd1164}1165 1166define i32 @nonnull_exec_ctx_1b(ptr %a, i32 %b) {1167; COMMON-LABEL: define i32 @nonnull_exec_ctx_1b(1168; COMMON-SAME: ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] {1169; COMMON-NEXT:  en:1170; COMMON-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 01171; COMMON-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1172; COMMON:       ex:1173; COMMON-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]])1174; COMMON-NEXT:    ret i32 [[TMP5]]1175; COMMON:       hd:1176; COMMON-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1177; COMMON-NEXT:    tail call void @h(ptr [[A]])1178; COMMON-NEXT:    br label [[HD2]]1179; COMMON:       hd2:1180; COMMON-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 11181; COMMON-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1182; COMMON-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]1183;1184en:1185  %tmp3 = icmp eq i32 %b, 01186  br i1 %tmp3, label %ex, label %hd1187 1188ex:1189  %tmp5 = tail call i32 @g(ptr nonnull %a)1190  ret i32 %tmp51191 1192hd:1193  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]1194  tail call void @h(ptr %a)1195  br label %hd21196 1197hd2:1198  %tmp8 = add nuw i32 %tmp7, 11199  %tmp9 = icmp eq i32 %tmp8, %b1200  br i1 %tmp9, label %ex, label %hd1201}1202 1203define i32 @nonnull_exec_ctx_2(ptr %a, i32 %b) willreturn nounwind {1204; FNATTRS-LABEL: define i32 @nonnull_exec_ctx_2(1205; FNATTRS-SAME: ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] {1206; FNATTRS-NEXT:  en:1207; FNATTRS-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 01208; FNATTRS-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1209; FNATTRS:       ex:1210; FNATTRS-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]])1211; FNATTRS-NEXT:    ret i32 [[TMP5]]1212; FNATTRS:       hd:1213; FNATTRS-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1214; FNATTRS-NEXT:    tail call void @h(ptr [[A]])1215; FNATTRS-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 11216; FNATTRS-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1217; FNATTRS-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]1218;1219; ATTRIBUTOR-LABEL: define i32 @nonnull_exec_ctx_2(1220; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] {1221; ATTRIBUTOR-NEXT:  en:1222; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 01223; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1224; ATTRIBUTOR:       ex:1225; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]])1226; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]1227; ATTRIBUTOR:       hd:1228; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ]1229; ATTRIBUTOR-NEXT:    tail call void @h(ptr nonnull [[A]])1230; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 11231; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1232; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]1233;1234en:1235  %tmp3 = icmp eq i32 %b, 01236  br i1 %tmp3, label %ex, label %hd1237 1238ex:1239  %tmp5 = tail call i32 @g(ptr nonnull %a)1240  ret i32 %tmp51241 1242hd:1243  %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]1244  tail call void @h(ptr %a)1245  %tmp8 = add nuw i32 %tmp7, 11246  %tmp9 = icmp eq i32 %tmp8, %b1247  br i1 %tmp9, label %ex, label %hd1248}1249 1250define i32 @nonnull_exec_ctx_2b(ptr %a, i32 %b) willreturn nounwind {1251; FNATTRS-LABEL: define i32 @nonnull_exec_ctx_2b(1252; FNATTRS-SAME: ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] {1253; FNATTRS-NEXT:  en:1254; FNATTRS-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 01255; FNATTRS-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1256; FNATTRS:       ex:1257; FNATTRS-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]])1258; FNATTRS-NEXT:    ret i32 [[TMP5]]1259; FNATTRS:       hd:1260; FNATTRS-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1261; FNATTRS-NEXT:    tail call void @h(ptr [[A]])1262; FNATTRS-NEXT:    br label [[HD2]]1263; FNATTRS:       hd2:1264; FNATTRS-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 11265; FNATTRS-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1266; FNATTRS-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]1267;1268; ATTRIBUTOR-LABEL: define i32 @nonnull_exec_ctx_2b(1269; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR6]] {1270; ATTRIBUTOR-NEXT:  en:1271; ATTRIBUTOR-NEXT:    [[TMP3:%.*]] = icmp eq i32 [[B]], 01272; ATTRIBUTOR-NEXT:    br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]]1273; ATTRIBUTOR:       ex:1274; ATTRIBUTOR-NEXT:    [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]])1275; ATTRIBUTOR-NEXT:    ret i32 [[TMP5]]1276; ATTRIBUTOR:       hd:1277; ATTRIBUTOR-NEXT:    [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ]1278; ATTRIBUTOR-NEXT:    tail call void @h(ptr nonnull [[A]])1279; ATTRIBUTOR-NEXT:    br label [[HD2]]1280; ATTRIBUTOR:       hd2:1281; ATTRIBUTOR-NEXT:    [[TMP8]] = add nuw i32 [[TMP7]], 11282; ATTRIBUTOR-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]]1283; ATTRIBUTOR-NEXT:    br i1 [[TMP9]], label [[EX]], label [[HD]]1284;1285en:1286  %tmp3 = icmp eq i32 %b, 01287  br i1 %tmp3, label %ex, label %hd1288 1289ex:1290  %tmp5 = tail call i32 @g(ptr nonnull %a)1291  ret i32 %tmp51292 1293hd:1294  %tmp7 = phi i32 [ %tmp8, %hd2 ], [ 0, %en ]1295  tail call void @h(ptr %a)1296  br label %hd21297 1298hd2:1299  %tmp8 = add nuw i32 %tmp7, 11300  %tmp9 = icmp eq i32 %tmp8, %b1301  br i1 %tmp9, label %ex, label %hd1302}1303 1304; Original from PR438331305declare void @sink(ptr)1306 1307; FIXME: the sink argument should be marked nonnull as in @PR43833_simple.1308define void @PR43833(ptr %0, i32 %1) {1309; COMMON-LABEL: define void @PR43833(1310; COMMON-SAME: ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) {1311; COMMON-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP1]], 11312; COMMON-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]1313; COMMON:       4:1314; COMMON-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i641315; COMMON-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[TMP5]]1316; COMMON-NEXT:    br label [[TMP8:%.*]]1317; COMMON:       7:1318; COMMON-NEXT:    ret void1319; COMMON:       8:1320; COMMON-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]1321; COMMON-NEXT:    tail call void @sink(ptr [[TMP6]])1322; COMMON-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 11323; COMMON-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]1324; COMMON-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]1325;1326  %3 = icmp sgt i32 %1, 11327  br i1 %3, label %4, label %71328 13294:                                                ; preds = %21330  %5 = zext i32 %1 to i641331  %6 = getelementptr inbounds i32, ptr %0, i64 %51332  br label %81333 13347:                                                ; preds = %8, %21335  ret void1336 13378:                                                ; preds = %8, %41338  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]1339  tail call void @sink(ptr %6)1340  %10 = add nuw nsw i32 %9, 11341  %11 = icmp eq i32 %10, %11342  br i1 %11, label %7, label %81343}1344 1345; Adjusted from PR438331346define void @PR43833_simple(ptr %0, i32 %1) {1347; COMMON-LABEL: define void @PR43833_simple(1348; COMMON-SAME: ptr [[TMP0:%.*]], i32 [[TMP1:%.*]]) {1349; COMMON-NEXT:    [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 01350; COMMON-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP7:%.*]]1351; COMMON:       4:1352; COMMON-NEXT:    [[TMP5:%.*]] = zext i32 [[TMP1]] to i641353; COMMON-NEXT:    [[TMP6:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[TMP5]]1354; COMMON-NEXT:    br label [[TMP8:%.*]]1355; COMMON:       7:1356; COMMON-NEXT:    ret void1357; COMMON:       8:1358; COMMON-NEXT:    [[TMP9:%.*]] = phi i32 [ 1, [[TMP4]] ], [ [[TMP10:%.*]], [[TMP8]] ]1359; COMMON-NEXT:    tail call void @sink(ptr [[TMP6]])1360; COMMON-NEXT:    [[TMP10]] = add nuw nsw i32 [[TMP9]], 11361; COMMON-NEXT:    [[TMP11:%.*]] = icmp eq i32 [[TMP10]], [[TMP1]]1362; COMMON-NEXT:    br i1 [[TMP11]], label [[TMP7]], label [[TMP8]]1363;1364  %3 = icmp ne i32 %1, 01365  br i1 %3, label %4, label %71366 13674:                                                ; preds = %21368  %5 = zext i32 %1 to i641369  %6 = getelementptr inbounds i32, ptr %0, i64 %51370  br label %81371 13727:                                                ; preds = %8, %21373  ret void1374 13758:                                                ; preds = %8, %41376  %9 = phi i32 [ 1, %4 ], [ %10, %8 ]1377  tail call void @sink(ptr %6)1378  %10 = add nuw nsw i32 %9, 11379  %11 = icmp eq i32 %10, %11380  br i1 %11, label %7, label %81381}1382 1383define ptr @pr91177_non_inbounds_gep(ptr nonnull %arg) {1384; FNATTRS-LABEL: define ptr @pr91177_non_inbounds_gep(1385; FNATTRS-SAME: ptr nonnull readnone captures(ret: address, provenance) [[ARG:%.*]]) #[[ATTR0]] {1386; FNATTRS-NEXT:    [[RES:%.*]] = getelementptr i8, ptr [[ARG]], i64 -81387; FNATTRS-NEXT:    ret ptr [[RES]]1388;1389; ATTRIBUTOR-LABEL: define ptr @pr91177_non_inbounds_gep(1390; ATTRIBUTOR-SAME: ptr nofree nonnull readnone [[ARG:%.*]]) #[[ATTR0]] {1391; ATTRIBUTOR-NEXT:    [[RES:%.*]] = getelementptr i8, ptr [[ARG]], i64 -81392; ATTRIBUTOR-NEXT:    ret ptr [[RES]]1393;1394  %res = getelementptr i8, ptr %arg, i64 -81395  ret ptr %res1396}1397 1398define ptr @unknown_func(ptr %fn) {1399; FNATTRS-LABEL: define ptr @unknown_func(1400; FNATTRS-SAME: ptr readonly captures(none) [[FN:%.*]]) {1401; FNATTRS-NEXT:    [[RES:%.*]] = call ptr [[FN]]()1402; FNATTRS-NEXT:    ret ptr [[RES]]1403;1404; ATTRIBUTOR-LABEL: define ptr @unknown_func(1405; ATTRIBUTOR-SAME: ptr nofree nonnull captures(none) [[FN:%.*]]) {1406; ATTRIBUTOR-NEXT:    [[RES:%.*]] = call ptr [[FN]]()1407; ATTRIBUTOR-NEXT:    ret ptr [[RES]]1408;1409  %res = call ptr %fn()1410  ret ptr %res1411}1412 1413define ptr @unknown_nonnull_func(ptr %fn) {1414; FNATTRS-LABEL: define nonnull ptr @unknown_nonnull_func(1415; FNATTRS-SAME: ptr readonly captures(none) [[FN:%.*]]) {1416; FNATTRS-NEXT:    [[RES:%.*]] = call nonnull ptr [[FN]]()1417; FNATTRS-NEXT:    ret ptr [[RES]]1418;1419; ATTRIBUTOR-LABEL: define nonnull ptr @unknown_nonnull_func(1420; ATTRIBUTOR-SAME: ptr nofree nonnull captures(none) [[FN:%.*]]) {1421; ATTRIBUTOR-NEXT:    [[RES:%.*]] = call nonnull ptr [[FN]]()1422; ATTRIBUTOR-NEXT:    ret ptr [[RES]]1423;1424  %res = call nonnull ptr %fn()1425  ret ptr %res1426}1427 1428attributes #0 = { null_pointer_is_valid }1429attributes #1 = { nounwind willreturn}1430