svn commit: r242879 - in head/lib: libc/gen msun/src

Bruce Evans brde at optusnet.com.au
Sun Nov 11 13:07:57 UTC 2012


On Sat, 10 Nov 2012, Dimitry Andric wrote:

> On 2012-11-10 22:43, Konstantin Belousov wrote:
>> On Sat, Nov 10, 2012 at 09:22:10PM +0000, Dimitry Andric wrote:
> ...
>>> Author: dim
>>> Date: Sat Nov 10 21:22:10 2012
>>> New Revision: 242879
>>> URL: http://svnweb.freebsd.org/changeset/base/242879
>>> 
>>> Log:
>>>    Only define isnan, isnanf, __isnan and __isnanf in libc.so, not in
>>>    libc.a and libc_p.a.  In addition, define isnan in libm.a and libm_p.a,
>>>    but not in libm.so.
>>> 
>>>    This makes it possible to statically link executables using both isnan
>>>    and isnanf with libc and libm.
> ...
>> So you broke ABI for libm ?
>
> No, both libc.so and libm.so are the same as before.  Only the .a files
> are changed.
>
> I should probably have made the commit message more clear, sorry about
> that.

Hopefully "fixed" instead of "broke" (except the .so files are unchanged
so they are still broken).  I use the hack of ifdefing out the definition
of __isnanf() in libm.  isnan() is already ifdefed out there.  I didn't
touch the compatibility cruft weak references to isnanf() there -- libc
has it too, so it is not needed any more than isnan() here.

The pessimality of these functions is another problem.  C99 only requires
the isnan() API, and only requires it to be a macro.  gcc-4.2.1 and clang
(but not gcc-3.3.3 which I often test with) provide good builtins for
these functions.  But the FreeBSD implementation destroys use of the
builtins with some help from the ABI:
- if you compile isnan*(x) calls using gcc _without_ including <math.h>,
   then everything works right -- they builtins are used and are optimal
- 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
   - the same warning is printed for -ffreestanding, but these functions
     are not reserved by C99 then.
   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, and
of course for other FP library features, omitting the include is even
more impractical.  This gives the pessimizations:
- the isnan() macro translates to isnan() for doubles, __isnanf() for
   floats and __isnanfl() for long doubles.  The null translation for
   doubles gives the builtin and it works as above, but the other
   translations give the library functions with their underscored
   spelling.  Compilers don't understand this spelling, so they don't
   give the builtins.  So isnan() is pessimized when applied to floats
   and long doubles.

OTOH, if you forget that isnan() is type-generic and spell it isnanf()
or isnanl(), then the float and long double cases mostly work right
again:
- same behaviour if <math.h> is not included (and -O is used)
- if <math.h> is included, then it declares isnanf() but not isnanl(),
   since only the former is compatibility cruft and has an extern function.
   So isnanf() always works and the builtin is always used with -O and
   and the extern function is used without -O.  But isnanl() causes the
   following problems:
   - -Wimplicit* warning
   - linkage failure without -O.

Another problem is that the extern __isnanl() is broken on x86, but the
builtin works.  The extern functions do bit tests that are rather slow
but not slow enough to be correct (they don't check for pseudo-numbers
which the hardware treats as NaNs), but the builtin does a simple x != x
test which is probably optimal, and works.

Similarly for some other macros (they convert to spelling that compilers
don't understand, and at least the classification macros are broken on
psudo-numbers, but now the broken cases are mostly ones for which the
builtins don't exist or is broken).

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).

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.

Bruce


More information about the svn-src-head mailing list