https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112449
Bug ID: 112449 Summary: Arithmetic operations can produce signaling NaNs Product: gcc Version: 13.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: post+gcc at ralfj dot de Target Milestone: --- According to the IEEE 754 specification, the output of an arithmetic operation can never be a signaling NaN. However, GCC performs optimizations that turn `x * 1.0` into just `x`, and if `x` is a signaling NaN, that means that the multiplication will now (seem to) return a signaling NaN. (proof of GCC performing that transformation: https://godbolt.org/z/scPhn1d8s) It is very common for C compilers to violate this IEEE 754 requirement, but it does open the door to a great many questions. Since GCC evidently does not seem to implement the original IEEE 754 semantics, it would be great to have some documentation on what exactly GCC *does* implement, and in particular under which conditions operations are allowed to return a signaling NaN. So currently, GCC is either buggy because it violates the IEEE 754 spec, or there's a documentation bug in that the actual floating point spec GCC intends to implement is not documented. At least, all I was able to find is https://gcc.gnu.org/wiki/FloatingPointMath, which just says "does not care about signalling NaNs". (I hope this does not mean that any arithmetic operation may arbitrarily produce signaling NaNs. That would be an issue for operations which are sensitive to the difference between quiet NaN and signaling NaN, such as `pow`.) As a point of comparison, LLVM recently added this to their documentation to answer these kinds of questions: https://llvm.org/docs/LangRef.html#behavior-of-floating-point-nan-values. (That PR was authored by me but received input from a lot of people.) LLVM goes further than to just document signaling vs quiet NaN there, since in practice there's some critical code that would break if arithmetic operations returned NaNs with arbitrary bits in their payload (specifically, that would break NaN boxing as performing by some JavaScript engines, or at least make it a lot less efficient since engines would have to re-normalize NaNs after every single operation -- which to my knowledge, they don't actually do in practice).