diff options
Diffstat (limited to 'gcc/targhooks.cc')
-rw-r--r-- | gcc/targhooks.cc | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index 51bf3fb..e190369 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-vectorizer.h" #include "options.h" +#include "case-cfn-macros.h" bool default_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, @@ -1903,6 +1904,73 @@ bsd_libc_has_function (enum function_class fn_class, return false; } +unsigned +default_libm_function_max_error (unsigned, machine_mode, bool) +{ + return ~0U; +} + +unsigned +glibc_linux_libm_function_max_error (unsigned cfn, machine_mode mode, + bool boundary_p) +{ + /* Let's use + https://www.gnu.org/software/libc/manual/2.22/html_node/Errors-in-Math-Functions.html + https://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html + with usual values recorded here and significant outliers handled in + target CPU specific overriders. The tables only record default + rounding to nearest, for -frounding-math let's add some extra ulps. + For boundary_p values (say finite results outside of [-1.,1.] for + sin/cos, or [-0.,+Inf] for sqrt etc. let's use custom random testers. */ + int rnd = flag_rounding_math ? 4 : 0; + bool sf = (REAL_MODE_FORMAT (mode) == &ieee_single_format + || REAL_MODE_FORMAT (mode) == &mips_single_format + || REAL_MODE_FORMAT (mode) == &motorola_single_format); + bool df = (REAL_MODE_FORMAT (mode) == &ieee_double_format + || REAL_MODE_FORMAT (mode) == &mips_double_format + || REAL_MODE_FORMAT (mode) == &motorola_double_format); + bool xf = (REAL_MODE_FORMAT (mode) == &ieee_extended_intel_96_format + || REAL_MODE_FORMAT (mode) == &ieee_extended_intel_128_format + || REAL_MODE_FORMAT (mode) == &ieee_extended_motorola_format); + bool tf = (REAL_MODE_FORMAT (mode) == &ieee_quad_format + || REAL_MODE_FORMAT (mode) == &mips_quad_format); + + switch (cfn) + { + CASE_CFN_SQRT: + CASE_CFN_SQRT_FN: + if (boundary_p) + /* https://gcc.gnu.org/pipermail/gcc-patches/2023-April/616595.html */ + return 0; + if (sf || df || xf || tf) + return 0 + rnd; + break; + CASE_CFN_COS: + CASE_CFN_COS_FN: + /* cos is generally errors like sin, but far more arches have 2ulps + for double. */ + if (!boundary_p && df) + return 2 + rnd; + gcc_fallthrough (); + CASE_CFN_SIN: + CASE_CFN_SIN_FN: + if (boundary_p) + /* According to + https://sourceware.org/pipermail/gcc-patches/2023-April/616315.html + seems default rounding sin/cos stay strictly in [-1.,1.] range, + with rounding to infinity it can be 1ulp larger/smaller. */ + return flag_rounding_math ? 1 : 0; + if (sf || df) + return 1 + rnd; + if (xf || tf) + return 2 + rnd; + break; + default: + break; + } + + return default_libm_function_max_error (cfn, mode, boundary_p); +} tree default_builtin_tm_load_store (tree ARG_UNUSED (type)) |