Skip to content

Commit 9211a4b

Browse files
committed
Revert "LangRef: Clarify llvm.minnum and llvm.maxnum about sNaN and signed zero (llvm#112852)"
This reverts commit 363b059. I don't agree with the change itself, but even if we want to do it, it needs to be phased in a lot more carefully than it was. You can't just change the semantics in LangRef without actually dealing with the consequences of the change. Revert to the status quo for now. Fixes llvm#138303.
1 parent b2e2ae8 commit 9211a4b

File tree

2 files changed

+54
-69
lines changed

2 files changed

+54
-69
lines changed

llvm/docs/LangRef.rst

Lines changed: 49 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16936,7 +16936,7 @@ versions of the intrinsics respect the exception behavior.
1693616936
- qNaN, invalid exception
1693716937

1693816938
* - ``+0.0 vs -0.0``
16939-
- +0.0(max)/-0.0(min)
16939+
- either one
1694016940
- +0.0(max)/-0.0(min)
1694116941
- +0.0(max)/-0.0(min)
1694216942

@@ -16980,30 +16980,21 @@ type.
1698016980

1698116981
Semantics:
1698216982
""""""""""
16983-
Follows the semantics of minNum in IEEE-754-2008, except that -0.0 < +0.0 for the purposes
16984-
of this intrinsic. As for signaling NaNs, per the minNum semantics, if either operand is sNaN,
16985-
the result is qNaN. This matches the recommended behavior for the libm
16986-
function ``fmin``, although not all implementations have implemented these recommended behaviors.
16987-
16988-
If either operand is a qNaN, returns the other non-NaN operand. Returns NaN only if both operands are
16989-
NaN or if either operand is sNaN. Note that arithmetic on an sNaN doesn't consistently produce a qNaN,
16990-
so arithmetic feeding into a minnum can produce inconsistent results. For example,
16991-
``minnum(fadd(sNaN, -0.0), 1.0)`` can produce qNaN or 1.0 depending on whether ``fadd`` is folded.
1699216983

16993-
IEEE-754-2008 defines minNum, and it was removed in IEEE-754-2019. As the replacement, IEEE-754-2019
16994-
defines :ref:`minimumNumber <i_minimumnum>`.
16984+
Follows the IEEE-754 semantics for minNum, except for handling of
16985+
signaling NaNs. This match's the behavior of libm's fmin.
1699516986

16996-
If the intrinsic is marked with the nsz attribute, then the effect is as in the definition in C
16997-
and IEEE-754-2008: the result of ``minnum(-0.0, +0.0)`` may be either -0.0 or +0.0.
16987+
If either operand is a NaN, returns the other non-NaN operand. Returns
16988+
NaN only if both operands are NaN. If the operands compare equal,
16989+
returns either one of the operands. For example, this means that
16990+
fmin(+0.0, -0.0) returns either operand.
1699816991

16999-
Some architectures, such as ARMv8 (FMINNM), LoongArch (fmin), MIPSr6 (min.fmt), PowerPC/VSX (xsmindp),
17000-
have instructions that match these semantics exactly; thus it is quite simple for these architectures.
17001-
Some architectures have similiar ones while they are not exact equivalent. Such as x86 implements ``MINPS``,
17002-
which implements the semantics of C code ``a<b?a:b``: NUM vs qNaN always return qNaN. ``MINPS`` can be used
17003-
if ``nsz`` and ``nnan`` are given.
17004-
17005-
For existing libc implementations, the behaviors of fmin may be quite different on sNaN and signed zero behaviors,
17006-
even in the same release of a single libm implemention.
16992+
Unlike the IEEE-754 2008 behavior, this does not distinguish between
16993+
signaling and quiet NaN inputs. If a target's implementation follows
16994+
the standard and returns a quiet NaN if either input is a signaling
16995+
NaN, the intrinsic lowering is responsible for quieting the inputs to
16996+
correctly return the non-NaN input (e.g. by using the equivalent of
16997+
``llvm.canonicalize``).
1700716998

1700816999
.. _i_maxnum:
1700917000

@@ -17040,30 +17031,20 @@ type.
1704017031

1704117032
Semantics:
1704217033
""""""""""
17043-
Follows the semantics of maxNum in IEEE-754-2008, except that -0.0 < +0.0 for the purposes
17044-
of this intrinsic. As for signaling NaNs, per the maxNum semantics, if either operand is sNaN,
17045-
the result is qNaN. This matches the recommended behavior for the libm
17046-
function ``fmax``, although not all implementations have implemented these recommended behaviors.
17047-
17048-
If either operand is a qNaN, returns the other non-NaN operand. Returns NaN only if both operands are
17049-
NaN or if either operand is sNaN. Note that arithmetic on an sNaN doesn't consistently produce a qNaN,
17050-
so arithmetic feeding into a maxnum can produce inconsistent results. For example,
17051-
``maxnum(fadd(sNaN, -0.0), 1.0)`` can produce qNaN or 1.0 depending on whether ``fadd`` is folded.
17034+
Follows the IEEE-754 semantics for maxNum except for the handling of
17035+
signaling NaNs. This matches the behavior of libm's fmax.
1705217036

