[llvm] LangRef: Clarify llvm.minnum and llvm.maxnum about sNaN and signed zero (PR #112852)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Sun Dec 8 07:02:55 PST 2024
================
@@ -16574,21 +16574,34 @@ type.
Semantics:
""""""""""
+Follows the semantics of mininumNumber in IEEE-754-2019, except for signaling NaNs. If either operand
+is an sNaN, the result is always a 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.
+
+IEEE-754-2008 defines minNum, and it is removed in IEEE-754-2019. The behavior of this intrinsic is
+stricter than minNum in IEEE-754-2008, where either zero may be returned. To achieve the same permissiveness,
+the backend may implement the nsz attribute, and one may use the nsz attribute.
+
+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.
+
+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<b?a:b`: NUM vs qNaN always return qNaN. `MINPS` can be used
+if `nsz` and `nnan` are given.
-Follows the IEEE-754 semantics for minNum, except for handling of
-signaling NaNs. This match's the behavior of libm's fmin.
-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.
+In the real libc worlds, the bebhaviors of fmin may be quite different on sNaN and signed zero behaviors,
+even in the same release of a single libm implemention.
-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``).
+Note that arithmetic on an sNaN doesn't consistently produce a qNaN,
+so arithmetic feeding into a minnum 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.
----------------
arsenm wrote:
This should just link to the section on signaling nan semantics in the IR
https://github.com/llvm/llvm-project/pull/112852
More information about the llvm-commits
mailing list