From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id C24213858D20 for ; Thu, 27 Apr 2023 07:18:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C24213858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out2.suse.de (Postfix) with ESMTP id E00EA1FDE1; Thu, 27 Apr 2023 07:18:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1682579932; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Oir4LkM81turQ90/YTxodWKm0jo3ArwlETIAUZCXnR0=; b=OvLPiSneGDNzvo8gH0LCFBeU4UcdDBkeEjJxXsW5kwar8hUXe5aXPOfjPQxXbfKAosWetC lFaXePH+MQ7SBwIURfJ8Kzn+qrzkIREOv9iI36Ov5emj2WUfu6qQH/DMy1xAZLeGbJZR/d SRSKa0FQgJwRLUwFs3/r5LjiGbyhJp0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1682579932; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=Oir4LkM81turQ90/YTxodWKm0jo3ArwlETIAUZCXnR0=; b=AXlQOJSp35mMAZsuX/CcZ2jEzKgqAFbOgi42RnJtfCGpaQ9hsOenH8x5aX/69hEz1qyf/Y epFmIhut+3n9O1Ag== Received: from wotan.suse.de (wotan.suse.de [10.160.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by relay2.suse.de (Postfix) with ESMTPS id 6FDDE2C141; Thu, 27 Apr 2023 07:18:52 +0000 (UTC) Date: Thu, 27 Apr 2023 07:18:52 +0000 (UTC) From: Richard Biener To: Jakub Jelinek cc: Aldy Hernandez , "Joseph S. Myers" , gcc-patches@gcc.gnu.org, Siddhesh Poyarekar , Andrew MacLeod Subject: Re: [PATCH] Add targetm.libm_function_max_error In-Reply-To: Message-ID: References: User-Agent: Alpine 2.22 (LSU 394 2020-01-19) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Wed, 26 Apr 2023, Jakub Jelinek wrote: > Hi! > > As has been discussed before, the following patch adds target hook > for math library function maximum errors measured in ulps. > The default is to return ~0U which is a magic maximum value which means > nothing is known about precision of the match function. > > The first argument is unsigned int because enum combined_fn isn't available > everywhere where target hooks are included but is expected to be given > the enum combined_fn value, although it should be used solely to find out > which kind of match function (say sin vs. cos vs. sqrt vs. exp10) rather > than its variant (f suffix, no suffix, l suffix, f128 suffix, ...), for > which there is the machine_mode argument. > The last argument is a bool, if it is false, the function should return > maximum known error in ulps for a given function (taking -frounding-math > into account if enabled), with 0.5ulps being represented as 0. > If it is true, it is about whether the function can return values outside of > an intrinsic finite range for the function and by how many ulps. > E.g. sin/cos should return result in [-1.,1], if the function is expected > to never return values outside of that finite interval, the hook should > return 0. Similarly for sqrt such range is [-0.,+Inf]. > > The patch implements it for glibc only so far, I hope other maintainers > can submit details for Solaris, musl, perhaps BSDs, etc. > For glibc I've gathered data from: > 1) https://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html > as latest published glibc data > 2) https://www.gnu.org/software/libc/manual/2.22/html_node/Errors-in-Math-Functions.html > as a few years old glibc data > 3) using attached libc-ulps.sh script from glibc git > 4) using attached ulp-tester.c (how to invoke in file comment; tested > both x86_64, ppc64, ppc64le 50M pseudo-random values in all 4 rounding > modes, plus on x86_64 float/double sin/cos using libmvec - see > attached libmvec-wrapper.c as well) > 5) using attached boundary-tester.c to test for whether sin/cos/sqrt return > values outside of the intrinsic ranges for those functions (again, > tested on x86_64, ppc64, ppc64le plus on x86_64 using libmvec as well; > libmvec with non-default rounding modes is pretty much random number > generator it seems) > > The data is added to various hooks, the generic and generic glibc versions > being in targhooks.c so that the various targets can easily override it. > The intent is that the generic glibc version handles most of the stuff > and specific target arch overrides handle the outliers or special cases. > The patch has special case for x86_64 when __FAST_MATH__ is defined (as > one can use in that case either libm or libmvec and we don't know which > one will be used; so it uses maximum of what libm provides and libmvec), > rs6000 (had to add one because cosf has 3ulps on ppc* rather than 1-2ulps > on most other targets; MODE_COMPOSITE_P could be in theory handled in the > generic code too, but as we have rs6000-linux specific function, it can be > done just there), arc-linux (because DFmode sin has 7ulps there compared to > 1ulps on other targets, both in default rounding mode and in others) and > or1k-linux (while DFmode sin has 1ulps there for default rounding mode, > for other rounding modes it has up to 7ulps). > Now, for -frounding-math I'm trying to add a few ulps more because I expect > it to be much less tested, except that for boundary_p I try to use > the numbers I got from the 5) tester. > > So far built on x86_64-linux, powerpc64le-linux, arc-linux and or1k-linux, > ok for trunk if it passes bootstrap/regtest? Humm. Is it worth the trouble? I think if we make use of this it needs to be with -funsafe-math-optimizations (or a new switch?). I'll note that we happily constant fold math functions and there the result will likely differ from a library result. Thus volatile double x = y; assert (sin (y) == sin (x)); will result in many assertions for constant y. In that regard - why should we worry at all? Do the language standards say anything here as to what the compiler is allowed to produce when constant folding or what it can assume for the results? Should we, when simplifying say x = sin (y); if (x <= 1.) simplify it to x = sin (y); x = min (x, 1.); for extra safety? That said - what kind of code do we expect to optimize when producing ranges for math function [operands]? Isn't it just defensive programming that we'd "undo"? Are there any missed-optimization PRs around this? The patch itself looks good to me, but I question whether we want to make use of such info. Thanks, Richard. > 2023-04-26 Jakub Jelinek > > * target.def (libm_function_max_error): New target hook. > * doc/tm.texi.in (TARGET_LIBM_FUNCTION_MAX_ERROR): Add. > * doc/tm.texi: Regenerated. > * targhooks.h (default_libm_function_max_error, > glibc_linux_libm_function_max_error): Declare. > * targhooks.cc: Include case-cfn-macros.h. > (default_libm_function_max_error, > glibc_linux_libm_function_max_error): New functions. > * config/linux.h (TARGET_LIBM_FUNCTION_MAX_ERROR): Redefine. > * config/linux-protos.h (linux_libm_function_max_error): Declare. > * config/linux.cc: Include target.h and targhooks.h. > (linux_libm_function_max_error): New function. > * config/arc/arc.cc: Include targhooks.h and case-cfn-macros.h. > (arc_libm_function_max_error): New function. > (TARGET_LIBM_FUNCTION_MAX_ERROR): Redefine. > * config/i386/i386.cc (ix86_libc_has_fast_function): Formatting fix. > (ix86_libm_function_max_error): New function. > (TARGET_LIBM_FUNCTION_MAX_ERROR): Redefine. > * config/rs6000/rs6000-protos.h > (rs6000_linux_libm_function_max_error): Declare. > * config/rs6000/rs6000-linux.cc: Include target.h, targhooks.h, tree.h > and case-cfn-macros.h. > (rs6000_linux_libm_function_max_error): New function. > * config/rs6000/linux.h (TARGET_LIBM_FUNCTION_MAX_ERROR): Redefine. > * config/rs6000/linux64.h (TARGET_LIBM_FUNCTION_MAX_ERROR): Redefine. > * config/or1k/or1k.cc: Include targhooks.h and case-cfn-macros.h. > (or1k_libm_function_max_error): New function. > (TARGET_LIBM_FUNCTION_MAX_ERROR): Redefine. > > --- gcc/target.def.jj 2023-04-26 08:32:38.118070594 +0200 > +++ gcc/target.def 2023-04-26 08:33:01.752718215 +0200 > @@ -2670,6 +2670,23 @@ DEFHOOK > bool, (int fcode), > default_libc_has_fast_function) > > +DEFHOOK > +(libm_function_max_error, > + "This hook determines expected maximum errors for math functions measured\n\ > +in ulps (units of the last place). 0 means 0.5ulps precision (correctly\n\ > +rounded). ~0U means unknown errors. The @code{combined_fn} @var{cfn}\n\ > +argument should identify just which math built-in function it is rather than\n\ > +its variant, @var{mode} the variant in terms of floating-point machine mode.\n\ > +The hook should also take into account @code{flag_rounding_math} whether it\n\ > +is maximum error just in default rounding mode, or in all possible rounding\n\ > +modes. @var{boundary_p} is @code{true} for maximum errors on intrinsic math\n\ > +boundaries of functions rather than errors inside of the usual result ranges\n\ > +of the functions. E.g.@ the sin/cos function finite result is in between\n\ > +-1.0 and 1.0 inclusive, with @var{boundary_p} true the function returns how\n\ > +many ulps below or above those boundaries result could be.", > + unsigned, (unsigned cfn, machine_mode mode, bool boundary_p), > + default_libm_function_max_error) > + > /* True if new jumps cannot be created, to replace existing ones or > not, at the current point in the compilation. */ > DEFHOOK > --- gcc/doc/tm.texi.in.jj 2023-04-26 08:32:38.116070623 +0200 > +++ gcc/doc/tm.texi.in 2023-04-26 08:33:01.751718229 +0200 > @@ -4004,6 +4004,8 @@ macro, a reasonable default is used. > > @hook TARGET_LIBC_HAS_FAST_FUNCTION > > +@hook TARGET_LIBM_FUNCTION_MAX_ERROR > + > @defmac NEXT_OBJC_RUNTIME > Set this macro to 1 to use the "NeXT" Objective-C message sending conventions > by default. This calling convention involves passing the object, the selector > --- gcc/doc/tm.texi.jj 2023-04-26 08:32:38.090071011 +0200 > +++ gcc/doc/tm.texi 2023-04-26 08:33:01.750718244 +0200 > @@ -5760,6 +5760,21 @@ This hook determines whether a function > @code{(enum function_class)}@var{fcode} has a fast implementation. > @end deftypefn > > +@deftypefn {Target Hook} unsigned TARGET_LIBM_FUNCTION_MAX_ERROR (unsigned @var{cfn}, machine_mode @var{mode}, bool @var{boundary_p}) > +This hook determines expected maximum errors for math functions measured > +in ulps (units of the last place). 0 means 0.5ulps precision (correctly > +rounded). ~0U means unknown errors. The @code{combined_fn} @var{cfn} > +argument should identify just which math built-in function it is rather than > +its variant, @var{mode} the variant in terms of floating-point machine mode. > +The hook should also take into account @code{flag_rounding_math} whether it > +is maximum error just in default rounding mode, or in all possible rounding > +modes. @var{boundary_p} is @code{true} for maximum errors on intrinsic math > +boundaries of functions rather than errors inside of the usual result ranges > +of the functions. E.g.@ the sin/cos function finite result is in between > +-1.0 and 1.0 inclusive, with @var{boundary_p} true the function returns how > +many ulps below or above those boundaries result could be. > +@end deftypefn > + > @defmac NEXT_OBJC_RUNTIME > Set this macro to 1 to use the "NeXT" Objective-C message sending conventions > by default. This calling convention involves passing the object, the selector > --- gcc/targhooks.h.jj 2023-04-26 08:32:38.118070594 +0200 > +++ gcc/targhooks.h 2023-04-26 08:33:01.748718274 +0200 > @@ -219,6 +219,9 @@ extern bool default_libc_has_fast_functi > extern bool no_c99_libc_has_function (enum function_class, tree); > extern bool gnu_libc_has_function (enum function_class, tree); > extern bool bsd_libc_has_function (enum function_class, tree); > +extern unsigned default_libm_function_max_error (unsigned, machine_mode, bool); > +extern unsigned glibc_linux_libm_function_max_error (unsigned, machine_mode, > + bool); > > extern tree default_builtin_tm_load_store (tree); > > --- gcc/targhooks.cc.jj 2023-04-26 08:32:38.118070594 +0200 > +++ gcc/targhooks.cc 2023-04-26 13:21:26.776752299 +0200 > @@ -94,6 +94,7 @@ along with GCC; see the file COPYING3. > #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,70 @@ bsd_libc_has_function (enum function_cla > 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_ALL: > + 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_ALL: > + /* 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_ALL: > + 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)) > --- gcc/config/linux.h.jj 2023-04-26 08:32:38.055071533 +0200 > +++ gcc/config/linux.h 2023-04-26 08:33:01.747718289 +0200 > @@ -212,4 +212,7 @@ see the files COPYING3 and COPYING.RUNTI > # undef TARGET_LIBC_HAS_FUNCTION > # define TARGET_LIBC_HAS_FUNCTION linux_libc_has_function > > +# undef TARGET_LIBM_FUNCTION_MAX_ERROR > +# define TARGET_LIBM_FUNCTION_MAX_ERROR linux_libm_function_max_error > + > #endif > --- gcc/config/linux-protos.h.jj 2023-04-26 08:32:38.055071533 +0200 > +++ gcc/config/linux-protos.h 2023-04-26 08:33:01.747718289 +0200 > @@ -20,3 +20,5 @@ along with GCC; see the file COPYING3. > extern bool linux_has_ifunc_p (void); > > extern bool linux_libc_has_function (enum function_class fn_class, tree); > + > +extern unsigned linux_libm_function_max_error (unsigned, machine_mode, bool); > --- gcc/config/linux.cc.jj 2023-04-26 08:32:38.055071533 +0200 > +++ gcc/config/linux.cc 2023-04-26 08:33:01.747718289 +0200 > @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. > #include "tm.h" > #include "tree.h" > #include "linux-protos.h" > +#include "target.h" > +#include "targhooks.h" > > bool > linux_libc_has_function (enum function_class fn_class, > @@ -38,3 +40,12 @@ linux_libc_has_function (enum function_c > > return false; > } > + > +unsigned > +linux_libm_function_max_error (unsigned cfn, machine_mode mode, > + bool boundary_p) > +{ > + if (OPTION_GLIBC) > + return glibc_linux_libm_function_max_error (cfn, mode, boundary_p); > + return default_libm_function_max_error (cfn, mode, boundary_p); > +} > --- gcc/config/arc/arc.cc.jj 2023-01-02 09:33:00.219738627 +0100 > +++ gcc/config/arc/arc.cc 2023-04-26 14:59:20.440175058 +0200 > @@ -68,6 +68,8 @@ along with GCC; see the file COPYING3. > #include "alias.h" > #include "opts.h" > #include "hw-doloop.h" > +#include "targhooks.h" > +#include "case-cfn-macros.h" > > /* Which cpu we're compiling for (ARC600, ARC601, ARC700). */ > static char arc_cpu_name[10] = ""; > @@ -11808,6 +11810,35 @@ arc_insn_cost (rtx_insn *insn, bool spee > return cost; > } > > +static unsigned > +arc_libm_function_max_error (unsigned cfn, machine_mode mode, > + bool boundary_p) > +{ > +#ifdef OPTION_GLIBC > + bool glibc_p = OPTION_GLIBC; > +#else > + bool glibc_p = false; > +#endif > + if (glibc_p) > + { > + int rnd = flag_rounding_math ? 4 : 0; > + switch (cfn) > + { > + CASE_CFN_SIN_ALL: > + if (!boundary_p && mode == DFmode) > + return 7 + rnd; > + break; > + CASE_CFN_COS_ALL: > + if (!boundary_p && mode == DFmode) > + return 4 + rnd; > + default: > + break; > + } > + return glibc_linux_libm_function_max_error (cfn, mode, boundary_p); > + } > + return default_libm_function_max_error (cfn, mode, boundary_p); > +} > + > #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P > #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p > > @@ -11832,6 +11863,9 @@ arc_insn_cost (rtx_insn *insn, bool spee > #undef TARGET_INSN_COST > #define TARGET_INSN_COST arc_insn_cost > > +#undef TARGET_LIBM_FUNCTION_MAX_ERROR > +#define TARGET_LIBM_FUNCTION_MAX_ERROR arc_libm_function_max_error > + > struct gcc_target targetm = TARGET_INITIALIZER; > > #include "gt-arc.h" > --- gcc/config/i386/i386.cc.jj 2023-04-22 10:23:40.539613820 +0200 > +++ gcc/config/i386/i386.cc 2023-04-26 13:37:56.273154402 +0200 > @@ -25250,7 +25250,8 @@ ix86_libgcc_floating_mode_supported_p > #undef TARGET_MEMTAG_TAG_SIZE > #define TARGET_MEMTAG_TAG_SIZE ix86_memtag_tag_size > > -static bool ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED) > +static bool > +ix86_libc_has_fast_function (int fcode ATTRIBUTE_UNUSED) > { > #ifdef OPTION_GLIBC > if (OPTION_GLIBC) > @@ -25265,6 +25266,56 @@ static bool ix86_libc_has_fast_function > #undef TARGET_LIBC_HAS_FAST_FUNCTION > #define TARGET_LIBC_HAS_FAST_FUNCTION ix86_libc_has_fast_function > > +static unsigned > +ix86_libm_function_max_error (unsigned cfn, machine_mode mode, > + bool boundary_p) > +{ > +#ifdef OPTION_GLIBC > + bool glibc_p = OPTION_GLIBC; > +#else > + bool glibc_p = false; > +#endif > + if (glibc_p) > + { > + /* If __FAST_MATH__ is defined, glibc provides libmvec. */ > + unsigned int libmvec_ret = 0; > + if (!flag_trapping_math > + && flag_unsafe_math_optimizations > + && flag_finite_math_only > + && !flag_signed_zeros > + && !flag_errno_math) > + switch (cfn) > + { > + CASE_CFN_COS_ALL: > + CASE_CFN_SIN_ALL: > + if (!boundary_p) > + { > + /* With non-default rounding modes, libmvec provides > + complete garbage in results. E.g. > + _ZGVcN8v_sinf for 1.40129846e-45f in FE_UPWARD > + returns 0.00333309174f rather than 1.40129846e-45f. */ > + if (flag_rounding_math) > + return ~0U; > + /* https://www.gnu.org/software/libc/manual/html_node/Errors-in-Math-Functions.html > + claims libmvec maximum error is 4ulps. > + My own random testing indicates 2ulps for SFmode and > + 0.5ulps for DFmode, but let's go with the 4ulps. */ > + libmvec_ret = 4; > + } > + break; > + default: > + break; > + } > + unsigned int ret = glibc_linux_libm_function_max_error (cfn, mode, > + boundary_p); > + return MAX (ret, libmvec_ret); > + } > + return default_libm_function_max_error (cfn, mode, boundary_p); > +} > + > +#undef TARGET_LIBM_FUNCTION_MAX_ERROR > +#define TARGET_LIBM_FUNCTION_MAX_ERROR ix86_libm_function_max_error > + > #if CHECKING_P > #undef TARGET_RUN_TARGET_SELFTESTS > #define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests > --- gcc/config/rs6000/rs6000-protos.h.jj 2023-04-26 08:32:38.072071280 +0200 > +++ gcc/config/rs6000/rs6000-protos.h 2023-04-26 08:33:01.748718274 +0200 > @@ -334,6 +334,8 @@ extern unsigned char rs6000_class_max_nr > extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER]; > > extern bool rs6000_linux_float_exceptions_rounding_supported_p (void); > +extern unsigned rs6000_linux_libm_function_max_error (unsigned, machine_mode, > + bool); > > /* Pass management. */ > namespace gcc { class context; } > --- gcc/config/rs6000/rs6000-linux.cc.jj 2023-04-26 08:32:38.055071533 +0200 > +++ gcc/config/rs6000/rs6000-linux.cc 2023-04-26 13:30:57.231335122 +0200 > @@ -23,6 +23,10 @@ along with GCC; see the file COPYING3. > #include "system.h" > #include "coretypes.h" > #include "tm.h" > +#include "target.h" > +#include "targhooks.h" > +#include "tree.h" > +#include "case-cfn-macros.h" > > /* Implement TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P. */ > > @@ -36,3 +40,36 @@ rs6000_linux_float_exceptions_rounding_s > else > return TARGET_HARD_FLOAT; > } > + > +/* Implement TARGET_LIBM_FUNCTION_MAX_ERROR. */ > + > +unsigned > +rs6000_linux_libm_function_max_error (unsigned cfn, machine_mode mode, > + bool boundary_p) > +{ > + if (OPTION_GLIBC) > + { > + int rnd = flag_rounding_math ? 4 : 0; > + switch (cfn) > + { > + CASE_CFN_SQRT_ALL: > + if (!boundary_p && MODE_COMPOSITE_P (mode)) > + return 1 + rnd; > + break; > + CASE_CFN_COS_ALL: > + if (!boundary_p && mode == SFmode) > + return 3 + rnd; > + if (!boundary_p && MODE_COMPOSITE_P (mode)) > + return 4 + rnd; > + break; > + CASE_CFN_SIN_ALL: > + if (!boundary_p && MODE_COMPOSITE_P (mode)) > + return 1 + rnd; > + break; > + default: > + break; > + } > + return glibc_linux_libm_function_max_error (cfn, mode, boundary_p); > + } > + return default_libm_function_max_error (cfn, mode, boundary_p); > +} > --- gcc/config/rs6000/linux.h.jj 2023-01-16 11:52:16.022734963 +0100 > +++ gcc/config/rs6000/linux.h 2023-04-26 15:57:23.636976113 +0200 > @@ -50,6 +50,9 @@ > #undef TARGET_LIBC_HAS_FUNCTION > #define TARGET_LIBC_HAS_FUNCTION linux_libc_has_function > > +#undef TARGET_LIBM_FUNCTION_MAX_ERROR > +#define TARGET_LIBM_FUNCTION_MAX_ERROR rs6000_linux_libm_function_max_error > + > #undef TARGET_OS_CPP_BUILTINS > #define TARGET_OS_CPP_BUILTINS() \ > do \ > --- gcc/config/rs6000/linux64.h.jj 2023-01-16 11:52:16.022734963 +0100 > +++ gcc/config/rs6000/linux64.h 2023-04-26 15:57:32.019853082 +0200 > @@ -288,6 +288,9 @@ extern int dot_symbols; > #undef TARGET_LIBC_HAS_FUNCTION > #define TARGET_LIBC_HAS_FUNCTION linux_libc_has_function > > +#undef TARGET_LIBM_FUNCTION_MAX_ERROR > +#define TARGET_LIBM_FUNCTION_MAX_ERROR rs6000_linux_libm_function_max_error > + > #undef TARGET_OS_CPP_BUILTINS > #define TARGET_OS_CPP_BUILTINS() \ > do \ > --- gcc/config/or1k/or1k.cc.jj 2023-01-16 11:52:16.004735229 +0100 > +++ gcc/config/or1k/or1k.cc 2023-04-26 15:02:23.434480484 +0200 > @@ -44,6 +44,8 @@ > #include "explow.h" > #include "cfgrtl.h" > #include "alias.h" > +#include "targhooks.h" > +#include "case-cfn-macros.h" > > /* These 4 are needed to allow using satisfies_constraint_J. */ > #include "insn-config.h" > @@ -2191,6 +2193,31 @@ or1k_output_mi_thunk (FILE *file, tree t > epilogue_completed = 0; > } > > +static unsigned > +or1k_libm_function_max_error (unsigned cfn, machine_mode mode, > + bool boundary_p) > +{ > +#ifdef OPTION_GLIBC > + bool glibc_p = OPTION_GLIBC; > +#else > + bool glibc_p = false; > +#endif > + if (glibc_p) > + { > + switch (cfn) > + { > + CASE_CFN_SIN_ALL: > + if (!boundary_p && mode == DFmode && flag_rounding_math) > + return 7; > + break; > + default: > + break; > + } > + return glibc_linux_libm_function_max_error (cfn, mode, boundary_p); > + } > + return default_libm_function_max_error (cfn, mode, boundary_p); > +} > + > #undef TARGET_ASM_OUTPUT_MI_THUNK > #define TARGET_ASM_OUTPUT_MI_THUNK or1k_output_mi_thunk > #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK > @@ -2214,6 +2241,9 @@ or1k_output_mi_thunk (FILE *file, tree t > #undef TARGET_HAVE_SPECULATION_SAFE_VALUE > #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed > > +#undef TARGET_LIBM_FUNCTION_MAX_ERROR > +#define TARGET_LIBM_FUNCTION_MAX_ERROR or1k_libm_function_max_error > + > /* Calling Conventions. */ > #undef TARGET_FUNCTION_VALUE > #define TARGET_FUNCTION_VALUE or1k_function_value > > Jakub > -- Richard Biener SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew Myers, Andrew McDonald, Boudien Moerman; HRB 36809 (AG Nuernberg)