17053-
IEEE-754-2008 defines maxNum, and it was removed in IEEE-754-2019. As the replacement, IEEE-754-2019
17054-
defines :ref:`maximumNumber <i_maximumnum>`.
17037+
If either operand is a NaN, returns the other non-NaN operand. Returns
17038+
NaN only if both operands are NaN. If the operands compare equal,
17039+
returns either one of the operands. For example, this means that
17040+
fmax(+0.0, -0.0) returns either -0.0 or 0.0.
1705517041

17056-
If the intrinsic is marked with the nsz attribute, then the effect is as in the definition in C
17057-
and IEEE-754-2008: the result of maxnum(-0.0, +0.0) may be either -0.0 or +0.0.
17058-
17059-
Some architectures, such as ARMv8 (FMAXNM), LoongArch (fmax), MIPSr6 (max.fmt), PowerPC/VSX (xsmaxdp),
17060-
have instructions that match these semantics exactly; thus it is quite simple for these architectures.
17061-
Some architectures have similiar ones while they are not exact equivalent. Such as x86 implements ``MAXPS``,
17062-
which implements the semantics of C code ``a>b?a:b``: NUM vs qNaN always return qNaN. ``MAXPS`` can be used
17063-
if ``nsz`` and ``nnan`` are given.
17064-
17065-
For existing libc implementations, the behaviors of fmin may be quite different on sNaN and signed zero behaviors,
17066-
even in the same release of a single libm implemention.
17042+
Unlike the IEEE-754 2008 behavior, this does not distinguish between
17043+
signaling and quiet NaN inputs. If a target's implementation follows
17044+
the standard and returns a quiet NaN if either input is a signaling
17045+
NaN, the intrinsic lowering is responsible for quieting the inputs to
17046+
correctly return the non-NaN input (e.g. by using the equivalent of
17047+
``llvm.canonicalize``).
1706717048

1706817049
.. _i_minimum:
1706917050

@@ -19942,8 +19923,12 @@ The '``llvm.vector.reduce.fmax.*``' intrinsics do a floating-point
1994219923
matches the element-type of the vector input.
1994319924

1994419925
This instruction has the same comparison semantics as the '``llvm.maxnum.*``'
19945-
intrinsic. If the intrinsic call has the ``nnan`` fast-math flag, then the
19946-
operation can assume that NaNs are not present in the input vector.
19926+
intrinsic. That is, the result will always be a number unless all elements of
19927+
the vector are NaN. For a vector with maximum element magnitude 0.0 and
19928+
containing both +0.0 and -0.0 elements, the sign of the result is unspecified.
19929+
19930+
If the intrinsic call has the ``nnan`` fast-math flag, then the operation can
19931+
assume that NaNs are not present in the input vector.
1994719932

1994819933
Arguments:
1994919934
""""""""""
@@ -19971,8 +19956,12 @@ The '``llvm.vector.reduce.fmin.*``' intrinsics do a floating-point
1997119956
matches the element-type of the vector input.
1997219957

1997319958
This instruction has the same comparison semantics as the '``llvm.minnum.*``'
19974-
intrinsic. If the intrinsic call has the ``nnan`` fast-math flag, then the
19975-
operation can assume that NaNs are not present in the input vector.
19959+
intrinsic. That is, the result will always be a number unless all elements of
19960+
the vector are NaN. For a vector with minimum element magnitude 0.0 and
19961+
containing both +0.0 and -0.0 elements, the sign of the result is unspecified.
19962+
19963+
If the intrinsic call has the ``nnan`` fast-math flag, then the operation can
19964+
assume that NaNs are not present in the input vector.
1997619965

1997719966
Arguments:
1997819967
""""""""""
@@ -22262,7 +22251,7 @@ This is an overloaded intrinsic.
2226222251
Overview:
2226322252
"""""""""
2226422253

22265-
Predicated floating-point IEEE-754-2008 minNum of two vectors of floating-point values.
22254+
Predicated floating-point IEEE-754 minNum of two vectors of floating-point values.
2226622255

2226722256

2226822257
Arguments:
@@ -22311,7 +22300,7 @@ This is an overloaded intrinsic.
2231122300
Overview:
2231222301
"""""""""
2231322302

