[Cfp-interest 2805] Subnormals and flush-to-zero and IEC 60559 conformance macros

Hans Boehm boehm at acm.org
Thu Jul 20 14:15:14 PDT 2023


[ I previously sent this to a smaller group, but would also appreciate
feedback from this group as well. Was it considered that IEC 60559
conformance is essentially not determinable at compile time? ]

While discussing my WG21/SG6 proposal to deprecate fenv-based rounding in
C++ (wg21.link/p2746), Matthias Kretz raised the issue of code run in
flush-to-zero mode. I had thought that had largely disappeared for
CPU-executed code, but it actually seems quite common on X86. Based on a
quick look, ARM is similar, though RISC-V is currently not, I think.

I investigated this while trying to generate the next paper revision (which
will be delayed, partly as a result). The current draft of my conclusions
is below. But my overall conclusion is that this is a bit of a mess, and
probably one I want to largely ignore for now. But I'd appreciate any
insights you may have. (Feel free to forward, if you like. I can also post
to the cfp and sg6 groups, but I wanted to ask you for feedback first.)

It appears to me that the 60559-conformance macros defined in C23 are
essentially unimplementable on modern x86 platforms, because there is no
way to know until runtime whether the hardware is conformant; it depends on
what code was run at startup-time, or possibly later if somebody decides to
switch the flush-to-zero bits in the middle. And the macros may or may not
indicate what the programmer actually wants to know. I expect that some
code will want to treat a 60559-except-flush-to-zero platform as
conformant, and clearly some will not.

Current draft of summary for wg21.link/p2746:

It was pointed out that it is common to disable
subnormals/denormals/gradual underflow on x86, and changing this locally
around cr_ library calls is probably infeasible.

Further investigation showed:

Implementations other than x87 (SSE and later) commonly need
software assist for gradual underflow, potentially making performance
unacceptable when dealing with many near-zero values. Gcc provides the
-mdaz-ftz (denormals are zero, flush to zero) flag for this purpose. It
appears to be implemented entirely by including code that sets a hardware
flag; constants are unaffected.

This seems to be most commonly enabled by -ffast-math.

This mode is not IEC 60559 conformant. The C standard also  says “IEC 60559
arithmetic (with default exception handling) always treats subnormal
numbers as nonzero”. Clang does not support it as an explicit flag, though
-ffast-math may have a similar effect. (This seems to depend on
installation details.) As one might expect, it is highly controversial. It
is also brittle since it can apparently affect code not expecting to run in
this mode. (See e.g.
https://moyix.blogspot.com/2022/09/someones-been-messing-with-my-subnormals.html,
which I found through a clang discussion.)

It is hard to make compiler-provided information about 60559 conformance
accurate, given that behavior with respect to subnormals is controlled by a
runtime flag. Gcc sets __STDC_IEC_559__ with -mdaz-ftz, but not with
-ffast-math.

My current conclusion is that this is a bit of a mess, which we should
largely try to dodge. A standard-conforming implementation should not claim
to be 60559 compliant unless it can turn off flush-to-zero for those
operations.

Hans
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.oakapple.net/pipermail/cfp-interest/attachments/20230720/0a29e924/attachment.htm>


More information about the Cfp-interest mailing list