Date: Mon, 14 Mar 2016 20:23:33 +0100 From: Dimitry Andric <dim@FreeBSD.org> To: Steve Kargl <sgk@troutmask.apl.washington.edu> Cc: freebsd-toolchain@freebsd.org Subject: Re: clang gets numerical underflow wrong, please fix. Message-ID: <65DA5D5E-6BEE-4522-9478-B659724F9CDC@FreeBSD.org> In-Reply-To: <20160314015311.GA28237@troutmask.apl.washington.edu> 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> <20160314015311.GA28237@troutmask.apl.washington.edu>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
On 14 Mar 2016, at 02:53, Steve Kargl <sgk@troutmask.apl.washington.edu> wrote:
...
> #include <fenv.h>
> #include <stdio.h>
>
> int
> main(void)
> {
> int i;
> float x = 1.f;
> i = 0;
> feclearexcept(FE_ALL_EXCEPT);
> do {
> x *= 2;
> i++;
> printf("%d %e\n", i, x);
> } while(!fetestexcept(FE_OVERFLOW));
> if (fetestexcept(FE_OVERFLOW)) printf("FE_UNDERFLOW: ");
> printf("x = %e after %d iterations\n", x, i);
>
> return 0;
> }
>
> You'll get a bunch of invalid output before the OVERFLOW.
>
> % cc -O -o z b.c -lm && ./z | tail
> 1016 7.022239e+305 <-- not a valid float
> 1017 1.404448e+306 <-- not a valid float
> 1018 2.808896e+306 <-- not a valid float
> 1019 5.617791e+306 <-- not a valid float
> 1020 1.123558e+307 <-- not a valid float
> 1021 2.247116e+307 <-- not a valid float
> 1022 4.494233e+307 <-- not a valid float
> 1023 8.988466e+307 <-- not a valid float
> 1024 inf
> FE_UNDERFLOW: x = inf after 1024 iterations
>
> Clang is broken with or without #pragma FENV_ACCESS "on".
Well, it simply doesn't support that #pragma [1], just like gcc [2]. :-(
Apparently compiler writers have trouble with this pragma, don't
implement it, and assume that it's always off. Which then appears to
make most (or all) fenv.h functions into undefined behavior.
That said, making 'x' in your test case volatile helps, e.g. the main
loop was:
fadd %st(0), %st(0)
fstl -20(%ebp)
incl %esi
movl %esi, 4(%esp)
fstpl 8(%esp)
movl $.L.str, (%esp)
calll printf
fnstsw -10(%ebp)
and becomes:
flds -16(%ebp)
fadd %st(0), %st(0)
fstps -16(%ebp)
incl %esi
flds -16(%ebp)
fstpl 8(%esp)
movl %esi, 4(%esp)
movl $.L.str, (%esp)
calll printf
#APP
fnstsw -10(%ebp)
So the fstps causes an overflow when 128 iterations are reached:
[...]
126 8.507059e+37
127 1.701412e+38
128 inf
FE_UNDERFLOW: x = inf after 128 iterations
Maybe this is a usable workaround for libm.
-Dimitry
[1] https://llvm.org/bugs/show_bug.cgi?id=8100
[2] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34678
[-- Attachment #2 --]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.29
iEYEARECAAYFAlbnD7sACgkQsF6jCi4glqO1pgCfV451ofXJJz9udR4DzWyPpPrx
gLkAoK1IOJCSYSGWEaTBBiQ8SUHtdW6u
=F9zX
-----END PGP SIGNATURE-----
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?65DA5D5E-6BEE-4522-9478-B659724F9CDC>
