764 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,CGSCC4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"5 6@G = external dso_local global i32, align 47 8declare noalias ptr @malloc(i64) inaccessiblememonly9 10;.11; CHECK: @G = external dso_local global i32, align 412;.13define dso_local ptr @internal_only(i32 %arg) {14; CHECK: Function Attrs: memory(inaccessiblemem: readwrite)15; CHECK-LABEL: define {{[^@]+}}@internal_only16; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR0:[0-9]+]] {17; CHECK-NEXT: entry:18; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i6419; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @malloc(i64 [[CONV]])20; CHECK-NEXT: ret ptr [[CALL]]21;22entry:23 %conv = sext i32 %arg to i6424 %call = call ptr @malloc(i64 %conv)25 ret ptr %call26}27 28define dso_local ptr @internal_only_rec(i32 %arg) {29; CHECK: Function Attrs: memory(inaccessiblemem: readwrite)30; CHECK-LABEL: define {{[^@]+}}@internal_only_rec31; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] {32; CHECK-NEXT: entry:33; CHECK-NEXT: [[REM:%.*]] = srem i32 [[ARG]], 234; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 135; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]36; CHECK: if.then:37; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ARG]], 238; CHECK-NEXT: [[CALL:%.*]] = call ptr @internal_only_rec(i32 [[DIV]])39; CHECK-NEXT: br label [[RETURN:%.*]]40; CHECK: if.end:41; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i6442; CHECK-NEXT: [[CALL1:%.*]] = call noalias ptr @malloc(i64 [[CONV]])43; CHECK-NEXT: br label [[RETURN]]44; CHECK: return:45; CHECK-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[CALL]], [[IF_THEN]] ], [ [[CALL1]], [[IF_END]] ]46; CHECK-NEXT: ret ptr [[RETVAL_0]]47;48entry:49 %rem = srem i32 %arg, 250 %cmp = icmp eq i32 %rem, 151 br i1 %cmp, label %if.then, label %if.end52 53if.then: ; preds = %entry54 %div = sdiv i32 %arg, 255 %call = call ptr @internal_only_rec(i32 %div)56 br label %return57 58if.end: ; preds = %entry59 %conv = sext i32 %arg to i6460 %call1 = call ptr @malloc(i64 %conv)61 br label %return62 63return: ; preds = %if.end, %if.then64 %retval.0 = phi ptr [ %call, %if.then ], [ %call1, %if.end ]65 ret ptr %retval.066}67 68define dso_local ptr @internal_only_rec_static_helper(i32 %arg) {69; CHECK: Function Attrs: memory(inaccessiblemem: readwrite)70; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_helper71; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] {72; CHECK-NEXT: entry:73; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @internal_only_rec_static(i32 [[ARG]])74; CHECK-NEXT: ret ptr [[CALL]]75;76entry:77 %call = call ptr @internal_only_rec_static(i32 %arg)78 ret ptr %call79}80 81define internal ptr @internal_only_rec_static(i32 %arg) {82; CHECK: Function Attrs: memory(inaccessiblemem: readwrite)83; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static84; CHECK-SAME: (i32 [[ARG:%.*]]) #[[ATTR0]] {85; CHECK-NEXT: entry:86; CHECK-NEXT: [[REM:%.*]] = srem i32 [[ARG]], 287; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 188; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]89; CHECK: if.then:90; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ARG]], 291; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @internal_only_rec(i32 [[DIV]])92; CHECK-NEXT: br label [[RETURN:%.*]]93; CHECK: if.end:94; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i6495; CHECK-NEXT: [[CALL1:%.*]] = call noalias ptr @malloc(i64 [[CONV]])96; CHECK-NEXT: br label [[RETURN]]97; CHECK: return:98; CHECK-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[CALL]], [[IF_THEN]] ], [ [[CALL1]], [[IF_END]] ]99; CHECK-NEXT: ret ptr [[RETVAL_0]]100;101entry:102 %rem = srem i32 %arg, 2103 %cmp = icmp eq i32 %rem, 1104 br i1 %cmp, label %if.then, label %if.end105 106if.then: ; preds = %entry107 %div = sdiv i32 %arg, 2108 %call = call ptr @internal_only_rec(i32 %div)109 br label %return110 111if.end: ; preds = %entry112 %conv = sext i32 %arg to i64113 %call1 = call ptr @malloc(i64 %conv)114 br label %return115 116return: ; preds = %if.end, %if.then117 %retval.0 = phi ptr [ %call, %if.then ], [ %call1, %if.end ]118 ret ptr %retval.0119}120 121define dso_local ptr @internal_only_rec_static_helper_malloc_noescape(i32 %arg) {122; FIXME: This is actually inaccessiblememonly because the malloced memory does not escape123; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_helper_malloc_noescape124; CHECK-SAME: (i32 [[ARG:%.*]]) {125; CHECK-NEXT: entry:126; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @internal_only_rec_static_malloc_noescape(i32 [[ARG]])127; CHECK-NEXT: ret ptr [[CALL]]128;129entry:130 %call = call ptr @internal_only_rec_static_malloc_noescape(i32 %arg)131 ret ptr %call132}133 134define internal ptr @internal_only_rec_static_malloc_noescape(i32 %arg) {135; FIXME: This is actually inaccessiblememonly because the malloced memory does not escape136; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_malloc_noescape137; CHECK-SAME: (i32 [[ARG:%.*]]) {138; CHECK-NEXT: entry:139; CHECK-NEXT: [[REM:%.*]] = srem i32 [[ARG]], 2140; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 1141; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]142; CHECK: if.then:143; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[ARG]], 2144; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @internal_only_rec(i32 [[DIV]])145; CHECK-NEXT: br label [[RETURN:%.*]]146; CHECK: if.end:147; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64148; CHECK-NEXT: [[CALL1:%.*]] = call noalias ptr @malloc(i64 [[CONV]])149; CHECK-NEXT: br label [[RETURN]]150; CHECK: return:151; CHECK-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[CALL]], [[IF_THEN]] ], [ null, [[IF_END]] ]152; CHECK-NEXT: ret ptr [[RETVAL_0]]153;154entry:155 %rem = srem i32 %arg, 2156 %cmp = icmp eq i32 %rem, 1157 br i1 %cmp, label %if.then, label %if.end158 159if.then: ; preds = %entry160 %div = sdiv i32 %arg, 2161 %call = call ptr @internal_only_rec(i32 %div)162 br label %return163 164if.end: ; preds = %entry165 %conv = sext i32 %arg to i64166 %call1 = call ptr @malloc(i64 %conv)167 store i8 0, ptr %call1168 br label %return169 170return: ; preds = %if.end, %if.then171 %retval.0 = phi ptr [ %call, %if.then ], [ null, %if.end ]172 ret ptr %retval.0173}174 175define dso_local ptr @internal_argmem_only_read(ptr %arg) {176; CHECK: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)177; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_read178; CHECK-SAME: (ptr nofree noundef nonnull readonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR1:[0-9]+]] {179; CHECK-NEXT: entry:180; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[ARG]], align 4181; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP]] to i64182; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @malloc(i64 [[CONV]])183; CHECK-NEXT: ret ptr [[CALL]]184;185entry:186 %tmp = load i32, ptr %arg, align 4187 %conv = sext i32 %tmp to i64188 %call = call ptr @malloc(i64 %conv)189 ret ptr %call190}191 192define dso_local ptr @internal_argmem_only_write(ptr %arg) {193; CHECK: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)194; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_write195; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR1]] {196; CHECK-NEXT: entry:197; CHECK-NEXT: store i32 10, ptr [[ARG]], align 4198; CHECK-NEXT: [[CALL:%.*]] = call noalias noundef dereferenceable_or_null(10) ptr @malloc(i64 noundef 10)199; CHECK-NEXT: ret ptr [[CALL]]200;201entry:202 store i32 10, ptr %arg, align 4203 %call = call dereferenceable_or_null(10) ptr @malloc(i64 10)204 ret ptr %call205}206 207define dso_local ptr @internal_argmem_only_rec(ptr %arg) {208; TUNIT: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)209; TUNIT-LABEL: define {{[^@]+}}@internal_argmem_only_rec210; TUNIT-SAME: (ptr nofree captures(none) [[ARG:%.*]]) #[[ATTR1]] {211; TUNIT-NEXT: entry:212; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @internal_argmem_only_rec_1(ptr nofree noundef align 4 captures(none) [[ARG]])213; TUNIT-NEXT: ret ptr [[CALL]]214;215; CGSCC: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)216; CGSCC-LABEL: define {{[^@]+}}@internal_argmem_only_rec217; CGSCC-SAME: (ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR1]] {218; CGSCC-NEXT: entry:219; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @internal_argmem_only_rec_1(ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[ARG]])220; CGSCC-NEXT: ret ptr [[CALL]]221;222entry:223 %call = call ptr @internal_argmem_only_rec_1(ptr %arg)224 ret ptr %call225}226 227define internal ptr @internal_argmem_only_rec_1(ptr %arg) {228; CHECK: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)229; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_rec_1230; CHECK-SAME: (ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR1]] {231; CHECK-NEXT: entry:232; CHECK-NEXT: [[TMP:%.*]] = load i32, ptr [[ARG]], align 4233; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP]], 0234; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]235; CHECK: if.then:236; CHECK-NEXT: br label [[RETURN:%.*]]237; CHECK: if.end:238; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARG]], align 4239; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[TMP1]], 1240; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]]241; CHECK: if.then2:242; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 -1243; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @internal_argmem_only_rec_2(ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[ADD_PTR]])244; CHECK-NEXT: br label [[RETURN]]245; CHECK: if.end3:246; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4247; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP2]] to i64248; CHECK-NEXT: [[CALL4:%.*]] = call noalias ptr @malloc(i64 [[CONV]])249; CHECK-NEXT: br label [[RETURN]]250; CHECK: return:251; CHECK-NEXT: [[RETVAL_0:%.*]] = phi ptr [ null, [[IF_THEN]] ], [ [[CALL]], [[IF_THEN2]] ], [ [[CALL4]], [[IF_END3]] ]252; CHECK-NEXT: ret ptr [[RETVAL_0]]253;254entry:255 %tmp = load i32, ptr %arg, align 4256 %cmp = icmp eq i32 %tmp, 0257 br i1 %cmp, label %if.then, label %if.end258 259if.then: ; preds = %entry260 br label %return261 262if.end: ; preds = %entry263 %tmp1 = load i32, ptr %arg, align 4264 %cmp1 = icmp eq i32 %tmp1, 1265 br i1 %cmp1, label %if.then2, label %if.end3266 267if.then2: ; preds = %if.end268 %add.ptr = getelementptr inbounds i32, ptr %arg, i64 -1269 %call = call ptr @internal_argmem_only_rec_2(ptr nonnull %add.ptr)270 br label %return271 272if.end3: ; preds = %if.end273 %tmp2 = load i32, ptr %arg, align 4274 %conv = sext i32 %tmp2 to i64275 %call4 = call ptr @malloc(i64 %conv)276 br label %return277 278return: ; preds = %if.end3, %if.then2, %if.then279 %retval.0 = phi ptr [ null, %if.then ], [ %call, %if.then2 ], [ %call4, %if.end3 ]280 ret ptr %retval.0281}282 283define internal ptr @internal_argmem_only_rec_2(ptr %arg) {284; CHECK: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)285; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_rec_2286; CHECK-SAME: (ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[ARG:%.*]]) #[[ATTR1]] {287; CHECK-NEXT: entry:288; CHECK-NEXT: store i32 0, ptr [[ARG]], align 4289; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 -1290; CHECK-NEXT: [[CALL:%.*]] = call noalias ptr @internal_argmem_only_rec_1(ptr nofree noundef nonnull align 4 captures(none) dereferenceable(4) [[ADD_PTR]])291; CHECK-NEXT: ret ptr [[CALL]]292;293entry:294 store i32 0, ptr %arg, align 4295 %add.ptr = getelementptr inbounds i32, ptr %arg, i64 -1296 %call = call ptr @internal_argmem_only_rec_1(ptr nonnull %add.ptr)297 ret ptr %call298}299 300declare ptr @unknown_ptr() readnone301declare ptr @argmem_only(ptr %arg) argmemonly302declare ptr @inaccesible_argmem_only_decl(ptr %arg) inaccessiblemem_or_argmemonly303 304define void @callerA1(ptr %arg) {305; CHECK: Function Attrs: memory(argmem: readwrite)306; CHECK-LABEL: define {{[^@]+}}@callerA1307; CHECK-SAME: (ptr [[ARG:%.*]]) #[[ATTR3:[0-9]+]] {308; CHECK-NEXT: [[TMP1:%.*]] = call ptr @argmem_only(ptr [[ARG]])309; CHECK-NEXT: ret void310;311 call ptr @argmem_only(ptr %arg)312 ret void313}314define void @callerA2(ptr %arg) {315; CHECK: Function Attrs: memory(argmem: readwrite, inaccessiblemem: readwrite)316; CHECK-LABEL: define {{[^@]+}}@callerA2317; CHECK-SAME: (ptr [[ARG:%.*]]) #[[ATTR1]] {318; CHECK-NEXT: [[TMP1:%.*]] = call ptr @inaccesible_argmem_only_decl(ptr [[ARG]])319; CHECK-NEXT: ret void320;321 call ptr @inaccesible_argmem_only_decl(ptr %arg)322 ret void323}324define void @callerB1() {325; CHECK: Function Attrs: memory(none)326; CHECK-LABEL: define {{[^@]+}}@callerB1327; CHECK-SAME: () #[[ATTR2:[0-9]+]] {328; CHECK-NEXT: [[STACK:%.*]] = alloca i8, align 1329; CHECK-NEXT: [[TMP1:%.*]] = call ptr @argmem_only(ptr noundef nonnull dereferenceable(1) [[STACK]])330; CHECK-NEXT: ret void331;332 %stack = alloca i8333 call ptr @argmem_only(ptr %stack)334 ret void335}336define void @callerB2() {337; CHECK: Function Attrs: memory(inaccessiblemem: readwrite)338; CHECK-LABEL: define {{[^@]+}}@callerB2339; CHECK-SAME: () #[[ATTR0]] {340; CHECK-NEXT: [[STACK:%.*]] = alloca i8, align 1341; CHECK-NEXT: [[TMP1:%.*]] = call ptr @inaccesible_argmem_only_decl(ptr noundef nonnull dereferenceable(1) [[STACK]])342; CHECK-NEXT: ret void343;344 %stack = alloca i8345 call ptr @inaccesible_argmem_only_decl(ptr %stack)346 ret void347}348define void @callerC1() {349; CHECK-LABEL: define {{[^@]+}}@callerC1() {350; CHECK-NEXT: [[UNKNOWN:%.*]] = call ptr @unknown_ptr()351; CHECK-NEXT: [[TMP1:%.*]] = call ptr @argmem_only(ptr [[UNKNOWN]])352; CHECK-NEXT: ret void353;354 %unknown = call ptr @unknown_ptr()355 call ptr @argmem_only(ptr %unknown)356 ret void357}358define void @callerC2() {359; CHECK-LABEL: define {{[^@]+}}@callerC2() {360; CHECK-NEXT: [[UNKNOWN:%.*]] = call ptr @unknown_ptr()361; CHECK-NEXT: [[TMP1:%.*]] = call ptr @inaccesible_argmem_only_decl(ptr [[UNKNOWN]])362; CHECK-NEXT: ret void363;364 %unknown = call ptr @unknown_ptr()365 call ptr @inaccesible_argmem_only_decl(ptr %unknown)366 ret void367}368define void @callerD1() {369; CHECK-LABEL: define {{[^@]+}}@callerD1() {370; CHECK-NEXT: [[UNKNOWN:%.*]] = call ptr @argmem_only(ptr noundef null)371; CHECK-NEXT: store i8 0, ptr [[UNKNOWN]], align 1372; CHECK-NEXT: ret void373;374 %unknown = call ptr @argmem_only(ptr null)375 store i8 0, ptr %unknown376 ret void377}378define void @callerD2() {379; CHECK-LABEL: define {{[^@]+}}@callerD2() {380; CHECK-NEXT: [[UNKNOWN:%.*]] = call ptr @inaccesible_argmem_only_decl(ptr noundef null)381; CHECK-NEXT: store i8 0, ptr [[UNKNOWN]], align 1382; CHECK-NEXT: ret void383;384 %unknown = call ptr @inaccesible_argmem_only_decl(ptr null)385 store i8 0, ptr %unknown386 ret void387}388 389define void @write_global() {390; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)391; CHECK-LABEL: define {{[^@]+}}@write_global392; CHECK-SAME: () #[[ATTR4:[0-9]+]] {393; CHECK-NEXT: store i32 0, ptr @G, align 4394; CHECK-NEXT: ret void395;396 store i32 0, ptr @G, align 4397 ret void398}399define void @write_global_via_arg(ptr %GPtr) {400; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)401; CHECK-LABEL: define {{[^@]+}}@write_global_via_arg402; CHECK-SAME: (ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) [[GPTR:%.*]]) #[[ATTR5:[0-9]+]] {403; CHECK-NEXT: store i32 0, ptr [[GPTR]], align 4404; CHECK-NEXT: ret void405;406 store i32 0, ptr %GPtr, align 4407 ret void408}409define internal void @write_global_via_arg_internal(ptr %GPtr) {410; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none)411; CHECK-LABEL: define {{[^@]+}}@write_global_via_arg_internal412; CHECK-SAME: () #[[ATTR6:[0-9]+]] {413; CHECK-NEXT: store i32 0, ptr @G, align 4414; CHECK-NEXT: ret void415;416 store i32 0, ptr %GPtr, align 4417 ret void418}419 420define void @writeonly_global() {421; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)422; TUNIT-LABEL: define {{[^@]+}}@writeonly_global423; TUNIT-SAME: () #[[ATTR4]] {424; TUNIT-NEXT: call void @write_global() #[[ATTR10:[0-9]+]]425; TUNIT-NEXT: ret void426;427; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)428; CGSCC-LABEL: define {{[^@]+}}@writeonly_global429; CGSCC-SAME: () #[[ATTR7:[0-9]+]] {430; CGSCC-NEXT: call void @write_global() #[[ATTR11:[0-9]+]]431; CGSCC-NEXT: ret void432;433 call void @write_global()434 ret void435}436define void @writeonly_global_via_arg() {437; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)438; TUNIT-LABEL: define {{[^@]+}}@writeonly_global_via_arg439; TUNIT-SAME: () #[[ATTR4]] {440; TUNIT-NEXT: call void @write_global_via_arg(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) @G) #[[ATTR10]]441; TUNIT-NEXT: ret void442;443; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)444; CGSCC-LABEL: define {{[^@]+}}@writeonly_global_via_arg445; CGSCC-SAME: () #[[ATTR7]] {446; CGSCC-NEXT: call void @write_global_via_arg(ptr nofree noundef nonnull writeonly align 4 captures(none) dereferenceable(4) @G) #[[ATTR11]]447; CGSCC-NEXT: ret void448;449 call void @write_global_via_arg(ptr @G)450 ret void451}452 453define void @writeonly_global_via_arg_internal() {454;455; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)456; TUNIT-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal457; TUNIT-SAME: () #[[ATTR4]] {458; TUNIT-NEXT: call void @write_global_via_arg_internal() #[[ATTR10]]459; TUNIT-NEXT: ret void460;461; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)462; CGSCC-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal463; CGSCC-SAME: () #[[ATTR7]] {464; CGSCC-NEXT: call void @write_global_via_arg_internal() #[[ATTR11]]465; CGSCC-NEXT: ret void466;467 call void @write_global_via_arg_internal(ptr @G)468 ret void469}470 471define i8 @recursive_not_readnone(ptr %ptr, i1 %c) {472; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: write)473; TUNIT-LABEL: define {{[^@]+}}@recursive_not_readnone474; TUNIT-SAME: (ptr nofree writeonly captures(none) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR7:[0-9]+]] {475; TUNIT-NEXT: [[ALLOC:%.*]] = alloca i8, align 1476; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]477; TUNIT: t:478; TUNIT-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11:[0-9]+]]479; TUNIT-NEXT: ret i8 1480; TUNIT: f:481; TUNIT-NEXT: store i8 1, ptr [[PTR]], align 1482; TUNIT-NEXT: ret i8 0483;484; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: write)485; CGSCC-LABEL: define {{[^@]+}}@recursive_not_readnone486; CGSCC-SAME: (ptr nofree writeonly captures(none) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR8:[0-9]+]] {487; CGSCC-NEXT: [[ALLOC:%.*]] = alloca i8, align 1488; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]489; CGSCC: t:490; CGSCC-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12:[0-9]+]]491; CGSCC-NEXT: ret i8 1492; CGSCC: f:493; CGSCC-NEXT: store i8 1, ptr [[PTR]], align 1494; CGSCC-NEXT: ret i8 0495;496 %alloc = alloca i8497 br i1 %c, label %t, label %f498t:499 call i8 @recursive_not_readnone(ptr %alloc, i1 false)500 %r = load i8, ptr %alloc501 ret i8 %r502f:503 store i8 1, ptr %ptr504 ret i8 0505}506 507define internal i8 @recursive_not_readnone_internal(ptr %ptr, i1 %c) {508; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: write)509; TUNIT-LABEL: define {{[^@]+}}@recursive_not_readnone_internal510; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR7]] {511; TUNIT-NEXT: [[ALLOC:%.*]] = alloca i8, align 1512; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]513; TUNIT: t:514; TUNIT-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]]515; TUNIT-NEXT: ret i8 1516; TUNIT: f:517; TUNIT-NEXT: store i8 1, ptr [[PTR]], align 1518; TUNIT-NEXT: ret i8 0519;520; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: write)521; CGSCC-LABEL: define {{[^@]+}}@recursive_not_readnone_internal522; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR8]] {523; CGSCC-NEXT: [[ALLOC:%.*]] = alloca i8, align 1524; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]525; CGSCC: t:526; CGSCC-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12]]527; CGSCC-NEXT: ret i8 1528; CGSCC: f:529; CGSCC-NEXT: store i8 1, ptr [[PTR]], align 1530; CGSCC-NEXT: ret i8 0531;532 %alloc = alloca i8533 br i1 %c, label %t, label %f534t:535 call i8 @recursive_not_readnone_internal(ptr %alloc, i1 false)536 %r = load i8, ptr %alloc537 ret i8 %r538f:539 store i8 1, ptr %ptr540 ret i8 0541}542 543define i8 @readnone_caller(i1 %c) {544; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)545; TUNIT-LABEL: define {{[^@]+}}@readnone_caller546; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR8:[0-9]+]] {547; TUNIT-NEXT: [[A:%.*]] = alloca i8, align 1548; TUNIT-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[A]], i1 noundef [[C]]) #[[ATTR11]]549; TUNIT-NEXT: ret i8 [[R]]550;551; CGSCC: Function Attrs: nofree nosync nounwind memory(none)552; CGSCC-LABEL: define {{[^@]+}}@readnone_caller553; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR9:[0-9]+]] {554; CGSCC-NEXT: [[A:%.*]] = alloca i8, align 1555; CGSCC-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[A]], i1 noundef [[C]]) #[[ATTR13:[0-9]+]]556; CGSCC-NEXT: ret i8 [[R]]557;558 %a = alloca i8559 %r = call i8 @recursive_not_readnone_internal(ptr %a, i1 %c)560 ret i8 %r561}562 563define internal i8 @recursive_readnone_internal2(ptr %ptr, i1 %c) {564; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: write)565; TUNIT-LABEL: define {{[^@]+}}@recursive_readnone_internal2566; TUNIT-SAME: (ptr noalias nofree writeonly captures(none) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR7]] {567; TUNIT-NEXT: [[ALLOC:%.*]] = alloca i8, align 1568; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]569; TUNIT: t:570; TUNIT-NEXT: [[TMP1:%.*]] = call i8 @recursive_readnone_internal2(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]]571; TUNIT-NEXT: ret i8 1572; TUNIT: f:573; TUNIT-NEXT: store i8 1, ptr [[PTR]], align 1574; TUNIT-NEXT: ret i8 0575;576; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: write)577; CGSCC-LABEL: define {{[^@]+}}@recursive_readnone_internal2578; CGSCC-SAME: (ptr noalias nofree writeonly captures(none) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR8]] {579; CGSCC-NEXT: [[ALLOC:%.*]] = alloca i8, align 1580; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]581; CGSCC: t:582; CGSCC-NEXT: [[TMP1:%.*]] = call i8 @recursive_readnone_internal2(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12]]583; CGSCC-NEXT: ret i8 1584; CGSCC: f:585; CGSCC-NEXT: store i8 1, ptr [[PTR]], align 1586; CGSCC-NEXT: ret i8 0587;588 %alloc = alloca i8589 br i1 %c, label %t, label %f590t:591 call i8 @recursive_readnone_internal2(ptr %alloc, i1 false)592 %r = load i8, ptr %alloc593 ret i8 %r594f:595 store i8 1, ptr %ptr596 ret i8 0597}598 599define i8 @readnone_caller2(i1 %c) {600; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)601; TUNIT-LABEL: define {{[^@]+}}@readnone_caller2602; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR8]] {603; TUNIT-NEXT: [[R:%.*]] = call i8 @recursive_readnone_internal2(ptr undef, i1 noundef [[C]]) #[[ATTR11]]604; TUNIT-NEXT: ret i8 [[R]]605;606; CGSCC: Function Attrs: nofree nosync nounwind memory(none)607; CGSCC-LABEL: define {{[^@]+}}@readnone_caller2608; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR9]] {609; CGSCC-NEXT: [[R:%.*]] = call i8 @recursive_readnone_internal2(ptr nofree undef, i1 noundef [[C]]) #[[ATTR13]]610; CGSCC-NEXT: ret i8 [[R]]611;612 %r = call i8 @recursive_readnone_internal2(ptr undef, i1 %c)613 ret i8 %r614}615 616define internal i8 @recursive_not_readnone_internal3(ptr %ptr, i1 %c) {617; TUNIT: Function Attrs: nofree nosync nounwind memory(argmem: write)618; TUNIT-LABEL: define {{[^@]+}}@recursive_not_readnone_internal3619; TUNIT-SAME: (ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR7]] {620; TUNIT-NEXT: [[ALLOC:%.*]] = alloca i8, align 1621; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]622; TUNIT: t:623; TUNIT-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal3(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR11]]624; TUNIT-NEXT: ret i8 1625; TUNIT: f:626; TUNIT-NEXT: store i8 1, ptr [[PTR]], align 1627; TUNIT-NEXT: ret i8 0628;629; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: write)630; CGSCC-LABEL: define {{[^@]+}}@recursive_not_readnone_internal3631; CGSCC-SAME: (ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[PTR:%.*]], i1 noundef [[C:%.*]]) #[[ATTR8]] {632; CGSCC-NEXT: [[ALLOC:%.*]] = alloca i8, align 1633; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]634; CGSCC: t:635; CGSCC-NEXT: [[TMP1:%.*]] = call i8 @recursive_not_readnone_internal3(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef false) #[[ATTR12]]636; CGSCC-NEXT: ret i8 1637; CGSCC: f:638; CGSCC-NEXT: store i8 1, ptr [[PTR]], align 1639; CGSCC-NEXT: ret i8 0640;641 %alloc = alloca i8642 br i1 %c, label %t, label %f643t:644 call i8 @recursive_not_readnone_internal3(ptr %alloc, i1 false)645 %r = load i8, ptr %alloc646 ret i8 %r647f:648 store i8 1, ptr %ptr649 ret i8 0650}651 652define i8 @readnone_caller3(i1 %c) {653; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)654; TUNIT-LABEL: define {{[^@]+}}@readnone_caller3655; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR8]] {656; TUNIT-NEXT: [[ALLOC:%.*]] = alloca i8, align 1657; TUNIT-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal3(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef [[C]]) #[[ATTR11]]658; TUNIT-NEXT: ret i8 [[R]]659;660; CGSCC: Function Attrs: nofree nosync nounwind memory(none)661; CGSCC-LABEL: define {{[^@]+}}@readnone_caller3662; CGSCC-SAME: (i1 noundef [[C:%.*]]) #[[ATTR9]] {663; CGSCC-NEXT: [[ALLOC:%.*]] = alloca i8, align 1664; CGSCC-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal3(ptr noalias nofree noundef nonnull writeonly captures(none) dereferenceable(1) [[ALLOC]], i1 noundef [[C]]) #[[ATTR13]]665; CGSCC-NEXT: ret i8 [[R]]666;667 %alloc = alloca i8668 %r = call i8 @recursive_not_readnone_internal3(ptr %alloc, i1 %c)669 ret i8 %r670}671 672define internal void @argmemonly_before_ipconstprop(ptr %p) argmemonly {673; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none)674; CHECK-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop675; CHECK-SAME: () #[[ATTR6]] {676; CHECK-NEXT: store i32 0, ptr @G, align 4677; CHECK-NEXT: ret void678;679 store i32 0, ptr %p680 ret void681}682 683define void @argmemonly_caller() {684; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write)685; TUNIT-LABEL: define {{[^@]+}}@argmemonly_caller686; TUNIT-SAME: () #[[ATTR4]] {687; TUNIT-NEXT: call void @argmemonly_before_ipconstprop() #[[ATTR10]]688; TUNIT-NEXT: ret void689;690; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write)691; CGSCC-LABEL: define {{[^@]+}}@argmemonly_caller692; CGSCC-SAME: () #[[ATTR7]] {693; CGSCC-NEXT: call void @argmemonly_before_ipconstprop() #[[ATTR11]]694; CGSCC-NEXT: ret void695;696 call void @argmemonly_before_ipconstprop(ptr @G)697 ret void698}699 700declare ptr @no_mem_unknown_ptr(ptr %arg) memory(none)701 702define void @argmem_and_unknown(i1 %c, ptr %arg) memory(argmem: readwrite) {703; TUNIT: Function Attrs: nosync memory(argmem: write)704; TUNIT-LABEL: define {{[^@]+}}@argmem_and_unknown705; TUNIT-SAME: (i1 noundef [[C:%.*]], ptr writeonly [[ARG:%.*]]) #[[ATTR9:[0-9]+]] {706; TUNIT-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]707; TUNIT: t:708; TUNIT-NEXT: [[P:%.*]] = call ptr @no_mem_unknown_ptr(ptr noalias readnone [[ARG]]) #[[ATTR12:[0-9]+]]709; TUNIT-NEXT: store i32 0, ptr [[P]], align 4710; TUNIT-NEXT: br label [[F]]711; TUNIT: f:712; TUNIT-NEXT: ret void713;714; CGSCC: Function Attrs: nosync memory(argmem: write)715; CGSCC-LABEL: define {{[^@]+}}@argmem_and_unknown716; CGSCC-SAME: (i1 noundef [[C:%.*]], ptr writeonly [[ARG:%.*]]) #[[ATTR10:[0-9]+]] {717; CGSCC-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]718; CGSCC: t:719; CGSCC-NEXT: [[P:%.*]] = call ptr @no_mem_unknown_ptr(ptr noalias readnone [[ARG]]) #[[ATTR14:[0-9]+]]720; CGSCC-NEXT: store i32 0, ptr [[P]], align 4721; CGSCC-NEXT: br label [[F]]722; CGSCC: f:723; CGSCC-NEXT: ret void724;725 br i1 %c, label %t, label %f726t:727 %p = call ptr @no_mem_unknown_ptr(ptr %arg)728 store i32 0, ptr %p729 br label %f730f:731 ret void732}733;.734; TUNIT: attributes #[[ATTR0]] = { memory(inaccessiblemem: readwrite) }735; TUNIT: attributes #[[ATTR1]] = { memory(argmem: readwrite, inaccessiblemem: readwrite) }736; TUNIT: attributes #[[ATTR2]] = { memory(none) }737; TUNIT: attributes #[[ATTR3]] = { memory(argmem: readwrite) }738; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }739; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }740; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none) }741; TUNIT: attributes #[[ATTR7]] = { nofree nosync nounwind memory(argmem: write) }742; TUNIT: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind memory(none) }743; TUNIT: attributes #[[ATTR9]] = { nosync memory(argmem: write) }744; TUNIT: attributes #[[ATTR10]] = { nofree nosync nounwind willreturn memory(write) }745; TUNIT: attributes #[[ATTR11]] = { nofree nosync nounwind memory(write) }746; TUNIT: attributes #[[ATTR12]] = { nosync }747;.748; CGSCC: attributes #[[ATTR0]] = { memory(inaccessiblemem: readwrite) }749; CGSCC: attributes #[[ATTR1]] = { memory(argmem: readwrite, inaccessiblemem: readwrite) }750; CGSCC: attributes #[[ATTR2]] = { memory(none) }751; CGSCC: attributes #[[ATTR3]] = { memory(argmem: readwrite) }752; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) }753; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }754; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write, argmem: none) }755; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree nosync nounwind willreturn memory(write) }756; CGSCC: attributes #[[ATTR8]] = { nofree nosync nounwind memory(argmem: write) }757; CGSCC: attributes #[[ATTR9]] = { nofree nosync nounwind memory(none) }758; CGSCC: attributes #[[ATTR10]] = { nosync memory(argmem: write) }759; CGSCC: attributes #[[ATTR11]] = { nofree nounwind willreturn memory(write) }760; CGSCC: attributes #[[ATTR12]] = { nofree nosync nounwind memory(write) }761; CGSCC: attributes #[[ATTR13]] = { nofree nounwind memory(write) }762; CGSCC: attributes #[[ATTR14]] = { nosync }763;.764