https://gcc.gnu.org/g:15fcb2f556f71653518fb4f441f85b1762043e7e
commit r16-1839-g15fcb2f556f71653518fb4f441f85b1762043e7e Author: Yuao Ma <c...@outlook.com> Date: Tue Jul 1 09:50:28 2025 +0200 gcc: middle-end opt for trigonometric pi-based functions builtins This patch partially handled PR118592. This patch builds upon r16-710-g591d3d02664c7b and r16-711-g89935d56f768b4. It introduces middle-end optimizations, such as constant folding, for our trigonometric pi-based function built-ins. gcc/ChangeLog: * fold-const-call.cc (fold_const_call_ss): Constant fold for single arg pi-based trigonometric builtins. (fold_const_call_sss): Constant fold for double arg pi-based trigonometric builtins. * fold-const.cc (negate_mathfn_p): asinpi/atanpi is odd func. (tree_call_nonnegative_warnv_p): acospi always non-neg, asinpi/atanpi non-neg iff arg non-neg. * tree-call-cdce.cc (can_test_argument_range): Add acospi/asinpi. (edom_only_function): Add acospi/asinpi/cospi/sinpi. (get_no_error_domain): Add acospi/asinpi. gcc/testsuite/ChangeLog: * lib/target-supports.exp (foldable_pi_based_trigonometry): New effective target. * gcc.dg/torture/builtin-math-9.c: New test. Signed-off-by: Yuao Ma <c...@outlook.com> Diff: --- gcc/fold-const-call.cc | 36 +++++++++++ gcc/fold-const.cc | 14 +++++ gcc/testsuite/gcc.dg/torture/builtin-math-9.c | 86 +++++++++++++++++++++++++++ gcc/testsuite/lib/target-supports.exp | 14 +++++ gcc/tree-call-cdce.cc | 16 +++++ 5 files changed, 166 insertions(+) diff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc index 8230b83b9296..439bf8044f5e 100644 --- a/gcc/fold-const-call.cc +++ b/gcc/fold-const-call.cc @@ -788,6 +788,36 @@ fold_const_call_ss (real_value *result, combined_fn fn, CASE_CFN_TANH_FN: return do_mpfr_arg1 (result, mpfr_tanh, arg, format); +#if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0) + CASE_CFN_ACOSPI: + CASE_CFN_ACOSPI_FN: + return (real_compare (GE_EXPR, arg, &dconstm1) + && real_compare (LE_EXPR, arg, &dconst1) + && do_mpfr_arg1 (result, mpfr_acospi, arg, format)); + + CASE_CFN_ASINPI: + CASE_CFN_ASINPI_FN: + return (real_compare (GE_EXPR, arg, &dconstm1) + && real_compare (LE_EXPR, arg, &dconst1) + && do_mpfr_arg1 (result, mpfr_asinpi, arg, format)); + + CASE_CFN_ATANPI: + CASE_CFN_ATANPI_FN: + return do_mpfr_arg1 (result, mpfr_atanpi, arg, format); + + CASE_CFN_COSPI: + CASE_CFN_COSPI_FN: + return do_mpfr_arg1 (result, mpfr_cospi, arg, format); + + CASE_CFN_SINPI: + CASE_CFN_SINPI_FN: + return do_mpfr_arg1 (result, mpfr_sinpi, arg, format); + + CASE_CFN_TANPI: + CASE_CFN_TANPI_FN: + return do_mpfr_arg1 (result, mpfr_tanpi, arg, format); +#endif + CASE_CFN_ERF: CASE_CFN_ERF_FN: return do_mpfr_arg1 (result, mpfr_erf, arg, format); @@ -1432,6 +1462,12 @@ fold_const_call_sss (real_value *result, combined_fn fn, CASE_CFN_ATAN2_FN: return do_mpfr_arg2 (result, mpfr_atan2, arg0, arg1, format); +#if MPFR_VERSION >= MPFR_VERSION_NUM(4, 2, 0) + CASE_CFN_ATAN2PI: + CASE_CFN_ATAN2PI_FN: + return do_mpfr_arg2 (result, mpfr_atan2pi, arg0, arg1, format); +#endif + CASE_CFN_FDIM: CASE_CFN_FDIM_FN: return do_mpfr_arg2 (result, mpfr_dim, arg0, arg1, format); diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc index 014f42187932..47492575d006 100644 --- a/gcc/fold-const.cc +++ b/gcc/fold-const.cc @@ -395,10 +395,14 @@ negate_mathfn_p (combined_fn fn) CASE_CFN_ASIN_FN: CASE_CFN_ASINH: CASE_CFN_ASINH_FN: + CASE_CFN_ASINPI: + CASE_CFN_ASINPI_FN: CASE_CFN_ATAN: CASE_CFN_ATAN_FN: CASE_CFN_ATANH: CASE_CFN_ATANH_FN: + CASE_CFN_ATANPI: + CASE_CFN_ATANPI_FN: CASE_CFN_CASIN: CASE_CFN_CASIN_FN: CASE_CFN_CASINH: @@ -432,10 +436,14 @@ negate_mathfn_p (combined_fn fn) CASE_CFN_SIN_FN: CASE_CFN_SINH: CASE_CFN_SINH_FN: + CASE_CFN_SINPI: + CASE_CFN_SINPI_FN: CASE_CFN_TAN: CASE_CFN_TAN_FN: CASE_CFN_TANH: CASE_CFN_TANH_FN: + CASE_CFN_TANPI: + CASE_CFN_TANPI_FN: CASE_CFN_TRUNC: CASE_CFN_TRUNC_FN: return true; @@ -14962,6 +14970,8 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_ACOS_FN: CASE_CFN_ACOSH: CASE_CFN_ACOSH_FN: + CASE_CFN_ACOSPI: + CASE_CFN_ACOSPI_FN: CASE_CFN_CABS: CASE_CFN_CABS_FN: CASE_CFN_COSH: @@ -15006,10 +15016,14 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1, CASE_CFN_ASINH: CASE_CFN_ASINH_FN: + CASE_CFN_ASINPI: + CASE_CFN_ASINPI_FN: CASE_CFN_ATAN: CASE_CFN_ATAN_FN: CASE_CFN_ATANH: CASE_CFN_ATANH_FN: + CASE_CFN_ATANPI: + CASE_CFN_ATANPI_FN: CASE_CFN_CBRT: CASE_CFN_CBRT_FN: CASE_CFN_CEIL: diff --git a/gcc/testsuite/gcc.dg/torture/builtin-math-9.c b/gcc/testsuite/gcc.dg/torture/builtin-math-9.c new file mode 100644 index 000000000000..ff79ee5dfd3b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/builtin-math-9.c @@ -0,0 +1,86 @@ +/* Copyright (C) 1988-2025 Free Software Foundation, Inc. + + Verify that built-in math function constant folding of constant + arguments is correctly performed by the compiler. */ + +/* { dg-do link } */ +/* { dg-require-effective-target foldable_pi_based_trigonometry } */ +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */ + +extern double acospi (double); +extern double asinpi (double); +extern double atanpi (double); +extern double atan2pi (double, double); +extern double cospi (double); +extern double sinpi (double); +extern double tanpi (double); + +/* All references to link_error should go away at compile-time. */ +extern void link_error (void); + +void +test_normal () +{ + if (acospi (0.5) < 0.3333 || acospi (0.5) > 0.3334 || acospi (-0.5) < 0.6666 + || acospi (-0.5) > 0.6667) + link_error (); + + if (asinpi (0.5) < 0.1666 || asinpi (0.5) > 0.1667 || asinpi (-0.5) < -0.1667 + || asinpi (-0.5) > -0.1666) + link_error (); + + if (atanpi (1.0) != 0.25 || atanpi (-1.0) > -0.25) + link_error (); + + if (atan2pi (1.0, 1.0) > 0.2501 || atan2pi (1.0, 1.0) < 0.2499 + || atan2pi (1.0, -1.0) < 0.7499 || atan2pi (1.0, -1.0) > 0.7501) + link_error (); + + if (cospi (1.0 / 3) > 0.5001 || cospi (-1.0 / 3) < 0.4999 + || cospi (4.0 / 3) > -0.4999 || cospi (4.0 / 3) < -0.5001) + link_error (); + + if (sinpi (1.0 / 6) > 0.5001 || sinpi (-1.0 / 6) > -0.4999 + || sinpi (5.0 / 6) < 0.4999 || sinpi (-7.0 / 6) > 0.5001) + link_error (); + + if (tanpi (0.25) != 1.0000 || tanpi (-0.25) != -1.0000 + || tanpi (1.25) != 1.0000 || tanpi (-1.25) != -1.0000) + link_error (); +} + +void +test_corner () +{ + if (__builtin_signbit (acospi (1.0))) + link_error (); + + if (__builtin_signbit (asinpi (0.0)) || !__builtin_signbit (asinpi (-0.0))) + link_error (); + + if (__builtin_signbit (atanpi (0.0)) || !__builtin_signbit (atanpi (-0.0))) + link_error (); + + if (__builtin_signbit (atan2pi (0.0, 0.0)) + || !__builtin_signbit (atan2pi (-0.0, 0.0)) || atan2pi (0.0, -0.0) != 1 + || atan2pi (-0.0, -0.0) != -1) + link_error (); + + if (__builtin_signbit (cospi (0.5)) || __builtin_signbit (cospi (-0.5))) + link_error (); + + if (__builtin_signbit (sinpi (1)) || !__builtin_signbit (sinpi (-1))) + link_error (); + + if (__builtin_signbit (tanpi (2)) || __builtin_signbit (tanpi (-3)) + || !__builtin_signbit (tanpi (5)) || !__builtin_signbit (tanpi (-6))) + link_error (); +} + +int +main () +{ + test_normal (); + test_corner (); + return 0; +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 82e5c31e4994..25ceeea95cb8 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -14495,3 +14495,17 @@ proc check_effective_target_xtensa_atomic { } { #endif }] } + +# Return 1 if pi-based trigonometry function is foldable +# We should remove this after bumping the minimum mpfr version to 4.2.0. +proc check_effective_target_foldable_pi_based_trigonometry { } { + return [check_runtime foldable_pi_based_trigonometry { + int + main () + { + if (!__builtin_constant_p (__builtin_acospi (0.5))) + __builtin_abort (); + return 0; + } + }] +} diff --git a/gcc/tree-call-cdce.cc b/gcc/tree-call-cdce.cc index 712ec7c8920d..649c1e2b9f99 100644 --- a/gcc/tree-call-cdce.cc +++ b/gcc/tree-call-cdce.cc @@ -296,8 +296,12 @@ can_test_argument_range (gcall *call) /* Trig functions. */ CASE_FLT_FN (BUILT_IN_ACOS): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS): + CASE_FLT_FN (BUILT_IN_ACOSPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSPI): CASE_FLT_FN (BUILT_IN_ASIN): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN): + CASE_FLT_FN (BUILT_IN_ASINPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINPI): /* Hyperbolic functions. */ CASE_FLT_FN (BUILT_IN_ACOSH): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSH): @@ -351,13 +355,21 @@ edom_only_function (gcall *call) { CASE_FLT_FN (BUILT_IN_ACOS): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS): + CASE_FLT_FN (BUILT_IN_ACOSPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSPI): CASE_FLT_FN (BUILT_IN_ASIN): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN): + CASE_FLT_FN (BUILT_IN_ASINPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINPI): CASE_FLT_FN (BUILT_IN_COS): CASE_FLT_FN_FLOATN_NX (BUILT_IN_COS): + CASE_FLT_FN (BUILT_IN_COSPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_COSPI): CASE_FLT_FN (BUILT_IN_SIGNIFICAND): CASE_FLT_FN (BUILT_IN_SIN): CASE_FLT_FN_FLOATN_NX (BUILT_IN_SIN): + CASE_FLT_FN (BUILT_IN_SINPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_SINPI): CASE_FLT_FN (BUILT_IN_SQRT): CASE_FLT_FN_FLOATN_NX (BUILT_IN_SQRT): CASE_FLT_FN (BUILT_IN_FMOD): @@ -692,8 +704,12 @@ get_no_error_domain (enum built_in_function fnc) /* Trig functions: return [-1, +1] */ CASE_FLT_FN (BUILT_IN_ACOS): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOS): + CASE_FLT_FN (BUILT_IN_ACOSPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ACOSPI): CASE_FLT_FN (BUILT_IN_ASIN): CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASIN): + CASE_FLT_FN (BUILT_IN_ASINPI): + CASE_FLT_FN_FLOATN_NX (BUILT_IN_ASINPI): return get_domain (-1, true, true, 1, true, true); /* Hyperbolic functions. */