From a171e98dd2ad5af45f6dbea724d24eff0e8e739c Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 17 Mar 2023 06:46:37 -0400 Subject: [PATCH] Attributor: Add baseline tests for nofpclass Guess at suggestions from D145278 --- llvm/test/Transforms/Attributor/nofpclass.ll | 98 ++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/llvm/test/Transforms/Attributor/nofpclass.ll b/llvm/test/Transforms/Attributor/nofpclass.ll index fa44f3c..9f6514e 100644 --- a/llvm/test/Transforms/Attributor/nofpclass.ll +++ b/llvm/test/Transforms/Attributor/nofpclass.ll @@ -184,6 +184,18 @@ define void @ninf_arg_used_by_callsite_array([2 x [3 x float]] nofpclass(inf) %a ret void } +define void @nofpclass_call_use_after_unannotated_use(float %arg) { +; CHECK-LABEL: define void @nofpclass_call_use_after_unannotated_use +; CHECK-SAME: (float [[ARG:%.*]]) { +; CHECK-NEXT: call void @extern(float [[ARG]]) #[[ATTR5:[0-9]+]] +; CHECK-NEXT: call void @extern(float nofpclass(nan inf) [[ARG]]) +; CHECK-NEXT: ret void +; + call void @extern(float %arg) willreturn nounwind ; < annotate this use + call void @extern(float nofpclass(nan inf) %arg) + ret void +} + define float @mutually_recursive0(float %arg) { ; TUNIT: Function Attrs: nofree nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(all) float @mutually_recursive0 @@ -298,7 +310,7 @@ define float @fcmp_ord_assume_callsite_arg_return(float %arg) { ; CHECK-SAME: (float returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_NAN:%.*]] = fcmp ord float [[ARG]], 0.000000e+00 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_NAN]]) #[[ATTR4:[0-9]+]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_NAN]]) #[[ATTR6:[0-9]+]] ; CHECK-NEXT: call void @extern.use(float [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; @@ -342,13 +354,13 @@ define float @call_noinf_0(float nofpclass(inf) %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @call_noinf_0 ; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR2]] { -; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR5:[0-9]+]] +; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR7:[0-9]+]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_noinf_0 ; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3:[0-9]+]] { -; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR4]] +; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR6]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call float @only_nofpclass_inf_callers(float %arg) @@ -359,13 +371,13 @@ define float @call_noinf_1(float %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define float @call_noinf_1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { -; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR5]] +; TUNIT-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define float @call_noinf_1 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { -; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR4]] +; CGSCC-NEXT: [[RESULT:%.*]] = call float @only_nofpclass_inf_callers(float nofpclass(inf) [[ARG]]) #[[ATTR6]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call float @only_nofpclass_inf_callers(float nofpclass(inf) %arg) @@ -388,13 +400,13 @@ define float @call_noinf_return_0(float %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_0 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { -; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR5]] +; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_0 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { -; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR4]] +; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR6]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call nofpclass(inf) float @only_nofpclass_inf_return_users(float %arg) @@ -405,13 +417,13 @@ define float @call_noinf_return_1(float %arg) { ; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define nofpclass(inf) float @call_noinf_return_1 ; TUNIT-SAME: (float [[ARG:%.*]]) #[[ATTR2]] { -; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR5]] +; TUNIT-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: ret float [[RESULT]] ; ; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define nofpclass(inf) float @call_noinf_return_1 ; CGSCC-SAME: (float [[ARG:%.*]]) #[[ATTR3]] { -; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR4]] +; CGSCC-NEXT: [[RESULT:%.*]] = call nofpclass(inf) float @only_nofpclass_inf_return_users(float [[ARG]]) #[[ATTR6]] ; CGSCC-NEXT: ret float [[RESULT]] ; %result = call nofpclass(inf) float @only_nofpclass_inf_return_users(float %arg) @@ -423,7 +435,7 @@ define float @fcmp_olt_assume_one_0_callsite_arg_return(float %arg) { ; CHECK-SAME: (float returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp one float [[ARG]], 0.000000e+00 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use(float [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; @@ -439,7 +451,7 @@ define float @fcmp_olt_assume_une_0_callsite_arg_return(float %arg) { ; CHECK-SAME: (float returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[IS_NOT_ZERO_OR_NAN:%.*]] = fcmp une float [[ARG]], 0.000000e+00 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_NOT_ZERO_OR_NAN]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use(float [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; @@ -454,9 +466,9 @@ define half @fcmp_assume_issubnormal_callsite_arg_return(half %arg) { ; CHECK-LABEL: define half @fcmp_assume_issubnormal_callsite_arg_return ; CHECK-SAME: (half returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR4]] +; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR6]] ; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use.f16(half [[ARG]]) ; CHECK-NEXT: ret half [[ARG]] ; @@ -490,11 +502,11 @@ define half @fcmp_assume2_callsite_arg_return(half %arg) { ; CHECK-LABEL: define half @fcmp_assume2_callsite_arg_return ; CHECK-SAME: (half returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR4]] +; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR6]] ; CHECK-NEXT: [[NOT_SUBNORMAL_OR_ZERO:%.*]] = fcmp oge half [[FABS]], 0xH0400 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_SUBNORMAL_OR_ZERO]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_SUBNORMAL_OR_ZERO]]) #[[ATTR6]] ; CHECK-NEXT: [[NOT_INF:%.*]] = fcmp oeq half [[ARG]], 0xH7C00 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_INF]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[NOT_INF]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use.f16(half [[ARG]]) ; CHECK-NEXT: ret half [[ARG]] ; @@ -514,8 +526,8 @@ define float @is_fpclass_assume_arg_return(float %arg) { ; CHECK-LABEL: define float @is_fpclass_assume_arg_return ; CHECK-SAME: (float returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CLASS_TEST:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 292) #[[ATTR4]] -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS_TEST]]) #[[ATTR4]] +; CHECK-NEXT: [[CLASS_TEST:%.*]] = call i1 @llvm.is.fpclass.f32(float [[ARG]], i32 noundef 292) #[[ATTR6]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CLASS_TEST]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use(float [[ARG]]) ; CHECK-NEXT: ret float [[ARG]] ; @@ -532,11 +544,11 @@ define half @assume_fcmp_fabs_with_other_fabs_assume(half %arg) { ; CHECK-LABEL: define half @assume_fcmp_fabs_with_other_fabs_assume ; CHECK-SAME: (half returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR4]] +; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR6]] ; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp one half [[FABS]], 0xH0000 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR6]] ; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use.f16(half [[ARG]]) ; CHECK-NEXT: call void @extern.use.f16(half [[FABS]]) ; CHECK-NEXT: ret half [[ARG]] @@ -559,13 +571,13 @@ define half @assume_fcmp_fabs_with_other_fabs_assume_fallback(half %arg) { ; CHECK-LABEL: define half @assume_fcmp_fabs_with_other_fabs_assume_fallback ; CHECK-SAME: (half returned [[ARG:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR4]] +; CHECK-NEXT: [[FABS:%.*]] = call half @llvm.fabs.f16(half [[ARG]]) #[[ATTR6]] ; CHECK-NEXT: [[ONE_INF:%.*]] = fcmp oeq half [[ARG]], 0xH7C00 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[ONE_INF]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[ONE_INF]]) #[[ATTR6]] ; CHECK-NEXT: [[UNRELATED_FABS:%.*]] = fcmp oeq half [[FABS]], 0xH0000 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[UNRELATED_FABS]]) #[[ATTR6]] ; CHECK-NEXT: [[IS_SUBNORMAL:%.*]] = fcmp olt half [[FABS]], 0xH0400 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR4]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[IS_SUBNORMAL]]) #[[ATTR6]] ; CHECK-NEXT: call void @extern.use.f16(half [[ARG]]) ; CHECK-NEXT: call void @extern.use.f16(half [[FABS]]) ; CHECK-NEXT: ret half [[ARG]] @@ -593,7 +605,7 @@ define float @assume_bundles(i1 %c, float %ret) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] ; CHECK: A: -; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR4]] [ "nofpclass"(float [[RET]], i32 3) ] +; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR6]] [ "nofpclass"(float [[RET]], i32 3) ] ; CHECK-NEXT: call void @extern.use(float nofpclass(nan) [[RET]]) ; CHECK-NEXT: ret float [[RET]] ; CHECK: B: @@ -614,3 +626,37 @@ B: call void @extern.use(float %ret) ret float %ret } + +define float @returned_load(ptr %ptr) { +; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn memory(argmem: read) +; CHECK-LABEL: define float @returned_load +; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[PTR:%.*]]) #[[ATTR4:[0-9]+]] { +; CHECK-NEXT: [[LOAD:%.*]] = load float, ptr [[PTR]], align 4 +; CHECK-NEXT: ret float [[LOAD]] +; + %load = load float, ptr %ptr + ret float %load +} + +define float @pass_nofpclass_inf_through_memory(float nofpclass(inf) %arg) { +; TUNIT: Function Attrs: nofree norecurse nosync nounwind willreturn memory(none) +; TUNIT-LABEL: define float @pass_nofpclass_inf_through_memory +; TUNIT-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR2]] { +; TUNIT-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 +; TUNIT-NEXT: store float [[ARG]], ptr [[ALLOCA]], align 4 +; TUNIT-NEXT: [[RET:%.*]] = call float @returned_load(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ALLOCA]]) #[[ATTR7]] +; TUNIT-NEXT: ret float [[RET]] +; +; CGSCC: Function Attrs: nofree nosync nounwind willreturn memory(none) +; CGSCC-LABEL: define float @pass_nofpclass_inf_through_memory +; CGSCC-SAME: (float nofpclass(inf) [[ARG:%.*]]) #[[ATTR3]] { +; CGSCC-NEXT: [[ALLOCA:%.*]] = alloca float, align 4 +; CGSCC-NEXT: store float [[ARG]], ptr [[ALLOCA]], align 4 +; CGSCC-NEXT: [[RET:%.*]] = call float @returned_load(ptr noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ALLOCA]]) #[[ATTR6]] +; CGSCC-NEXT: ret float [[RET]] +; + %alloca = alloca float + store float %arg, ptr %alloca + %ret = call float @returned_load(ptr %alloca) + ret float %ret +} -- 2.7.4