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>