svn commit: r253215 - head/lib/msun/src

David Schultz das at FreeBSD.org
Tue Jul 30 07:02:31 UTC 2013


On Mon, Jul 29, 2013, David Chisnall wrote:
> On 29 Jul 2013, at 08:05, David Schultz <das at FreeBSD.ORG> wrote:
> 
> > On Thu, Jul 11, 2013, David Chisnall wrote:
> >> +static __inline int
> >> +__inline_isnan(double __x)
> >> +{
> >> +
> >> +	return (__x != __x);
> >> +}
> >> +
> >> +static __inline int
> >> +__inline_isnanf(float __x)
> >> +{
> >> +
> >> +	return (__x != __x);
> >> +}
> >> +
> >> +static __inline int
> >> +__inline_isnanl(long double __x)
> >> +{
> >> +
> >> +	return (__x != __x);
> >> +}
> > 
> > This has already been covered at greater length, but I believe
> > this part is incorrect.  Relational operators can raise an invalid
> > exception when one of the arguments is a NaN -- even a quiet NaN.
> > Raising an exception is optional in C99 (7.12.14) and required in
> > IEEE-754... in practice, it tends to be platform- and compiler-
> > specific.
> > 
> > That is the whole reason the is* macros are defined by the
> > standard in the first place, and also why we didn't use the
> > trivial implementation above.  The is* macros are required to not
> > raise an exception.
> 
> What would you suggest replacing them with?  Note that currently LLVM iR doesn't provide any way of distinguishing the != comparison from something that is guaranteed not to raise an exception.  I don't know how this works in GIMPLE, althouhg I'd imagine that, since gcc has a working Fortran front end, there is some better support for it.

I'm not sure what the inlines here were supposed to achieve, but I
think the ideal implementation would be a compiler intrinsic, with
a fallback of the libm functions if there's no working compiler
support.  As I recall, gcc has a __builtin_isnan() and macros to
test whether __builtin_nan() exists.  Presumably it wouldn't be too
hard to do the same thing in clang.

> > P.S. It would be great if clang implemented the FENV_ACCESS pragma
> > and provided an intrinsic that produced a fast inline isnan() when
> > the pragma is off, and the full, correct one when the pragma is on.
> 
> 
> I almost agree, but C is a really terrible language for mathematical work and I'd prefer that people just used Fortran instead of trying to force C to be Fortran.

Fortran has its own problems and isn't very well supported.  But
for what it's worth, C++ is actually a good choice for
high-performance numerics, IMO, mainly because of operator
overloading and generics.  I can write a function that looks like
actual math, and call it with a float, a double, or even an
arbitrary-precision mpfr_t, and it just works.  In C, on the other
hand, they added all this "type-generic arithmetic" and complex
number nonsense that's of very limited interest. In a better
language, that functionality could have been implemented as a
third-party library instead of as a built-in part of the language.
So in that sense, I agree with you that C went too far with
trying to compete with Fortran...

FENV_ACCESS is more reasonable, though.  It basically says that
sophisticated users ought to be able to take advantage of the IEEE
floating-point features that nearly all hardware FPUs support,
without having the compiler mess things up.  Meanwhile, there's a
second mode for users who don't care, where the optimizer is
allowed to make a lot more assumptions.  Before C99, compilers
tended to have some muddled combination of the two extremes, which
is bad for everyone.  Unfortunately, only the commercial compilers
actually implement FENV_ACCESS these days...

> In particular, take a look in the C11 spec for the semantics of this:
> 
> _Atomic(double) x = ...;
> x += 1;
> 
> It's quite astonishingly horrible.  We don't implement it correctly in clang, and I hope never to have to.  

I hope it does something horrible to the programmer who thought
of the idea of atomic double-precision arithmetic.


More information about the svn-src-all mailing list