aboutsummaryrefslogtreecommitdiff
path: root/gcc/targhooks.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/targhooks.cc')
-rw-r--r--gcc/targhooks.cc68
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))