diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index f542e70bcfee8..89a4a44b7d369 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -3394,17 +3394,81 @@ Floating-Point Environment The default LLVM floating-point environment assumes that traps are disabled and status flags are not observable. Therefore, floating-point math operations do not have side effects and may be speculated freely. Results assume the -round-to-nearest rounding mode. +round-to-nearest rounding mode, and subnormals are assumed to be preserved. + +Running LLVM code in an environment where these assumptions are not met can lead +to undefined behavior. The ``strictfp`` and ``denormal-fp-math`` attributes as +well as :ref:`Constrained Floating-Point Intrinsics ` can be used +to weaken LLVM's assumptions and ensure defined behavior in non-default +floating-point environments; see their respective documentation for details. + +.. _floatnan: + +Behavior of Floating-Point NaN values +------------------------------------- + +A floating-point NaN value consists of a sign bit, a quiet/signaling bit, and a +payload (which makes up the rest of the mantissa except for the quiet/signaling +bit). LLVM assumes that the quiet/signaling bit being set to ``1`` indicates a +quiet NaN (QNaN), and a value of ``0`` indicates a signaling NaN (SNaN). In the +following we will hence just call it the "quiet bit" + +The representation bits of a floating-point value do not mutate arbitrarily; in +particular, if there is no floating-point operation being performed, NaN signs, +quiet bits, and payloads are preserved. + +For the purpose of this section, ``bitcast`` as well as the following operations +are not "floating-point math operations": ``fneg``, ``llvm.fabs``, and +``llvm.copysign``. These operations act directly on the underlying bit +representation and never change anything except possibly for the sign bit. + +For floating-point math operations, unless specified otherwise, the following +rules apply when a NaN value is returned: the result has a non-deterministic +sign; the quiet bit and payload are non-deterministically chosen from the +following set of options: + +- The quiet bit is set and the payload is all-zero. ("Preferred NaN" case) +- The quiet bit is set and the payload is copied from any input operand that is + a NaN. ("Quieting NaN propagation" case) +- The quiet bit and payload are copied from any input operand that is a NaN. + ("Unchanged NaN propagation" case) +- The quiet bit is set and the payload is picked from a target-specific set of + "extra" possible NaN payloads. The set can depend on the input operand values. + This set is empty on x86 and ARM, but can be non-empty on other architectures. + (For instance, on wasm, if any input NaN does not have the preferred all-zero + payload or any input NaN is an SNaN, then this set contains all possible + payloads; otherwise, it is empty. On SPARC, this set consists of the all-one + payload.) + +In particular, if all input NaNs are quiet (or if there are no input NaNs), then +the output NaN is definitely quiet. Signaling NaN outputs can only occur if they +are provided as an input value. For example, "fmul SNaN, 1.0" may be simplified +to SNaN rather than QNaN. Similarly, if all input NaNs are preferred (or if +there are no input NaNs) and the target does not have any "extra" NaN payloads, +then the output NaN is guaranteed to be preferred. Floating-point math operations are allowed to treat all NaNs as if they were -quiet NaNs. For example, "pow(1.0, SNaN)" may be simplified to 1.0. This also -means that SNaN may be passed through a math operation without quieting. For -example, "fmul SNaN, 1.0" may be simplified to SNaN rather than QNaN. However, -SNaN values are never created by math operations. They may only occur when -provided as a program input value. +quiet NaNs. For example, "pow(1.0, SNaN)" may be simplified to 1.0. Code that requires different behavior than this should use the :ref:`Constrained Floating-Point Intrinsics `. +In particular, constrained intrinsics rule out the "Unchanged NaN propagation" +case; they are guaranteed to return a QNaN. + +Unfortunately, due to hard-or-impossible-to-fix issues, LLVM violates its own +specification on some architectures: +- x86-32 without SSE2 enabled may convert floating-point values to x86_fp80 and + back when performing floating-point math operations; this can lead to results + with different precision than expected and it can alter NaN values. Since + optimizations can make contradicting assumptions, this can lead to arbitrary + miscompilations. See `issue #44218 + `_. +- x86-32 (even with SSE2 enabled) may implicitly perform such a conversion on + values returned from a function for some calling conventions. See `issue + #66803 `_. +- Older MIPS versions use the opposite polarity for the quiet/signaling bit, and + LLVM does not correctly represent this. See `issue #60796 + `_. .. _fastmath: @@ -9085,6 +9149,9 @@ Semantics: """""""""" The value produced is a copy of the operand with its sign bit flipped. +The value is otherwise completely identical; in particular, if the input is a +NaN, then the quiet/signaling bit and payload are perfectly preserved. + This instruction can also take any number of :ref:`fast-math flags `, which are optimization hints to enable otherwise unsafe floating-point optimizations: @@ -11240,6 +11307,11 @@ The '``fptrunc``' instruction casts a ``value`` from a larger This instruction is assumed to execute in the default :ref:`floating-point environment `. +NaN values follow the usual :ref:`NaN behaviors `, except that _if_ a +NaN payload is propagated from the input ("Quieting NaN propagation" or +"Unchanged NaN propagation" cases), then the low order bits of the NaN payload +which cannot fit in the resulting type are discarded. + Example: """""""" @@ -11280,6 +11352,11 @@ The '``fpext``' instruction extends the ``value`` from a smaller *no-op cast* because it always changes bits. Use ``bitcast`` to make a *no-op cast* for a floating-point cast. +NaN values follow the usual :ref:`NaN behaviors `, except that _if_ a +NaN payload is propagated from the input ("Quieting NaN propagation" or +"Unchanged NaN propagation" cases), then it is copied to the high order bits of +the resulting payload, and the remaining low order bits are zero. + Example: """""""" @@ -15092,6 +15169,9 @@ Semantics: This function returns the same values as the libm ``fabs`` functions would, and handles error conditions in the same way. +The returned value is completely identical to the input except for the sign bit; +in particular, if the input is a NaN, then the quiet/signaling bit and payload +are perfectly preserved. .. _i_minnum: @@ -15307,6 +15387,9 @@ Semantics: This function returns the same values as the libm ``copysign`` functions would, and handles error conditions in the same way. +The returned value is completely identical to the first operand except for the +sign bit; in particular, if the input is a NaN, then the quiet/signaling bit and +payload are perfectly preserved. .. _int_floor: