gcc version 4.9.0 20140109 (experimental) [trunk revision 206459] (GCC) 31 bit zarch glibc testcase test-float: testing float (without inline functions) Failure: llrint (inf): Exception "Invalid operation" not set Failure: llrint (-inf): Exception "Invalid operation" not set Failure: llrint (qNaN): Exception "Invalid operation" not set Failure: llrint_tonearest (inf): Exception "Invalid operation" not set Failure: llrint_tonearest (-inf): Exception "Invalid operation" not set Failure: llrint_tonearest (qNaN): Exception "Invalid operation" not set Failure: llrint_towardzero (inf): Exception "Invalid operation" not set Failure: llrint_towardzero (-inf): Exception "Invalid operation" not set Failure: llrint_towardzero (qNaN): Exception "Invalid operation" not set Failure: llrint_downward (inf): Exception "Invalid operation" not set Failure: llrint_downward (-inf): Exception "Invalid operation" not set Failure: llrint_downward (qNaN): Exception "Invalid operation" not set Failure: llrint_upward (inf): Exception "Invalid operation" not set Failure: llrint_upward (-inf): Exception "Invalid operation" not set Failure: llrint_upward (qNaN): Exception "Invalid operation" not set Failure: llround (inf): Exception "Invalid operation" not set Failure: llround (-inf): Exception "Invalid operation" not set Failure: llround (qNaN): Exception "Invalid operation" not set
Same happens with double and ldouble
Likely to be a bug in the s390-specific libgcc functions (libgcc/config/s390/32), since llrint handles out-of-range values by a simple cast, which is supposed to raise INVALID.
the cast from float to long long is handled by a call to libgcc __fixsfdi function. This function in (libgcc/config/s390/32) does not raise the INVALID exception. According to c99 standard the cast is a conversion from float to integer and "If the value of the integral part cannot be represented by the integer type, the behavior is undefined." Is it correct to rely on the simple cast in glibc? In case of lrint, the cast to long is done via hardware instruction, which sets the INVALID flag. The same happens on 64 bit zarch.
On Tue, 28 Jan 2014, stli at linux dot vnet.ibm.com wrote: > the cast from float to long long is handled by a call to libgcc __fixsfdi > function. This function in (libgcc/config/s390/32) does not raise the INVALID > exception. > According to c99 standard the cast is a conversion from float to integer and > "If the value of the integral part cannot be represented by the integer type, > the behavior is undefined." > Is it correct to rely on the simple cast in glibc? Annex F changes this from undefined to unspecified value plus INVALID exception (F.4 in C99). There may well be a case for working around GCC deficiencies in this area in glibc (conditional on architecture and GCC version needing it) - such problems apply to several architectures, with the details of what needs fixing varying from architecture to architecture - but I'd also encourage reporting libgcc bugs found, and fixing them if possible. (Properly supporting Annex F in GCC is a large amount of work - but I'd like to see it done, and indeed the more recent under-development C bindings for IEEE 754-2008. This particular issue is one of the bits that could be addressed by a reasonably small self-contained patch.)
Fixed in GCC with: http://gcc.gnu.org/ml/gcc-patches/2014-02/msg00399.html