[llvm] LangRef: Clarify llvm.minnum and llvm.maxnum about sNaN (PR #112852)
Joshua Cranmer via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 2 14:07:31 PST 2024
================
@@ -16464,21 +16464,29 @@ type.
Semantics:
""""""""""
+Follows the IEEE-754 semantics for minNum, except that -0.0 < +0.0 for the purposes
+of this intrinsic. As for signaling NaNs, per the IEEE-754 semantics, 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 either operand is sNaN.
-Follows the IEEE-754 semantics for minNum, except for handling of
-signaling NaNs. This match's the behavior of libm's fmin.
+This behavior is more strict than the definition in C and IEEE 754, 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 on the intrinsic call.
-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.
+Some architectures, such as ARMv8, LoongArch, MIPSr6, PowerPC/VSX, have instructions that match
+these semantics exactly; thus it is quite simple for these architectures.
-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``).
+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. Such as in glibc 2.24, the Arm64 asm implemention
+has different behaviour with the generic C implemention.
+
+Note that that arithmetic on an sNaN doesn't consistently produce a qNaN,
+so arithmetic feeding into a minnum can produce inconsistent results.
+Such as `fmin(sNaN+0.0, 1.0)` can produce qNaN or 1.0 depending on whether `+0.0`
+is optimized out.
----------------
jcranmer-intel wrote:
If you're introducing an example in a separate sentence, the proper English introductory phrase is not "Such as" but rather something like "For example,"
I think this example works better if you address it explicitly as two instructions, an fadd and the minnum call, and point out the difference if the fadd call is folded.
https://github.com/llvm/llvm-project/pull/112852
More information about the llvm-commits
mailing list