diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -7681,10 +7681,13 @@ if (isa(Obj)) continue; if (auto *Arg = dyn_cast(Obj)) { - if (Arg->hasByValAttr()) - MLK = NO_LOCAL_MEM; - else - MLK = NO_ARGUMENT_MEM; + // TODO: For now we do not treat byval arguments as local copies performed + // on the call edge, though, we should. To make that happen we need to + // teach various passes, e.g., DSE, about the copy effect of a byval. That + // would also allow us to mark functions only accessing byval arguments as + // readnone again, atguably their acceses have no effect outside of the + // function, like accesses to allocas. + MLK = NO_ARGUMENT_MEM; } else if (auto *GV = dyn_cast(Obj)) { // Reading constant memory is not treated as a read "effect" by the // function attr pass so we won't neither. Constants defined by TBAA are diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll @@ -9,7 +9,7 @@ ; Don't drop 'byval' on %X here. define internal i32 @f(%struct.ss* byval(%struct.ss) %b, i32* byval(i32) %X, i32 %i) nounwind { ; -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree noundef nonnull byval(i32) align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: @@ -22,7 +22,7 @@ ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] ; IS__TUNIT_OPM-NEXT: ret i32 [[A]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT_NPM-NEXT: entry: @@ -42,7 +42,7 @@ ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f ; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree noundef nonnull byval(i32) align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: @@ -65,7 +65,6 @@ ; IS__CGSCC_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[B_PRIV_CAST]], align 8 ; IS__CGSCC_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[B_PRIV_0_1]], align 4 ; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 @@ -91,7 +90,7 @@ ; Also make sure we don't drop the call zeroext attribute. define i32 @test(i32* %X) { ; -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) #[[ATTR0]] { ; IS__TUNIT_OPM-NEXT: entry: @@ -99,10 +98,10 @@ ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 ; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]], i32* nocapture nofree readonly byval(i32) align 4 [[X]]) #[[ATTR0]] +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]], i32* nocapture nofree readonly byval(i32) align 4 [[X]]) #[[ATTR1:[0-9]+]] ; IS__TUNIT_OPM-NEXT: ret i32 [[C]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) #[[ATTR0]] { ; IS__TUNIT_NPM-NEXT: entry: @@ -115,18 +114,18 @@ ; IS__TUNIT_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 8 ; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 4 -; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]]) #[[ATTR1:[0-9]+]] ; IS__TUNIT_NPM-NEXT: ret i32 [[C]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test -; IS__CGSCC_OPM-SAME: (i32* nocapture nofree noundef nonnull readnone align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0]] { +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8 ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]], i32* noalias nocapture nofree noundef nonnull readnone byval(i32) align 4 dereferenceable(4) [[X]]) #[[ATTR1:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]], i32* noalias nocapture nofree noundef nonnull readonly byval(i32) align 4 dereferenceable(4) [[X]]) #[[ATTR1:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i32 [[C]] ; ; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn @@ -152,12 +151,13 @@ ret i32 %c } ;. -; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { nofree nosync nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind willreturn } ;. -; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC_OPM: attributes #[[ATTR1]] = { readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nounwind willreturn } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn } -; IS__CGSCC_NPM: attributes #[[ATTR2]] = { readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll @@ -7,7 +7,36 @@ %struct.ss = type { i32, i64 } define internal void @f(%struct.ss* byval(%struct.ss) %b, i32* byval(i32) %X) nounwind { -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f +; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree noundef nonnull writeonly byval(i32) align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__TUNIT_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 +; IS__TUNIT_OPM-NEXT: store i32 0, i32* [[X]], align 4 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[X_PRIV:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[X_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 8 +; IS__TUNIT_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 +; IS__TUNIT_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 +; IS__TUNIT_NPM-NEXT: store i32 0, i32* [[X_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f ; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree noundef nonnull writeonly byval(i32) align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: @@ -27,12 +56,10 @@ ; IS__CGSCC_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[B_PRIV_CAST]], align 8 ; IS__CGSCC_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[B_PRIV_0_1]], align 4 ; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 ; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 -; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[X_PRIV]], align 4 ; IS__CGSCC_NPM-NEXT: ret void ; entry: @@ -47,24 +74,42 @@ define i32 @test(i32* %X) { ; -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@test -; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) #[[ATTR0:[0-9]+]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8 -; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; IS__TUNIT____-NEXT: store i32 1, i32* [[TMP1]], align 8 -; IS__TUNIT____-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__TUNIT____-NEXT: ret i32 0 +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) #[[ATTR0]] { +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_OPM-NEXT: call void @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]], i32* nocapture nofree readonly byval(i32) align 4 [[X]]) #[[ATTR1:[0-9]+]] +; IS__TUNIT_OPM-NEXT: ret i32 0 ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) #[[ATTR0]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 4 +; IS__TUNIT_NPM-NEXT: call void @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]]) #[[ATTR1:[0-9]+]] +; IS__TUNIT_NPM-NEXT: ret i32 0 +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test -; IS__CGSCC_OPM-SAME: (i32* nocapture nofree noundef nonnull readnone align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0]] { +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 8 ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: call void @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]], i32* noalias nocapture nofree noundef nonnull readonly byval(i32) align 4 dereferenceable(4) [[X]]) #[[ATTR1:[0-9]+]] ; IS__CGSCC_OPM-NEXT: ret i32 0 ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -86,7 +131,11 @@ ret i32 0 } ;. -; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind willreturn } +;. +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nounwind willreturn } ;. -; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll @@ -9,7 +9,7 @@ %struct.ss = type { i32, i64 } define internal i32 @f(%struct.ss* byval(%struct.ss) %b) nounwind { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 8 dereferenceable(12) [[B:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: @@ -19,7 +19,7 @@ ; IS__TUNIT_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT_NPM-NEXT: entry: @@ -34,7 +34,7 @@ ; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP1]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f ; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 32 dereferenceable(12) [[B:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: @@ -52,7 +52,6 @@ ; IS__CGSCC_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[B_PRIV_CAST]], align 8 ; IS__CGSCC_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[B_PRIV_0_1]], align 4 ; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 @@ -69,7 +68,7 @@ define internal i32 @g(%struct.ss* byval(%struct.ss) align 32 %b) nounwind { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@g ; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 32 dereferenceable(12) [[B:%.*]]) #[[ATTR0]] { ; IS__TUNIT_OPM-NEXT: entry: @@ -79,7 +78,7 @@ ; IS__TUNIT_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@g ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) #[[ATTR0]] { ; IS__TUNIT_NPM-NEXT: entry: @@ -94,7 +93,7 @@ ; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP2]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@g ; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree noundef nonnull byval([[STRUCT_SS:%.*]]) align 32 dereferenceable(12) [[B:%.*]]) #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: @@ -112,7 +111,6 @@ ; IS__CGSCC_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[B_PRIV_CAST]], align 32 ; IS__CGSCC_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[B_PRIV_0_1]], align 4 ; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 ; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 ; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 @@ -131,20 +129,20 @@ define i32 @main() nounwind { ; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@main -; IS__TUNIT_OPM-SAME: () #[[ATTR0]] { +; IS__TUNIT_OPM-SAME: () #[[ATTR1:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 ; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 ; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__TUNIT_OPM-NEXT: [[C0:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]]) #[[ATTR0]] -; IS__TUNIT_OPM-NEXT: [[C1:%.*]] = call i32 @g(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 32 dereferenceable(12) [[S]]) #[[ATTR0]] +; IS__TUNIT_OPM-NEXT: [[C0:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 8 dereferenceable(12) [[S]]) #[[ATTR2:[0-9]+]] +; IS__TUNIT_OPM-NEXT: [[C1:%.*]] = call i32 @g(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 32 dereferenceable(12) [[S]]) #[[ATTR2]] ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__TUNIT_OPM-NEXT: ret i32 [[A]] ; ; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@main -; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { +; IS__TUNIT_NPM-SAME: () #[[ATTR1:[0-9]+]] { ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 @@ -154,25 +152,25 @@ ; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 8 ; IS__TUNIT_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 8 -; IS__TUNIT_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) #[[ATTR2:[0-9]+]] ; IS__TUNIT_NPM-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* ; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[S_CAST1]], align 32 ; IS__TUNIT_NPM-NEXT: [[S_0_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 ; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i64, i64* [[S_0_12]], align 32 -; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) #[[ATTR2]] ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@main -; IS__CGSCC_OPM-SAME: () #[[ATTR0]] { +; IS__CGSCC_OPM-SAME: () #[[ATTR1:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 ; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 ; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[TMP1]], align 32 ; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; IS__CGSCC_OPM-NEXT: [[C0:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_SS]]) align 32 dereferenceable(12) [[S]]) #[[ATTR1:[0-9]+]] -; IS__CGSCC_OPM-NEXT: [[C1:%.*]] = call i32 @g(%struct.ss* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_SS]]) align 32 dereferenceable(12) [[S]]) #[[ATTR1]] +; IS__CGSCC_OPM-NEXT: [[C0:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 32 dereferenceable(12) [[S]]) #[[ATTR2:[0-9]+]] +; IS__CGSCC_OPM-NEXT: [[C1:%.*]] = call i32 @g(%struct.ss* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_SS]]) align 32 dereferenceable(12) [[S]]) #[[ATTR2]] ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__CGSCC_OPM-NEXT: ret i32 [[A]] ; @@ -202,8 +200,14 @@ ;. -; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { nofree nosync nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn } +; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR2:[0-9]+]] = { nofree nosync nounwind willreturn } +;. +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nounwind willreturn } ;. -; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } -; IS__CGSCC____: attributes #[[ATTR1:[0-9]+]] = { nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll @@ -78,7 +78,7 @@ } define internal i32 @vfu2(%struct.MYstr* byval(%struct.MYstr) align 4 %u) nounwind readonly { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@vfu2 ; IS__TUNIT_OPM-SAME: (%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) [[U:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: @@ -90,7 +90,7 @@ ; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP5]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@vfu2 ; IS__TUNIT_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__TUNIT_NPM-NEXT: entry: @@ -107,7 +107,7 @@ ; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP7]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vfu2 ; IS__CGSCC_OPM-SAME: (%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) [[U:%.*]]) #[[ATTR1:[0-9]+]] { ; IS__CGSCC_OPM-NEXT: entry: @@ -159,15 +159,15 @@ ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions ; IS__TUNIT_NPM-SAME: () #[[ATTR0]] { ; IS__TUNIT_NPM-NEXT: entry: -; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 -; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] ; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 -; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 -; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_12]], align 8 +; IS__TUNIT_NPM-NEXT: call void @vfu1(i8 [[TMP0]], i32 [[TMP1]]) #[[ATTR0]] +; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i8, i8* [[MYSTR_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[MYSTR_0_1]], align 8 ; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP2]], i32 [[TMP3]]) #[[ATTR2:[0-9]+]] ; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] ; @@ -176,7 +176,7 @@ ; IS__CGSCC_OPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: call void @vfu1(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] -; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(%struct.MYstr* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_MYSTR]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] +; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RESULT]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind @@ -198,7 +198,7 @@ } define internal i32 @vfu2_v2(%struct.MYstr* byval(%struct.MYstr) align 4 %u) nounwind readonly { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@vfu2_v2 ; IS__TUNIT_OPM-SAME: (%struct.MYstr* noalias nocapture nofree noundef nonnull byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) [[U:%.*]]) #[[ATTR1]] { ; IS__TUNIT_OPM-NEXT: entry: @@ -212,7 +212,7 @@ ; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP5]] ; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@vfu2_v2 ; IS__TUNIT_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1]] { ; IS__TUNIT_NPM-NEXT: entry: @@ -231,7 +231,7 @@ ; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP7]] ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vfu2_v2 ; IS__CGSCC_OPM-SAME: (%struct.MYstr* noalias nocapture nofree noundef nonnull byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) [[U:%.*]]) #[[ATTR1]] { ; IS__CGSCC_OPM-NEXT: entry: @@ -251,7 +251,6 @@ ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8 ; IS__CGSCC_NPM-NEXT: [[U_PRIV_CAST:%.*]] = bitcast %struct.MYstr* [[U_PRIV]] to i8* -; IS__CGSCC_NPM-NEXT: store i8 0, i8* [[U_PRIV_CAST]], align 8 ; IS__CGSCC_NPM-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 ; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[U_PRIV_0_1]], align 4 ; IS__CGSCC_NPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 @@ -306,7 +305,7 @@ ; IS__CGSCC_OPM-SAME: () #[[ATTR0]] { ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: call void @vfu1(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR:%.*]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] -; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_MYSTR]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] +; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* noalias nocapture nofree noundef nonnull readonly byval([[STRUCT_MYSTR]]) align 8 dereferenceable(8) @mystr) #[[ATTR0]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RESULT]] ; ; IS__CGSCC_NPM: Function Attrs: nounwind @@ -324,9 +323,12 @@ } ;. ; IS__TUNIT____: attributes #[[ATTR0:[0-9]+]] = { nounwind } -; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { nofree nosync nounwind readnone willreturn } +; IS__TUNIT____: attributes #[[ATTR1:[0-9]+]] = { argmemonly nofree nosync nounwind readonly willreturn } ; IS__TUNIT____: attributes #[[ATTR2:[0-9]+]] = { nounwind readonly } ;. -; IS__CGSCC____: attributes #[[ATTR0:[0-9]+]] = { nounwind } -; IS__CGSCC____: attributes #[[ATTR1:[0-9]+]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nounwind } +; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn } +;. +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nounwind } +; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll --- a/llvm/test/Transforms/Attributor/readattrs.ll +++ b/llvm/test/Transforms/Attributor/readattrs.ll @@ -363,15 +363,15 @@ } define void @byval_no_fnarg(i8* byval(i8) %written) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_no_fnarg -; IS__TUNIT____-SAME: (i8* noalias nocapture nofree noundef nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) #[[ATTR1]] { +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree noundef nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) #[[ATTR3]] { ; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_no_fnarg -; IS__CGSCC____-SAME: (i8* noalias nocapture nofree noundef nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) #[[ATTR1]] { +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree noundef nonnull writeonly byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) #[[ATTR3]] { ; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 ; IS__CGSCC____-NEXT: ret void ; @@ -384,13 +384,14 @@ ; IS__TUNIT____-SAME: (i8* nocapture readonly [[READ_ONLY:%.*]]) { ; IS__TUNIT____-NEXT: call void @byval_not_readonly_1(i8* nocapture readonly byval(i8) [[READ_ONLY]]) #[[ATTR2]] ; IS__TUNIT____-NEXT: call void @byval_not_readnone_1(i8* noalias nocapture readnone byval(i8) [[READ_ONLY]]) +; IS__TUNIT____-NEXT: call void @byval_no_fnarg(i8* nocapture nofree readonly byval(i8) [[READ_ONLY]]) #[[ATTR13:[0-9]+]] ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: readonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@testbyval -; IS__CGSCC____-SAME: (i8* nocapture noundef nonnull readonly dereferenceable(1) [[READ_ONLY:%.*]]) #[[ATTR2]] { +; IS__CGSCC____-SAME: (i8* nocapture noundef nonnull readonly dereferenceable(1) [[READ_ONLY:%.*]]) { ; IS__CGSCC____-NEXT: call void @byval_not_readonly_1(i8* noalias nocapture noundef nonnull readonly byval(i8) dereferenceable(1) [[READ_ONLY]]) #[[ATTR2]] ; IS__CGSCC____-NEXT: call void @byval_not_readnone_1(i8* noalias nocapture noundef nonnull readnone byval(i8) dereferenceable(1) [[READ_ONLY]]) +; IS__CGSCC____-NEXT: call void @byval_no_fnarg(i8* noalias nocapture nofree noundef nonnull readnone byval(i8) dereferenceable(1) [[READ_ONLY]]) #[[ATTR14:[0-9]+]] ; IS__CGSCC____-NEXT: ret void ; call void @byval_not_readonly_1(i8* byval(i8) %read_only) @@ -486,6 +487,7 @@ ; IS__TUNIT____: attributes #[[ATTR10]] = { willreturn writeonly } ; IS__TUNIT____: attributes #[[ATTR11]] = { readonly willreturn } ; IS__TUNIT____: attributes #[[ATTR12]] = { nounwind } +; IS__TUNIT____: attributes #[[ATTR13]] = { nounwind writeonly } ;. ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } @@ -501,4 +503,5 @@ ; IS__CGSCC____: attributes #[[ATTR11]] = { willreturn writeonly } ; IS__CGSCC____: attributes #[[ATTR12]] = { readonly willreturn } ; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind } +; IS__CGSCC____: attributes #[[ATTR14]] = { nounwind writeonly } ;. diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -511,17 +511,12 @@ ; FIXME: Alignment and dereferenceability are not propagated to the argument define void @complicated_args_sret(%struct.X** %b) { ; -; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@complicated_args_sret -; IS__TUNIT_OPM-SAME: (%struct.X** nocapture nofree writeonly [[B:%.*]]) #[[ATTR2]] { -; IS__TUNIT_OPM-NEXT: call void @test_sret(%struct.X* noalias nocapture nofree noundef writeonly sret([[STRUCT_X:%.*]]) align 1073741824 null, %struct.X** nocapture nofree writeonly align 8 [[B]]) #[[ATTR4:[0-9]+]] -; IS__TUNIT_OPM-NEXT: ret void ; -; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@complicated_args_sret -; IS__TUNIT_NPM-SAME: (%struct.X** nocapture nofree writeonly [[B:%.*]]) #[[ATTR2]] { -; IS__TUNIT_NPM-NEXT: call void @test_sret(%struct.X* noalias nocapture nofree noundef writeonly sret([[STRUCT_X:%.*]]) align 1073741824 null, %struct.X** nocapture nofree writeonly align 8 [[B]]) #[[ATTR3:[0-9]+]] -; IS__TUNIT_NPM-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_sret +; IS__TUNIT____-SAME: (%struct.X** nocapture nofree writeonly [[B:%.*]]) #[[ATTR2]] { +; IS__TUNIT____-NEXT: call void @test_sret(%struct.X* noalias nocapture nofree noundef writeonly sret([[STRUCT_X:%.*]]) align 1073741824 null, %struct.X** nocapture nofree writeonly align 8 [[B]]) #[[ATTR3:[0-9]+]] +; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_sret @@ -557,9 +552,26 @@ @S = external global %struct.X define internal void @test_byval(%struct.X* byval(%struct.X) %a) { -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test_byval +; IS__TUNIT_OPM-SAME: (%struct.X* noalias nocapture nofree noundef nonnull writeonly byval([[STRUCT_X:%.*]]) align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR2]] { +; IS__TUNIT_OPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X]], %struct.X* [[A]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: store i8* null, i8** [[G0]], align 8 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test_byval +; IS__TUNIT_NPM-SAME: (i8* [[TMP0:%.*]]) #[[ATTR2]] { +; IS__TUNIT_NPM-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8 +; IS__TUNIT_NPM-NEXT: [[A_PRIV_CAST:%.*]] = bitcast %struct.X* [[A_PRIV]] to i8** +; IS__TUNIT_NPM-NEXT: store i8* [[TMP0]], i8** [[A_PRIV_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X]], %struct.X* [[A_PRIV]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: store i8* null, i8** [[G0]], align 8 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test_byval -; IS__CGSCC_OPM-SAME: (%struct.X* noalias nocapture nofree noundef nonnull writeonly byval([[STRUCT_X:%.*]]) align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR1]] { +; IS__CGSCC_OPM-SAME: (%struct.X* noalias nocapture nofree noundef nonnull writeonly byval([[STRUCT_X:%.*]]) align 8 dereferenceable(8) [[A:%.*]]) #[[ATTR2]] { ; IS__CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X]], %struct.X* [[A]], i32 0, i32 0 ; IS__CGSCC_OPM-NEXT: store i8* null, i8** [[G0]], align 8 ; IS__CGSCC_OPM-NEXT: ret void @@ -570,7 +582,6 @@ ; IS__CGSCC_NPM-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8 ; IS__CGSCC_NPM-NEXT: [[A_PRIV_CAST:%.*]] = bitcast %struct.X* [[A_PRIV]] to i8** ; IS__CGSCC_NPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X]], %struct.X* [[A_PRIV]], i32 0, i32 0 -; IS__CGSCC_NPM-NEXT: store i8* null, i8** [[G0]], align 8 ; IS__CGSCC_NPM-NEXT: ret void ; %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0 @@ -578,15 +589,30 @@ ret void } define void @complicated_args_byval() { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_byval -; IS__TUNIT____-SAME: () #[[ATTR1]] { -; IS__TUNIT____-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@complicated_args_byval +; IS__TUNIT_OPM-SAME: () #[[ATTR3]] { +; IS__TUNIT_OPM-NEXT: call void @test_byval(%struct.X* nocapture nofree noundef nonnull readonly byval([[STRUCT_X:%.*]]) align 8 dereferenceable(8) @S) #[[ATTR3]] +; IS__TUNIT_OPM-NEXT: ret void ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_byval -; IS__CGSCC____-SAME: () #[[ATTR1]] { -; IS__CGSCC____-NEXT: ret void +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@complicated_args_byval +; IS__TUNIT_NPM-SAME: () #[[ATTR3]] { +; IS__TUNIT_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.X* @S to i8** +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i8*, i8** [[S_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: call void @test_byval(i8* [[TMP1]]) #[[ATTR3]] +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_byval +; IS__CGSCC_OPM-SAME: () #[[ATTR1]] { +; IS__CGSCC_OPM-NEXT: call void @test_byval(%struct.X* noalias nocapture nofree noundef nonnull readnone byval([[STRUCT_X:%.*]]) align 8 dereferenceable(8) @S) #[[ATTR6:[0-9]+]] +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_byval +; IS__CGSCC_NPM-SAME: () #[[ATTR1]] { +; IS__CGSCC_NPM-NEXT: ret void ; call void @test_byval(%struct.X* byval(%struct.X) @S) ret void @@ -655,7 +681,7 @@ define void @fixpoint_changed(i32* %p) { ; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind writeonly ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fixpoint_changed -; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR3:[0-9]+]] { +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR4:[0-9]+]] { ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: br label [[FOR_COND:%.*]] ; IS__TUNIT_OPM: for.cond: @@ -867,17 +893,11 @@ } define void @user_as3() { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind willreturn writeonly -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@user_as3 -; IS__TUNIT_OPM-SAME: () #[[ATTR4]] { -; IS__TUNIT_OPM-NEXT: store i32 0, i32 addrspace(3)* @ConstAS3Ptr, align 4 -; IS__TUNIT_OPM-NEXT: ret void -; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@user_as3 -; IS__TUNIT_NPM-SAME: () #[[ATTR3]] { -; IS__TUNIT_NPM-NEXT: store i32 0, i32 addrspace(3)* @ConstAS3Ptr, align 4 -; IS__TUNIT_NPM-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@user_as3 +; IS__TUNIT____-SAME: () #[[ATTR3]] { +; IS__TUNIT____-NEXT: store i32 0, i32 addrspace(3)* @ConstAS3Ptr, align 4 +; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@user_as3 @@ -896,17 +916,11 @@ ret void } define void @user() { -; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind willreturn writeonly -; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@user -; IS__TUNIT_OPM-SAME: () #[[ATTR4]] { -; IS__TUNIT_OPM-NEXT: store i32 0, i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*), align 4 -; IS__TUNIT_OPM-NEXT: ret void -; -; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly -; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@user -; IS__TUNIT_NPM-SAME: () #[[ATTR3]] { -; IS__TUNIT_NPM-NEXT: store i32 0, i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*), align 4 -; IS__TUNIT_NPM-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@user +; IS__TUNIT____-SAME: () #[[ATTR3]] { +; IS__TUNIT____-NEXT: store i32 0, i32* addrspacecast (i32 addrspace(3)* @ConstAS3Ptr to i32*), align 4 +; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@user @@ -1259,8 +1273,8 @@ ; IS__TUNIT_OPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ; IS__TUNIT_OPM: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } ; IS__TUNIT_OPM: attributes #[[ATTR2]] = { argmemonly nofree nosync nounwind willreturn writeonly } -; IS__TUNIT_OPM: attributes #[[ATTR3]] = { argmemonly nofree nosync nounwind writeonly } -; IS__TUNIT_OPM: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn writeonly } +; IS__TUNIT_OPM: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn writeonly } +; IS__TUNIT_OPM: attributes #[[ATTR4]] = { argmemonly nofree nosync nounwind writeonly } ; IS__TUNIT_OPM: attributes #[[ATTR5]] = { willreturn } ;. ; IS__TUNIT_NPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } @@ -1275,6 +1289,7 @@ ; IS__CGSCC_OPM: attributes #[[ATTR3]] = { argmemonly nofree norecurse nosync nounwind writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind willreturn writeonly } ; IS__CGSCC_OPM: attributes #[[ATTR5]] = { willreturn } +; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nounwind willreturn writeonly } ;. ; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree nosync nounwind willreturn } ; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }