Skip to content

Commit d688816

Browse files
authored
[LangRef] Specify NaN behavior more precisely (#66579)
The current docs don't say anything about the possible set of values returned by a NaN-producing operation. However, there are some coding patterns where such guarantees are strongly desired, such as NaN boxing (as used e.g. in the Spidermonkey JS engine). And in fact the set of possible payloads that can be observed today when compiling code via LLVM is fairly limited (based on what optimizations and backends and hardware currently do) -- but without a documented guarantee, languages compiling to LLVM cannot really rely on this. There was a long discussion about the exact shape that the guarantees should take [on Discourse](https://discourse.llvm.org/t/stronger-floating-point-nan-guarantees/72165). This PR transcribes what I perceived as the consensus, plus some further clarifications: "unless specified otherwise", returned NaNs have a non-deterministic sign, and the payload is generally either the preferred (all-zero) payload or propagates the payload of one of the inputs.
1 parent 1c2634e commit d688816

File tree

1 file changed

+89
-6
lines changed

1 file changed

+89
-6
lines changed

llvm/docs/LangRef.rst

+89-6
Original file line numberDiff line numberDiff line change
@@ -3394,17 +3394,81 @@ Floating-Point Environment
33943394
The default LLVM floating-point environment assumes that traps are disabled and
33953395
status flags are not observable. Therefore, floating-point math operations do
33963396
not have side effects and may be speculated freely. Results assume the
3397-
round-to-nearest rounding mode.
3397+
round-to-nearest rounding mode, and subnormals are assumed to be preserved.
3398+
3399+
Running LLVM code in an environment where these assumptions are not met can lead
3400+
to undefined behavior. The ``strictfp`` and ``denormal-fp-math`` attributes as
3401+
well as :ref:`Constrained Floating-Point Intrinsics <constrainedfp>` can be used
3402+
to weaken LLVM's assumptions and ensure defined behavior in non-default
3403+
floating-point environments; see their respective documentation for details.
3404+
3405+
.. _floatnan:
3406+
3407+
Behavior of Floating-Point NaN values
3408+
-------------------------------------
3409+
3410+
A floating-point NaN value consists of a sign bit, a quiet/signaling bit, and a
3411+
payload (which makes up the rest of the mantissa except for the quiet/signaling
3412+
bit). LLVM assumes that the quiet/signaling bit being set to ``1`` indicates a
3413+
quiet NaN (QNaN), and a value of ``0`` indicates a signaling NaN (SNaN). In the
3414+
following we will hence just call it the "quiet bit"
3415+
3416+
The representation bits of a floating-point value do not mutate arbitrarily; in
3417+
particular, if there is no floating-point operation being performed, NaN signs,
3418+
quiet bits, and payloads are preserved.
3419+
3420+
For the purpose of this section, ``bitcast`` as well as the following operations
3421+
are not "floating-point math operations": ``fneg``, ``llvm.fabs``, and
3422+
``llvm.copysign``. These operations act directly on the underlying bit
3423+
representation and never change anything except possibly for the sign bit.
3424+
3425+
For floating-point math operations, unless specified otherwise, the following
3426+
rules apply when a NaN value is returned: the result has a non-deterministic
3427+
sign; the quiet bit and payload are non-deterministically chosen from the
3428+
following set of options:
3429+
3430+
- The quiet bit is set and the payload is all-zero. ("Preferred NaN" case)
3431+
- The quiet bit is set and the payload is copied from any input operand that is
3432+
a NaN. ("Quieting NaN propagation" case)
3433+
- The quiet bit and payload are copied from any input operand that is a NaN.
3434+
("Unchanged NaN propagation" case)
3435+
- The quiet bit is set and the payload is picked from a target-specific set of
3436+
"extra" possible NaN payloads. The set can depend on the input operand values.
3437+
This set is empty on x86 and ARM, but can be non-empty on other architectures.
3438+
(For instance, on wasm, if any input NaN does not have the preferred all-zero
3439+
payload or any input NaN is an SNaN, then this set contains all possible
3440+
payloads; otherwise, it is empty. On SPARC, this set consists of the all-one
3441+
payload.)
3442+
3443+
In particular, if all input NaNs are quiet (or if there are no input NaNs), then
3444+
the output NaN is definitely quiet. Signaling NaN outputs can only occur if they
3445+
are provided as an input value. For example, "fmul SNaN, 1.0" may be simplified
3446+
to SNaN rather than QNaN. Similarly, if all input NaNs are preferred (or if
3447+
there are no input NaNs) and the target does not have any "extra" NaN payloads,
3448+
then the output NaN is guaranteed to be preferred.
33983449

33993450
Floating-point math operations are allowed to treat all NaNs as if they were
3400-
quiet NaNs. For example, "pow(1.0, SNaN)" may be simplified to 1.0. This also
3401-
means that SNaN may be passed through a math operation without quieting. For
3402-
example, "fmul SNaN, 1.0" may be simplified to SNaN rather than QNaN. However,
3403-
SNaN values are never created by math operations. They may only occur when
3404-
provided as a program input value.
3451+
quiet NaNs. For example, "pow(1.0, SNaN)" may be simplified to 1.0.
34053452

34063453
Code that requires different behavior than this should use the
34073454
:ref:`Constrained Floating-Point Intrinsics <constrainedfp>`.
3455+
In particular, constrained intrinsics rule out the "Unchanged NaN propagation"
3456+
case; they are guaranteed to return a QNaN.
3457+
3458+
Unfortunately, due to hard-or-impossible-to-fix issues, LLVM violates its own
3459+
specification on some architectures:
3460+
- x86-32 without SSE2 enabled may convert floating-point values to x86_fp80 and
3461+
back when performing floating-point math operations; this can lead to results
3462+
with different precision than expected and it can alter NaN values. Since
3463+
optimizations can make contradicting assumptions, this can lead to arbitrary
3464+
miscompilations. See `issue #44218
3465+
<https://github.com/llvm/llvm-project/issues/44218>`_.
3466+
- x86-32 (even with SSE2 enabled) may implicitly perform such a conversion on
3467+
values returned from a function for some calling conventions. See `issue
3468+
#66803 <https://github.com/llvm/llvm-project/issues/66803>`_.
3469+
- Older MIPS versions use the opposite polarity for the quiet/signaling bit, and
3470+
LLVM does not correctly represent this. See `issue #60796
3471+
<https://github.com/llvm/llvm-project/issues/60796>`_.
34083472

34093473
.. _fastmath:
34103474

@@ -9085,6 +9149,9 @@ Semantics:
90859149
""""""""""
90869150

90879151
The value produced is a copy of the operand with its sign bit flipped.
9152+
The value is otherwise completely identical; in particular, if the input is a
9153+
NaN, then the quiet/signaling bit and payload are perfectly preserved.
9154+
90889155
This instruction can also take any number of :ref:`fast-math
90899156
flags <fastmath>`, which are optimization hints to enable otherwise
90909157
unsafe floating-point optimizations:
@@ -11240,6 +11307,11 @@ The '``fptrunc``' instruction casts a ``value`` from a larger
1124011307
This instruction is assumed to execute in the default :ref:`floating-point
1124111308
environment <floatenv>`.
1124211309

11310+
NaN values follow the usual :ref:`NaN behaviors <floatnan>`, except that _if_ a
11311+
NaN payload is propagated from the input ("Quieting NaN propagation" or
11312+
"Unchanged NaN propagation" cases), then the low order bits of the NaN payload
11313+
which cannot fit in the resulting type are discarded.
11314+
1124311315
Example:
1124411316
""""""""
1124511317

@@ -11280,6 +11352,11 @@ The '``fpext``' instruction extends the ``value`` from a smaller
1128011352
*no-op cast* because it always changes bits. Use ``bitcast`` to make a
1128111353
*no-op cast* for a floating-point cast.
1128211354

11355+
NaN values follow the usual :ref:`NaN behaviors <floatnan>`, except that _if_ a
11356+
NaN payload is propagated from the input ("Quieting NaN propagation" or
11357+
"Unchanged NaN propagation" cases), then it is copied to the high order bits of
11358+
the resulting payload, and the remaining low order bits are zero.
11359+
1128311360
Example:
1128411361
""""""""
1128511362

@@ -15092,6 +15169,9 @@ Semantics:
1509215169

1509315170
This function returns the same values as the libm ``fabs`` functions
1509415171
would, and handles error conditions in the same way.
15172+
The returned value is completely identical to the input except for the sign bit;
15173+
in particular, if the input is a NaN, then the quiet/signaling bit and payload
15174+
are perfectly preserved.
1509515175

1509615176
.. _i_minnum:
1509715177

@@ -15307,6 +15387,9 @@ Semantics:
1530715387

1530815388
This function returns the same values as the libm ``copysign``
1530915389
functions would, and handles error conditions in the same way.
15390+
The returned value is completely identical to the first operand except for the
15391+
sign bit; in particular, if the input is a NaN, then the quiet/signaling bit and
15392+
payload are perfectly preserved.
1531015393

1531115394
.. _int_floor:
1531215395

0 commit comments

Comments
 (0)