[PATCH] D87835: [APFloat] prevent NaN morphing into Inf on conversion (PR43907)

John McCall via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 11:38:06 PDT 2020


rjmccall added a comment.

Well, I went and did a whole investigation here, only to come around to the idea that what you're doing might be the most reasonable thing.

IEEE 754-2008 section 6.2.3 says:

> An operation that propagates a NaN operand to its result and has a single NaN as an input should produce a NaN with the payload of the input NaN if representable in the destination format.
> Conversion of a quiet NaN from a narrower format to a wider format in the same radix, and then back to the same narrower format, should not change the quiet NaN payload in any way except to make it canonical.
> Conversion of a quiet NaN to a floating-point format of the same or a different radix that does not allow the payload to be preserved, shall return a quiet NaN that should provide some language-defined diagnostic information.

Also, operations on sNaN are permitted to preserve sNaN (if the result can represent it) but are not permitted to substitute a qNaN without signaling.

The standard is not super-clear about how to think about payloads, but probably the most useful idea for language implementors would be that they're an unsigned number right-aligned in the significand, consisting of all the bits following the qNaN indicator bit (and thus cannot be zero in an sNaN).

If I were interpreting all this completely in the abstract, I'd say it collectively implies that we really cannot implement this correctly on top of a right-shift, and the right implementation would have to be:

- Check whether the payload is representable (i.e. whether truncating it would change any bits).
- If so, truncate it and then preserve the original qNaN indicator bit.
- If not, use a zero payload, preserve the original qNaN indicator bit, and then set the second-highest bit if we started with an sNaN (to preserve the sNaN).

But x86 double->float conversion does not keep the payload right-shifted or do overflow checks; it just shifts the payload around, dropping any extra bits.  And x86 is probably the most faithful implementation around, and we probably shouldn't have APFloat diverge from its behavior.

So I think the only quibble here is whether it's okay for this to silently produce a qNaN when it might've started with an sNaN.  And arguably the current contract of APFloat is to perform operations as if FP exceptions were disabled, and we'll need a slightly different interface if we want to model exceptions properly.  So I think this might just be fine as-is.

Steve Canon might have further thoughts.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87835/new/

https://reviews.llvm.org/D87835



More information about the llvm-commits mailing list