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 <c8ef@outlook.com>
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);
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);
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:
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;
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:
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:
--- /dev/null
+/* 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;
+}
#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;
+ }
+ }]
+}
/* 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):
{
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):
/* 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. */