diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index b922636d6c914..5c52ce2986a05 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -16679,7 +16679,7 @@ versions of the intrinsics respect the exception behavior. - qNaN, invalid exception * - ``+0.0 vs -0.0`` - - either one + - +0.0(max)/-0.0(min) - +0.0(max)/-0.0(min) - +0.0(max)/-0.0(min) @@ -16723,21 +16723,30 @@ 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. -Follows the IEEE-754 semantics for minNum, except for handling of -signaling NaNs. This match's the behavior of libm's fmin. +IEEE-754-2008 defines minNum, and it was removed in IEEE-754-2019. As the replacement, IEEE-754-2019 +defines :ref:`minimumNumber `. -If either operand is a NaN, returns the other non-NaN operand. Returns -NaN only if both operands are NaN. If the operands compare equal, -returns either one of the operands. For example, this means that -fmin(+0.0, -0.0) returns either operand. +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. -Unlike the IEEE-754 2008 behavior, this does not distinguish between -signaling and quiet NaN inputs. If a target's implementation follows -the standard and returns a quiet NaN if either input is a signaling -NaN, the intrinsic lowering is responsible for quieting the inputs to -correctly return the non-NaN input (e.g. by using the equivalent of -``llvm.canonicalize``). +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 similiar ones while they are not exact equivalent. Such as x86 implements ``MINPS``, +which implements the semantics of C code ``a`. -Unlike the IEEE-754 2008 behavior, this does not distinguish between -signaling and quiet NaN inputs. If a target's implementation follows -the standard and returns a quiet NaN if either input is a signaling -NaN, the intrinsic lowering is responsible for quieting the inputs to -correctly return the non-NaN input (e.g. by using the equivalent of -``llvm.canonicalize``). +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. + +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 similiar 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. + +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 implemention. .. _i_minimum: @@ -19666,12 +19685,8 @@ The '``llvm.vector.reduce.fmax.*``' intrinsics do a floating-point matches the element-type of the vector input. This instruction has the same comparison semantics as the '``llvm.maxnum.*``' -intrinsic. That is, the result will always be a number unless all elements of -the vector are NaN. For a vector with maximum element magnitude 0.0 and -containing both +0.0 and -0.0 elements, the sign of the result is unspecified. - -If the intrinsic call has the ``nnan`` fast-math flag, then the operation can -assume that NaNs are not present in the input vector. +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. Arguments: """""""""" @@ -19699,12 +19714,8 @@ The '``llvm.vector.reduce.fmin.*``' intrinsics do a floating-point matches the element-type of the vector input. This instruction has the same comparison semantics as the '``llvm.minnum.*``' -intrinsic. That is, the result will always be a number unless all elements of -the vector are NaN. For a vector with minimum element magnitude 0.0 and -containing both +0.0 and -0.0 elements, the sign of the result is unspecified. - -If the intrinsic call has the ``nnan`` fast-math flag, then the operation can -assume that NaNs are not present in the input vector. +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. Arguments: """""""""" @@ -21970,7 +21981,7 @@ This is an overloaded intrinsic. Overview: """"""""" -Predicated floating-point IEEE-754 minNum of two vectors of floating-point values. +Predicated floating-point IEEE-754-2008 minNum of two vectors of floating-point values. Arguments: @@ -22019,7 +22030,7 @@ This is an overloaded intrinsic. Overview: """"""""" -Predicated floating-point IEEE-754 maxNum of two vectors of floating-point values. +Predicated floating-point IEEE-754-2008 maxNum of two vectors of floating-point values. Arguments: @@ -23318,10 +23329,7 @@ result type. If only ``nnan`` is set then the neutral value is ``-Infinity``. This instruction has the same comparison semantics as the :ref:`llvm.vector.reduce.fmax ` intrinsic (and thus the -'``llvm.maxnum.*``' intrinsic). That is, the result will always be a number -unless all elements of the vector and the starting value are ``NaN``. For a -vector with maximum element magnitude ``0.0`` and containing both ``+0.0`` and -``-0.0`` elements, the sign of the result is unspecified. +'``llvm.maxnum.*``' intrinsic). To ignore the start value, the neutral value can be used. @@ -23388,10 +23396,7 @@ result type. If only ``nnan`` is set then the neutral value is ``+Infinity``. This instruction has the same comparison semantics as the :ref:`llvm.vector.reduce.fmin ` intrinsic (and thus the -'``llvm.minnum.*``' intrinsic). That is, the result will always be a number -unless all elements of the vector and the starting value are ``NaN``. For a -vector with maximum element magnitude ``0.0`` and containing both ``+0.0`` and -``-0.0`` elements, the sign of the result is unspecified. +'``llvm.minnum.*``' intrinsic). To ignore the start value, the neutral value can be used. @@ -28061,7 +28066,7 @@ The third argument specifies the exception behavior as described above. Semantics: """""""""" -This function follows the IEEE-754 semantics for maxNum. +This function follows the IEEE-754-2008 semantics for maxNum. '``llvm.experimental.constrained.minnum``' Intrinsic @@ -28093,7 +28098,7 @@ The third argument specifies the exception behavior as described above. Semantics: """""""""" -This function follows the IEEE-754 semantics for minNum. +This function follows the IEEE-754-2008 semantics for minNum. '``llvm.experimental.constrained.maximum``' Intrinsic diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h index fd8784a4c1003..678ed8c8a6fa3 100644 --- a/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -1021,13 +1021,20 @@ enum NodeType { LRINT, LLRINT, - /// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two - /// values. + /// FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values, + /// following IEEE-754 definitions except for signed zero behavior. /// - /// In the case where a single input is a NaN (either signaling or quiet), - /// the non-NaN input is returned. + /// If one input is a signaling NaN, returns a quiet NaN. This matches + /// IEEE-754 2008's minNum/maxNum behavior for signaling NaNs (which differs + /// from 2019). /// - /// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0. + /// These treat -0 as ordered less than +0, matching the behavior of IEEE-754 + /// 2019's minimumNumber/maximumNumber. + /// + /// Note that that arithmetic on an sNaN doesn't consistently produce a qNaN, + /// so arithmetic feeding into a minnum/maxnum can produce inconsistent + /// results. FMAXIMUN/FMINIMUM or FMAXIMUMNUM/FMINIMUMNUM may be better choice + /// for non-distinction of sNaN/qNaN handling. FMINNUM, FMAXNUM, @@ -1041,6 +1048,9 @@ enum NodeType { /// /// These treat -0 as ordered less than +0, matching the behavior of IEEE-754 /// 2019's minimumNumber/maximumNumber. + /// + /// Deprecated, and will be removed soon, as FMINNUM/FMAXNUM have the same + /// semantics now. FMINNUM_IEEE, FMAXNUM_IEEE,