On Sun, 17 Oct 2021, Raoni Fassina Firmino wrote:

> First is the different arguments from the C99 functions.  I think the
> solution is a macro to correct this, like so:
> 
>     #define feclearexcept(excepts) \
>         __builtin_feclearexcept(excepts, FE_DIVBYZERO, FE_INEXACT, \
>                                 FE_INVALID, FE_OVERFLOW, FE_UNDERFLOW)
> 
> That is automatically always included or included when fenv.h is
> included.  Does the preprocessor have this ability? If so, where
> should I put it?

The compiler should not be adding such macros to libc headers.  If libc 
wants to provide such optimizations based on built-in functions, they 
should go in libc headers with an appropriate condition on the compiler 
version.

However, it's better to get things right automatically without needing any 
macros or other header additions at all.  That is, define feclearexcept as 
a built-in function, *without* the extra arguments, and with the back end 
knowing about the FE_* values for the target libc.  Then you can simply 
avoid expanding the function inline when the back end doesn't know both 
the FE_* values and how to use them.

fpclassify is a fundamentally different case, because that's defined by 
the standard to be a *type-generic macro*, whereas feclearexcept is 
defined by the standard to be a *function*.  The example of fpclassify 
should not be followed for feclearexcept, feraiseexcept or fegetround.

> Second is the fallback of the expanders.  When the expanders fail it
> will leave the function call, which is great, but since the argument
> list is different, well, it not is pretty.  There is no execution

If you define __builtin_X to have different arguments to X, it should also 
be defined so it's *always* expanded inline (on all architectures) and 
never falls back to a library function call to X.  (This means, for 
example, not defining __builtin_X at all as a built-in function in cases, 
such as soft float, where you can't expand it inline, so that erroneous 
code trying to call __builtin_X in that case ends up with an undefined 
reference to the __builtin_X symbol.)

Once you avoid having different arguments to the library function, you can 
simply avoid expanding inline whenever the back end lacks the relevant 
information; you don't need to do anything to avoid the built-in function 
existing.

> +@deftypefn {Built-in Function} int __builtin_fegetround (int, int, int, int)
> +This built-in implements the C99 fegetround functionality.  The four int
> +arguments should be the target library's notion of the possible FP rouding
> +modes.  They must be constant values and they must appear in this order:
> +@code{FE_DOWNWARD}, @code{FE_TONEAREST}, @code{FE_TOWARDZERO},
> +@code{FE_UPWARD}.  In other words:

Some architectures have more rounding modes (e.g. FE_TONEARESTFROMZERO).  
Some have fewer.  I think that illustrates the essential flaw of defining 
these functions to take a fixed set of rounding mode macros as arguments.

On the other hand, there is a use for a *different* built-in function to 
get the rounding mode for FLT_ROUNDS, using the fixed set of values for 
FLT_ROUNDS specified in the C standard, and *always expanding inline 
without ever introducing a dependency on libm*.  See bug 30569 and 
<https://gcc.gnu.org/legacy-ml/gcc/2013-11/msg00317.html> regarding that.

-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to