On 14 Mar 2016, at 02:53, Steve Kargl <s...@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
signature.asc
Description: Message signed with OpenPGP using GPGMail