On Sun, 11 Nov 2012, Dimitry Andric wrote:

On 2012-11-11 14:07, Bruce Evans wrote:
...
The pessimality of these functions is another problem.  C99 only requires
...
- if you compile isnan*(x) calls using gcc _without_ including <math.h>,
    then you get annoying (and broken) warnings about implicit function
    declarations being invalid in C99.  This is a bug in clang.  These
    functions are reserved in C99, so some other warning for them would
    be correct, but things warning is wrong in several ways:
    - implicit function declarations are not invalid in C9

Implicit function declarations are invalid in C99, not in C89.  Clang
defaults to C99.  Whether the function is reserved or not, should not
matter.

    - the same warning is printed for -ffreestanding, but these functions
      are not reserved by C99 then.

Again, I don't agree.  Reserved or not is not relevant.  If the above
reasoning was followed, we would never have to include <stdio.h> either,
because all those prototypes would already be implicitly there? :-)

Oops, I thought it was removed later.

    After turning off the broken warning using
    -Wno-implicit-function-declarations, everything works right for these
    function calls, but of course not for others for which you want this
    warning.
So for clang you must include <math.h> for calling these functions,

No, according to the C99 standard you must include <math.h>.  Quoting
7.12.3.4:

 Synopsis:

 #include <math.h>
 int isnan(real-floating  x);

The synopses of all math functions explicitly have the the #include at
the top.

Except with -ffreestanding, isnan() is not reserved and <math.h> might not
exist.  gcc and clang handle this correctly by not converting isnan*()
into a builtin.

[... isnan() gets turned into an extern function that bypasses better
 builtins]

In short, maybe just:

#define isnan __builtin_isnan

? That should cover all cases.  With a fallback for !gcc && !clang,
obviously.  The functions stay behind for backwards compatibility.

This fails for gcc-3.3.3 which I test on (gcc-3.3.3 produces better
libm code in some cases).

Fixing the pessimizations would reduce the ABI problems.  Both libc
and libm should translate to the builtin if it exists and is a real
builtin (not a libcall).  This seems reasonable even without -O, since
C99 doesn't require any functions to exist so nothing should take their
addresses or try to call them as non-macros ('(isnan)(x)').  <math.h>
already has complications to use builtins for 1 set of interfaces only.
The only problems are that it is that it is hard to tell if builtins
exist and are real (there are compiler predefines for the set that
uses builtins but not for most sets).

How is it hard to tell?  Both gcc and clang support those builtins,
unless you want to support very old versions of gcc, which might not
have them.

It is easy to hard-code ifdefs on the compiler name, but only for
a couple of compiler/version combinations, and this is ugly.  Then
there is the problem that some builtins just gives libcalls so they
are useless.  In general, whether a builtin gives a libcall is MD.
__builtin_fma() should be an example.  It should give hardware fma
on ia64 but doesn't.  It should give hardware fma on any future x86
that has fma.  Currently it always gives a libcall so it is useless.

With this, the library functions are never used by new compiles and
are only needed by old applications.  All static copies of them can
be removed, but the .so ones are still needed until the ABI is changed.

When will the library isnanf() have been deprecated long enough to
remove in .so's too?  Maybe it never needed to be preserved, since
old applications will link to old libraries that have it.

I don't think we can ever remove them from libc.so anymore, unless
version bumps are reintroduced. :-)

Sigh, the version has been bumped twice since isnanf() was deprecated.
First from 5 to 6 in 2004 just 3 months days after the deprecation.  Then
from 6 to 7 in 2006.  The log message says that isnan() and others are
done in the "hard" way instead of relying on fpclassify(), for binary
compatibility since we have never bumpled libm's major number, but that
has also been bumped twice since the deprecation.

Using fpclassify() would actually be the hard way for isnan(), since
there is no builtin for it.  Of the functions referred to in the log
message, isinf() is easy using its builtin and isfinite() and isnormal()
are "hard" since they don't have a builtin in gcc.

Summary of the libm builtins:
- isnan(): good but not always used
- isinf(): like isnan()
- isfinite(): only in clang (I don't know if it is more than a libcall)
- isnormal(): like isfinite()
- signbit(): like isnan()
- significand(): only in gcc, and seems to be just a libcall.  This one
  is a nonstandard old-IEEE API while the others are C99.
- fma(): builtin but useless since it is always (?) a libcall.
- sin(), cos(), ...: only in clang, and useless since they are libcalls at
  best.  clang seems to have builtins that expand to libcalls for most
  libc and libm functions.

Bruce
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to