Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Mar 2016 17:40:02 -0700
From:      Steve Kargl <sgk@troutmask.apl.washington.edu>
To:        Dimitry Andric <dim@FreeBSD.org>
Cc:        freebsd-toolchain@freebsd.org
Subject:   Re: clang gets numerical underflow wrong, please fix.
Message-ID:  <20160314004002.GA27922@troutmask.apl.washington.edu>
In-Reply-To: <A70D119A-514A-4949-9BCB-CA344650BDB5@FreeBSD.org>
References:  <20160313182521.GA25361@troutmask.apl.washington.edu> <74970883-FE44-47C0-BDA0-92DB0723398A@FreeBSD.org> <20160313201004.GA26343@troutmask.apl.washington.edu> <A70D119A-514A-4949-9BCB-CA344650BDB5@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Mar 14, 2016 at 01:02:20AM +0100, Dimitry Andric wrote:
> On 13 Mar 2016, at 21:10, Steve Kargl <sgk@troutmask.apl.washington.edu> wrote:
> > Thanks for the quick reply.  But, it must be using an 80-bit
> > extended double instead of a double for storage.  This variation
> > 
> > #include <fenv.h>
> > #include <stdio.h>
> > 
> > int
> > main(void)
> > {
> >   int i;
> > //   float x = 1.f;
> >   double x = 1.;
> >   i = 0;
> >   feclearexcept(FE_ALL_EXCEPT);
> >   do {
> >      x /= 2;
> >      i++;
> >   } while(!fetestexcept(FE_UNDERFLOW));
> >   if (fetestexcept(FE_UNDERFLOW)) printf("FE_UNDERFLOW: ");
> >   printf("x = %e after %d iterations\n", x, i);
> > 
> >   return 0;
> > }
> > 
> > yields
> > 
> > % cc -O -o z b.c -lm && ./z
> > FE_UNDERFLOW: x = 0.000000e+00 after 16435 iterations
> > 
> > It should be 1075 iterations.
> > 
> > Note, there is a similar issue with OVERFLOW.  The upshot is
> > that clang on current is probably miscompiling libm.
> 
> With this example, I also get different results from gcc (4.8.5),
> depending on the optimization level:
> 
> $ gcc -O underflow-iter.c -o underflow-iter-gcc -lm
> $ ./underflow-iter-gcc
> FE_UNDERFLOW: x = 0.000000e+00 after 1075 iterations
> $ gcc -O2 underflow-iter.c -o underflow-iter-gcc -lm
> $ ./underflow-iter-gcc
> FE_UNDERFLOW: x = 0.000000e+00 after 16435 iterations
> 
> Similar for the overflow case:
> 
> $ gcc -O overflow-iter.c -o overflow-iter-gcc -lm
> $ ./overflow-iter-gcc
> FE_OVERFLOW: x = inf after 1024 iterations
> $ gcc -O2 overflow-iter.c -o overflow-iter-gcc -lm
> $ ./overflow-iter-gcc
> FE_OVERFLOW: x = inf after 16384 iterations
> 
> Are we depending on some sort of subtle undefined behavior here?

I don't know.  From n1256.pdf, 6.5.5, I can find

    The result of the binary * operator is the product of the operands.

I can't find what happens when one operand is DBL_MAX and the
other is greater than 1.  The result is clearly an overflow 
condition.  Annex F is normative text, which defers to IEC
60559.  F.3 states 

    -- The +, -, *, and / operators provide the IEC 60559 add,
       subtract, multiply, and divide operations.

Annex F contains alot of text about "#pragma STDC FENV_ACCESS ON",
but of course neither gcc nor clang implement this pragma.  In
particular, in F.8.1 one has

    Floating-point arithmetic operations ... may entail side effects
    which optimization shall honor, at least where the state of the
    FENV_ACCESS pragma is ``on''.  The flags ... in the floating-point
    environment may be regarded as global variables; floating-point
    operations (+, *, etc.) implicitly ... write the flags.

However, F.7.1 has

F.7.1 Environment management

    IEC 60559 requires that floating-point operations implicitly raise
    floating-point exception status flags, ...  When the state for the
    FENV_ACCESS pragma (defined in <fenv.h>) is ``on'', these changes
    to the floating-point state are treated as side effects which respect
    sequence points.313)

    313) If the state for the FENV_ACCESS pragma is ``off'', the
         implementation is free to assume the floating-point control
         modes will be the default ones and the floating-point status
         flags will not be tested, which allows certain optimizations
         (see F.8).

So, I'm guessing clang/llvm developers aer going to claim that the
lack of implementation of the FENV_ACCESS pragme means "off".  So,
clang is unsuitable for real floating-point development.

-- 
Steve



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20160314004002.GA27922>