IEEE inexact-flag not working on the Alpha (despite -mieee-with-inexact)?
While testing the portability of the Parma Polyhedra Library, Abramo Bagnara and myself identified the following apparent problem on the Alpha, whereby the division 2/3 made on floats is flagged as exact. Here are the details:
$ cat sf.cc #include <fenv.h> #include <cstdio>
int main() { float x = 2; float y = 3; feclearexcept(FE_INEXACT); x = x / y; printf("%d %.1000g\n", fetestexcept(FE_INEXACT) != 0, x); } $ g++ -v Using built-in specs. Target: alpha-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --disable-libssp --with-long-double-128 --enable-checking=release --build=alpha-linux-gnu --host=alpha-linux-gnu --target=alpha-linux-gnu Thread model: posix gcc version 4.2.4 (Debian 4.2.4-3) $ g++ -mieee-with-inexact sf.cc $ ./a.out 0 0.666666686534881591796875 $ cat /proc/cpuinfo cpu : Alpha cpu model : EV56 cpu variation : 7 cpu revision : 0 cpu serial number : system type : Rawhide system variation : Tincup system revision : 0 system serial number : AY74642662 cycle frequency [Hz] : 399642346 est. timer frequency [Hz] : 1200.00 page size [bytes] : 8192 phys. address bits : 40 max. addr. space # : 127 BogoMIPS : 705.16 kernel unaligned acc : 0 (pc=0,va=0) user unaligned acc : 31 (pc=20000074c18,va=87) platform string : AlphaServer 1200 5/400 4MB cpus detected : 1 cpus active : 1 cpu active mask : 0000000000000001 L1 Icache : 8K, 1-way, 32b line L1 Dcache : 8K, 1-way, 32b line L2 cache : 96K, 3-way, 64b line L3 cache : 4096K, 1-way, 64b line $
We are not sure if this is a bug in GCC (we did search bugzilla though), so we decided to post here before filing a bug report. All the best,
Roberto
Roberto Bagnara bagnara@cs.unipr.it writes:
$ cat sf.cc #include <fenv.h> #include <cstdio>
int main() { float x = 2; float y = 3; feclearexcept(FE_INEXACT); x = x / y; printf("%d %.1000g\n", fetestexcept(FE_INEXACT) != 0, x);
You need to enable the FENV_ACCESS pragma (which is not yet implemented) to get defined behaviour.
Andreas.
Andreas Schwab wrote:
Roberto Bagnara bagnara@cs.unipr.it writes:
$ cat sf.cc #include <fenv.h> #include <cstdio>
int main() { float x = 2; float y = 3; feclearexcept(FE_INEXACT); x = x / y; printf("%d %.1000g\n", fetestexcept(FE_INEXACT) != 0, x);
You need to enable the FENV_ACCESS pragma (which is not yet implemented) to get defined behaviour.
Hi Andreas,
thanks for your message. Do you mean that we need to enable the FENV_ACCESS pragma to get defined behavior only on the Alpha or also elsewhere?
Moreover, do you mean that the FENV_ACCESS pragma is unimplemented for the Alpha or unimplemented everywhere?
I am asking these questions because we observe this behavior only on the Alpha: on all the other platforms we tested things seem to work fine. However, your words could be interpreted as saying that, today, with GCC there is no way to use feclearexcept() and fetestexcept() and get defined behavior. Thanks again,
Roberto
Roberto Bagnara bagnara@cs.unipr.it writes:
thanks for your message. Do you mean that we need to enable the FENV_ACCESS pragma to get defined behavior only on the Alpha or also elsewhere?
See the C standard, 7.6.1 The FENV_ACCESS pragma.
The FENV_ACCESS pragma provides a means to inform the implementation when a program might access the floating-point environment to test floating-point status flags or run under non-default floating-point control modes. ... If part of a program tests floating-point status flags, sets floating-point control modes, or runs under non-default mode settings, but was translated with the state for the FENV_ACCESS pragma ‘‘off’’, the behavior is undefined.
Andreas.
Andreas Schwab wrote:
Roberto Bagnara bagnara@cs.unipr.it writes:
thanks for your message. Do you mean that we need to enable the FENV_ACCESS pragma to get defined behavior only on the Alpha or also elsewhere?
See the C standard, 7.6.1 The FENV_ACCESS pragma.
The FENV_ACCESS pragma provides a means to inform the implementation when a program might access the floating-point environment to test floating-point status flags or run under non-default floating-point control modes. ... If part of a program tests floating-point status flags, sets floating-point control modes, or runs under non-default mode settings, but was translated with the state for the FENV_ACCESS pragma ‘‘off’’, the behavior is undefined.
I did read that, but I thought that, from a practical (i.e., not legal) standpoint, the issues were constant-propagation and other similar transformations, that is, something that seems unrelated to our testcase.
Sorry if I insist, and thank you in advance for clarifying. Do you mean both the following?
1) Any program calling fetestexcept() without setting FENV_ACCESS "on" has undefined behavior, not only as far as the standard is concerned, but also in the GCC concrete world (meaning that GCC may really do no matter what if fetestexcept() is invoked with FENV_ACCESS "off").
2) GCC does not implement a way to set FENV_ACCESS "on" so that fetestexcept() can be used reliably.
I guess I misunderstood you either on point 1 or on point 2 or on both, because otherwise we would have that any program compiled with GCC and calling fetestexcept() has (in concrete terms) undefined behavior. All the best,
Roberto
On Thu, 18 Sep 2008, Andreas Schwab wrote:
Roberto Bagnara bagnara@cs.unipr.it writes:
$ cat sf.cc #include <fenv.h> #include <cstdio>
int main() { float x = 2; float y = 3; feclearexcept(FE_INEXACT); x = x / y; printf("%d %.1000g\n", fetestexcept(FE_INEXACT) != 0, x);
You need to enable the FENV_ACCESS pragma (which is not yet implemented) to get defined behaviour.
It's more complicated than that.
In theory, GCC represents parts of the FENV_ACCESS pragma with the options -ftrapping-math and -frounding-math, enables -ftrapping-math by default, disables -frounding-math by default, documents that -frounding-math will determine the default setting of FENV_ACCESS in future, and documents that -frounding-math is experimental and that some optimizations affected by rounding mode may not have been found and disabled.
In theory, -ftrapping-math should suffice to ensure the correct set of exceptions are generated between any two calls to fenv.h functions (or between calls to other functions that might call those functions indirectly). (As per C99 Annex F, there is no requirement to generate an exception the correct number of times as long as it's generated at least once iff it would be generated at least once in the abstract machine.)
In practice, there are many cases where -ftrapping-math does not cause the right exceptions to be generated, or where spurious exceptions are generated, and a few open PRs for such cases. Inexact folding without generating the inexact exception is only one example. Furthermore, the results will vary between GCC versions and target processors and optimization levels.
It's my suspicion that if we implement everything needed to preserve exceptions properly in accordance with Annex F, it will turn out there is a significant performance cost to the default -ftrapping-math mode and we will need to consider whether the option can be split up so parts can be disabled selectively.
Roberto Bagnara wrote:
#include <fenv.h> #include <cstdio>
int main() { float x = 2; float y = 3; feclearexcept(FE_INEXACT); x = x / y; printf("%d %.1000g\n", fetestexcept(FE_INEXACT) != 0, x); }
Is this a way of testing whether the division is performed at compile time? Do you call it a bug if constant propagation occurs when you don't take action to prevent it?
Tim Prince wrote:
Roberto Bagnara wrote:
#include <fenv.h> #include <cstdio>
int main() { float x = 2; float y = 3; feclearexcept(FE_INEXACT); x = x / y; printf("%d %.1000g\n", fetestexcept(FE_INEXACT) != 0, x); }
Is this a way of testing whether the division is performed at compile time? Do you call it a bug if constant propagation occurs when you don't take action to prevent it?
Hi Tim,
I am not sure I understand your message. However, before mailing I did check that constant propagation is not an issue by checking the generated assembly:
ldq $27,feclearexcept($29) !literal!2 jsr $26,($27),0 !lituse_jsr!2 ldah $29,0($26) !gpdisp!3 lda $29,0($29) !gpdisp!3 lds $f11,20($15) lds $f10,16($15) divs/sui $f11,$f10,$f12 trapb cpys $f12,$f12,$f10 sts $f10,20($15) ldah $16,32($31) ldq $27,fetestexcept($29) !literal!4 jsr $26,($27),0 !lituse_jsr!4
Note that I am not compiling with optimizations and that the divs/sui opcode is generated. All the best,
Roberto
participants (5)
-
Andreas Schwab -
Joseph S. Myers -
Richard Henderson -
Roberto Bagnara -
Tim Prince