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
[email protected]