diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index d7963243564a1..2055def4a6e14 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -842,20 +842,20 @@ of different sizes and signs is forbidden in binary and ternary builtins. T __builtin_elementwise_max(T x, T y) return x or y, whichever is larger integer and floating point types For floating point types, follows semantics of maxNum in IEEE 754-2008. See `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_min(T x, T y) return x or y, whichever is smaller integer and floating point types For floating point types, follows semantics of minNum in IEEE 754-2008. See `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_maxnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2008 floating point types semantics (maxNum) with +0.0>-0.0. See `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_minnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2008 floating point types semantics (minNum) with +0.0>-0.0. See `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_add_sat(T x, T y) return the sum of x and y, clamped to the range of integer types representable values for the signed/unsigned integer type. @@ -863,19 +863,19 @@ of different sizes and signs is forbidden in binary and ternary builtins. representable values for the signed/unsigned integer type. T __builtin_elementwise_maximum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types semantics, see `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_minimum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types semantics, see `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_maximumnum(T x, T y) return x or y, whichever is larger. Follows IEEE 754-2019 floating point types semantics, see `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_minimumnum(T x, T y) return x or y, whichever is smaller. Follows IEEE 754-2019 floating point types semantics, see `LangRef - `_ + `_ for the comparison. T __builtin_elementwise_fshl(T x, T y, T z) perform a funnel shift left. Concatenate x and y (x is the most integer types significant bits of the wide value), the combined value is shifted @@ -940,11 +940,11 @@ Let ``VT`` be a vector type and ``ET`` the element type of ``VT``. ET __builtin_reduce_xor(VT a) ^ integer types ET __builtin_reduce_maximum(VT a) return the largest element of the vector. Follows IEEE 754-2019 floating point types semantics, see `LangRef - `_ + `_ for the comparison. ET __builtin_reduce_minimum(VT a) return the smallest element of the vector. Follows IEEE 754-2019 floating point types semantics, see `LangRef - `_ + `_ for the comparison. ======================================= ====================================================================== ================================== diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 041a526b6729f..7d21ecfb2b607 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -17307,93 +17307,45 @@ are perfectly preserved. .. _i_fminmax_family: -'``llvm.min.*``' Intrinsics Comparation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Floating-point min/max intrinsics comparison +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Standard: -""""""""" +LLVM supports three pairs of floating-point min/max intrinsics, which differ +in their handling of :ref:`NaN values `: -IEEE754 and ISO C define some min/max operations, and they have some differences -on working with qNaN/sNaN and +0.0/-0.0. Here is the list: + * ``llvm.minimum`` and ``llvm.maximum``: Return NaN if one the arguments is + NaN. + * ``llvm.minimumnum`` and ``llvm.maximumnum``: Return the other argument if + one of the arguments is NaN. + * ``llvm.minnum`` and ``llvm.maxnum``: For quiet NaNs behaves like + minimumnum/maximumnum. For signaling NaNs, non-deterministically returns + NaN or the other operand. -.. list-table:: - :header-rows: 2 - - * - ``ISO C`` - - fmin/fmax - - fmininum/fmaximum - - fminimum_num/fmaximum_num - - * - ``IEEE754`` - - minNum/maxNum (2008) - - minimum/maximum (2019) - - minimumNumber/maximumNumber (2019) - - * - ``+0.0 vs -0.0`` - - either one - - +0.0 > -0.0 - - +0.0 > -0.0 - - * - ``NUM vs sNaN`` - - qNaN, invalid exception - - qNaN, invalid exception - - NUM, invalid exception - - * - ``qNaN vs sNaN`` - - qNaN, invalid exception - - qNaN, invalid exception - - qNaN, invalid exception - - * - ``NUM vs qNaN`` - - NUM, no exception - - qNaN, no exception - - NUM, no exception - -LLVM Implementation: -"""""""""""""""""""" +Additionally, each of these intrinsics supports two behaviors for signed zeros. +By default, -0.0 is considered smaller than +0.0. If the ``nsz`` flag is +specified, the order is non-deterministic: If the two inputs are zeros with +opposite sign, either input may be returned. -LLVM implements all ISO C flavors as listed in this table, except in the -default floating-point environment exceptions are ignored. The constrained -versions of the intrinsics respect the exception behavior. +The mapping between the LLVM intrinsics, C functions and IEEE 754 functions is +as follows (up to divergences permitted by the usual `NaN rules `): .. list-table:: :header-rows: 1 - :widths: 16 28 28 28 - - * - Operation - - minnum/maxnum - - minimum/maximum - - minimumnum/maximumnum - - * - ``NUM vs qNaN`` - - NUM, no exception - - qNaN, no exception - - NUM, no exception - - * - ``NUM vs sNaN`` - - qNaN, invalid exception - - qNaN, invalid exception - - NUM, invalid exception - - * - ``qNaN vs sNaN`` - - qNaN, invalid exception - - qNaN, invalid exception - - qNaN, invalid exception - - * - ``sNaN vs sNaN`` - - qNaN, invalid exception - - qNaN, invalid exception - - qNaN, invalid exception - - * - ``+0.0 vs -0.0`` - - +0.0(max)/-0.0(min) - - +0.0(max)/-0.0(min) - - +0.0(max)/-0.0(min) - - * - ``NUM vs NUM`` - - larger(max)/smaller(min) - - larger(max)/smaller(min) - - larger(max)/smaller(min) + + * - LLVM intrinsic + - llvm.minnum with nsz flag + - llvm.minimum + - llvm.minimumnum + + * - C function + - fmin + - fminimum + - fminimum_num + + * - IEEE 754 function + - minNum (2008) + - minimum (2019) + - minimumNumber (2019) .. _i_minnum: @@ -17430,30 +17382,36 @@ type. Semantics: """""""""" -Follows the semantics of minNum in IEEE-754-2008, except that -0.0 < +0.0 for the purposes -of this intrinsic. As for signaling NaNs, per the minNum semantics, if either operand is sNaN, -the result is qNaN. This matches the recommended behavior for the libm -function ``fmin``, although not all implementations have implemented these recommended behaviors. -If either operand is a qNaN, returns the other non-NaN operand. Returns NaN only if both operands are -NaN or if either operand is sNaN. Note that arithmetic on an sNaN doesn't consistently produce a qNaN, -so arithmetic feeding into a minnum can produce inconsistent results. For example, -``minnum(fadd(sNaN, -0.0), 1.0)`` can produce qNaN or 1.0 depending on whether ``fadd`` is folded. +If both operands are qNaNs, returns a :ref:`NaN `. If one operand is +qNaN and another operand is a number, returns the number. If both operands are +numbers, returns the lesser of the two arguments. -0.0 is considered to be less +than +0.0 for this intrinsic. + +If an operand is a signaling NaN, then the intrinsic will non-deterministically +either: -IEEE-754-2008 defines minNum, and it was removed in IEEE-754-2019. As the replacement, IEEE-754-2019 -defines :ref:`minimumNumber `. + * Return a :ref:`NaN `. + * Or treat the signaling NaN as a quiet NaN. -If the intrinsic is marked with the nsz attribute, then the effect is as in the definition in C -and IEEE-754-2008: the result of ``minnum(-0.0, +0.0)`` may be either -0.0 or +0.0. +If the ``nsz`` flag is specified, ``llvm.minnum`` with one +0.0 and one +-0.0 operand may non-deterministically return either operand. Contrary to normal +``nsz`` semantics, if both operands have the same sign, the result must also +have the same sign. -Some architectures, such as ARMv8 (FMINNM), LoongArch (fmin), MIPSr6 (min.fmt), PowerPC/VSX (xsmindp), -have instructions that match these semantics exactly; thus it is quite simple for these architectures. -Some architectures have similar ones while they are not exact equivalent. Such as x86 implements ``MINPS``, -which implements the semantics of C code ``a` instead. -For existing libc implementations, the behaviors of fmin may be quite different on sNaN and signed zero behaviors, -even in the same release of a single libm implementation. +The ``llvm.minnum`` intrinsic can be refined into ``llvm.minimumnum``, as the +latter exhibits a subset of behaviors of the former. + +.. warning:: + + If the intrinsic is used without nsz, not all backends currently respect the + specified signed zero ordering. Do not rely on it until this warning has + been removed. See `issue #174730 + `_. .. _i_maxnum: @@ -17490,30 +17448,36 @@ type. Semantics: """""""""" -Follows the semantics of maxNum in IEEE-754-2008, except that -0.0 < +0.0 for the purposes -of this intrinsic. As for signaling NaNs, per the maxNum semantics, if either operand is sNaN, -the result is qNaN. This matches the recommended behavior for the libm -function ``fmax``, although not all implementations have implemented these recommended behaviors. -If either operand is a qNaN, returns the other non-NaN operand. Returns NaN only if both operands are -NaN or if either operand is sNaN. Note that arithmetic on an sNaN doesn't consistently produce a qNaN, -so arithmetic feeding into a maxnum can produce inconsistent results. For example, -``maxnum(fadd(sNaN, -0.0), 1.0)`` can produce qNaN or 1.0 depending on whether ``fadd`` is folded. +If both operands are qNaNs, returns a :ref:`NaN `. If one operand is +qNaN and another operand is a number, returns the number. If both operands are +numbers, returns the greater of the two arguments. -0.0 is considered to be +less than +0.0 for this intrinsic. + +If an operand is a signaling NaN, then the intrinsic will non-deterministically +either: -IEEE-754-2008 defines maxNum, and it was removed in IEEE-754-2019. As the replacement, IEEE-754-2019 -defines :ref:`maximumNumber `. + * Return a :ref:`NaN `. + * Or treat the signaling NaN as a quiet NaN. -If the intrinsic is marked with the nsz attribute, then the effect is as in the definition in C -and IEEE-754-2008: the result of maxnum(-0.0, +0.0) may be either -0.0 or +0.0. +If the ``nsz`` flag is specified, ``llvm.maxnum`` with one +0.0 and one +-0.0 operand may non-deterministically return either operand. Contrary to normal +``nsz`` semantics, if both operands have the same sign, the result must also +have the same sign. -Some architectures, such as ARMv8 (FMAXNM), LoongArch (fmax), MIPSr6 (max.fmt), PowerPC/VSX (xsmaxdp), -have instructions that match these semantics exactly; thus it is quite simple for these architectures. -Some architectures have similar ones while they are not exact equivalent. Such as x86 implements ``MAXPS``, -which implements the semantics of C code ``a>b?a:b``: NUM vs qNaN always return qNaN. ``MAXPS`` can be used -if ``nsz`` and ``nnan`` are given. +When used with the ``nsz`` flag, this intrinsic follows the semantics of +``fmax`` in C and ``maxNum`` in IEEE 754-2008, except for signaling NaN inputs, +which follow :ref:`LLVM's usual signaling NaN behavior ` instead. -For existing libc implementations, the behaviors of fmin may be quite different on sNaN and signed zero behaviors, -even in the same release of a single libm implementation. +The ``llvm.maxnum`` intrinsic can be refined into ``llvm.maximumnum``, as the +latter exhibits a subset of behaviors of the former. + +.. warning:: + + If the intrinsic is used without nsz, not all backends currently respect the + specified signed zero ordering. Do not rely on it until this warning has + been removed. See `issue #174730 + `_. .. _i_minimum: @@ -17550,10 +17514,18 @@ type. Semantics: """""""""" -If either operand is a NaN, returns NaN. Otherwise returns the lesser -of the two arguments. -0.0 is considered to be less than +0.0 for this -intrinsic. Note that these are the semantics specified in the draft of -IEEE 754-2019. +If either operand is a NaN, returns a :ref:`NaN `. Otherwise returns +the lesser of the two arguments. -0.0 is considered to be less than +0.0 for +this intrinsic. + +This intrinsic follows the semantics of ``fminimum`` in C23 and ``minimum`` in +IEEE 754-2019, except for signaling NaN inputs, which follow +:ref:`LLVM's usual signaling NaN behavior ` instead. + +If the ``nsz`` flag is specified, ``llvm.maximum`` with one +0.0 and one +-0.0 operand may non-deterministically return either operand. Contrary to normal +``nsz`` semantics, if both operands have the same sign, the result must also +have the same sign. .. _i_maximum: @@ -17590,10 +17562,18 @@ type. Semantics: """""""""" -If either operand is a NaN, returns NaN. Otherwise returns the greater -of the two arguments. -0.0 is considered to be less than +0.0 for this -intrinsic. Note that these are the semantics specified in the draft of -IEEE 754-2019. +If either operand is a NaN, returns a :ref:`NaN `. Otherwise returns +the greater of the two arguments. -0.0 is considered to be less than +0.0 for +this intrinsic. + +This intrinsic follows the semantics of ``fmaximum`` in C23 and ``maximum`` in +IEEE 754-2019, except for signaling NaN inputs, which follow +:ref:`LLVM's usual signaling NaN behavior ` instead. + +If the ``nsz`` flag is specified, ``llvm.maximum`` with one +0.0 and one +-0.0 operand may non-deterministically return either operand. Contrary to normal +``nsz`` semantics, if both operands have the same sign, the result must also +have the same sign. .. _i_minimumnum: @@ -17636,12 +17616,17 @@ one operand is NaN (including sNaN) and another operand is a number, return the number. Otherwise returns the lesser of the two arguments. -0.0 is considered to be less than +0.0 for this intrinsic. -Note that these are the semantics of minimumNumber specified in -IEEE-754-2019 with the usual :ref:`signaling NaN ` exception. +If the ``nsz`` flag is specified, ``llvm.minimumnum`` with one +0.0 and one +-0.0 operand may non-deterministically return either operand. Contrary to normal +``nsz`` semantics, if both operands have the same sign, the result must also +have the same sign. -It has some differences with '``llvm.minnum.*``': -1)'``llvm.minnum.*``' will return qNaN if either operand is sNaN. -2)'``llvm.minnum*``' may return either one if we compare +0.0 vs -0.0. +This intrinsic follows the semantics of ``fminimum_num`` in C23 and +``minimumNumber`` in IEEE 754-2019, except for signaling NaN inputs, which +follow :ref:`LLVM's usual signaling NaN behavior ` instead. + +This intrinsic behaves the same as ``llvm.minnum`` other than its treatment of +sNaN inputs. .. _i_maximumnum: @@ -17685,12 +17670,17 @@ another operand is a number, return the number. Otherwise returns the greater of the two arguments. -0.0 is considered to be less than +0.0 for this intrinsic. -Note that these are the semantics of maximumNumber specified in -IEEE-754-2019 with the usual :ref:`signaling NaN ` exception. +If the ``nsz`` flag is specified, ``llvm.maximumnum`` with one +0.0 and one +-0.0 operand may non-deterministically return either operand. Contrary to normal +``nsz`` semantics, if both operands have the same sign, the result must also +have the same sign. + +This intrinsic follows the semantics of ``fmaximum_num`` in C23 and +``maximumNumber`` in IEEE 754-2019, except for signaling NaN inputs, which +follow :ref:`LLVM's usual signaling NaN behavior ` instead. -It has some differences with '``llvm.maxnum.*``': -1)'``llvm.maxnum.*``' will return qNaN if either operand is sNaN. -2)'``llvm.maxnum*``' may return either one if we compare +0.0 vs -0.0. +This intrinsic behaves the same as ``llvm.maxnum`` other than its treatment of +sNaN inputs. .. _int_copysign: @@ -20445,9 +20435,14 @@ The '``llvm.vector.reduce.fmax.*``' intrinsics do a floating-point ``MAX`` reduction of a vector, returning the result as a scalar. The return type matches the element-type of the vector input. -This instruction has the same comparison semantics as the '``llvm.maxnum.*``' -intrinsic. If the intrinsic call has the ``nnan`` fast-math flag, then the -operation can assume that NaNs are not present in the input vector. +This instruction has the same comparison and ``nsz`` semantics as the +'``llvm.maxnum.*``' intrinsic. + +If any of the vector elements is a signaling NaN, the intrinsic will +non-deterministically either: + + * Return a :ref:`NaN `. + * Treat the signaling NaN as a quiet NaN. Arguments: """""""""" @@ -20474,9 +20469,14 @@ The '``llvm.vector.reduce.fmin.*``' intrinsics do a floating-point ``MIN`` reduction of a vector, returning the result as a scalar. The return type matches the element-type of the vector input. -This instruction has the same comparison semantics as the '``llvm.minnum.*``' -intrinsic. If the intrinsic call has the ``nnan`` fast-math flag, then the -operation can assume that NaNs are not present in the input vector. +This instruction has the same comparison and ``nsz`` semantics as the +'``llvm.minnum.*``' intrinsic. + +If any of the vector elements is a signaling NaN, the intrinsic will +non-deterministically either: + + * Return a :ref:`NaN `. + * Treat the signaling NaN as a quiet NaN. Arguments: """"""""""