22314-
Predicated floating-point IEEE-754-2008 maxNum of two vectors of floating-point values.
22303+
Predicated floating-point IEEE-754 maxNum of two vectors of floating-point values.
2231522304

2231622305

2231722306
Arguments:
@@ -23610,7 +23599,10 @@ result type. If only ``nnan`` is set then the neutral value is ``-Infinity``.
2361023599

2361123600
This instruction has the same comparison semantics as the
2361223601
:ref:`llvm.vector.reduce.fmax <int_vector_reduce_fmax>` intrinsic (and thus the
23613-
'``llvm.maxnum.*``' intrinsic).
23602+
'``llvm.maxnum.*``' intrinsic). That is, the result will always be a number
23603+
unless all elements of the vector and the starting value are ``NaN``. For a
23604+
vector with maximum element magnitude ``0.0`` and containing both ``+0.0`` and
23605+
``-0.0`` elements, the sign of the result is unspecified.
2361423606

2361523607
To ignore the start value, the neutral value can be used.
2361623608

@@ -23677,7 +23669,10 @@ result type. If only ``nnan`` is set then the neutral value is ``+Infinity``.
2367723669

2367823670
This instruction has the same comparison semantics as the
2367923671
:ref:`llvm.vector.reduce.fmin <int_vector_reduce_fmin>` intrinsic (and thus the
23680-
'``llvm.minnum.*``' intrinsic).
23672+
'``llvm.minnum.*``' intrinsic). That is, the result will always be a number
23673+
unless all elements of the vector and the starting value are ``NaN``. For a
23674+
vector with maximum element magnitude ``0.0`` and containing both ``+0.0`` and
23675+
``-0.0`` elements, the sign of the result is unspecified.
2368123676

2368223677
To ignore the start value, the neutral value can be used.
2368323678

@@ -28349,7 +28344,7 @@ The third argument specifies the exception behavior as described above.
2834928344
Semantics:
2835028345
""""""""""
2835128346

28352-
This function follows the IEEE-754-2008 semantics for maxNum.
28347+
This function follows the IEEE-754 semantics for maxNum.
2835328348

2835428349

2835528350
'``llvm.experimental.constrained.minnum``' Intrinsic
@@ -28381,7 +28376,7 @@ The third argument specifies the exception behavior as described above.
2838128376
Semantics:
2838228377
""""""""""
2838328378

28384-
This function follows the IEEE-754-2008 semantics for minNum.
28379+
This function follows the IEEE-754 semantics for minNum.
2838528380

2838628381

2838728382
'``llvm.experimental.constrained.maximum``' Intrinsic

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,20 +1024,13 @@ enum NodeType {
10241024
LRINT,
10251025
LLRINT,
10261026

1027-
/// FMINNUM/FMAXNUM - Perform floating-point minimum maximum on two values,
1028-
/// following IEEE-754 definitions except for signed zero behavior.
1027+
/// FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
1028+
/// values.
10291029
///
1030-
/// If one input is a signaling NaN, returns a quiet NaN. This matches
1031-
/// IEEE-754 2008's minNum/maxNum behavior for signaling NaNs (which differs
1032-
/// from 2019).
1030+
/// In the case where a single input is a NaN (either signaling or quiet),
1031+
/// the non-NaN input is returned.
10331032
///
1034-
/// These treat -0 as ordered less than +0, matching the behavior of IEEE-754
1035-
/// 2019's minimumNumber/maximumNumber.
1036-
///
1037-
/// Note that that arithmetic on an sNaN doesn't consistently produce a qNaN,
1038-
/// so arithmetic feeding into a minnum/maxnum can produce inconsistent
1039-
/// results. FMAXIMUN/FMINIMUM or FMAXIMUMNUM/FMINIMUMNUM may be better choice
1040-
/// for non-distinction of sNaN/qNaN handling.
1033+
/// The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
10411034
FMINNUM,
10421035
FMAXNUM,
10431036

@@ -1051,9 +1044,6 @@ enum NodeType {
10511044
///
10521045
/// These treat -0 as ordered less than +0, matching the behavior of IEEE-754
10531046
/// 2019's minimumNumber/maximumNumber.
1054-
///
1055-
/// Deprecated, and will be removed soon, as FMINNUM/FMAXNUM have the same
1056-
/// semantics now.
10571047
FMINNUM_IEEE,
10581048
FMAXNUM_IEEE,
10591049

0 commit comments

Comments
 (0)