mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
soft-fp: Refine FP_EX_DENORM handling for comparisons.
In <https://sourceware.org/ml/libc-alpha/2014-09/msg00488.html>, I noted that comparisons in soft-fp did not set FP_EX_DENORM unless denormal operands were flushed to zero. This patch fixes soft-fp to check for denormal operands for comparisons and set that exception whenever FP_EX_DENORM is not zero. In particular, for the one architecture for which the Linux kernel defines FP_EX_DENORM (alpha), this corresponds to the existing logic for comparisons and so allows that logic to be replaced by a simple call to FP_CMP_D when soft-fp is updated in the kernel. Tested for powerpc (e500) that installed stripped shared libraries are unchanged by this patch. * soft-fp/op-common.h (_FP_CMP_CHECK_DENORM): New macro. (_FP_CMP_CHECK_FLUSH_ZERO): Likewise. (_FP_CMP): Use_FP_CMP_CHECK_DENORM and _FP_CMP_CHECK_FLUSH_ZERO. (_FP_CMP_EQ): Likewise. (_FP_CMP_UNORD): Use _FP_CMP_CHECK_DENORM.
This commit is contained in:
parent
639e42eb90
commit
61f006c12d
@ -1,5 +1,11 @@
|
|||||||
2015-02-06 Joseph Myers <joseph@codesourcery.com>
|
2015-02-06 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
|
* soft-fp/op-common.h (_FP_CMP_CHECK_DENORM): New macro.
|
||||||
|
(_FP_CMP_CHECK_FLUSH_ZERO): Likewise.
|
||||||
|
(_FP_CMP): Use_FP_CMP_CHECK_DENORM and _FP_CMP_CHECK_FLUSH_ZERO.
|
||||||
|
(_FP_CMP_EQ): Likewise.
|
||||||
|
(_FP_CMP_UNORD): Use _FP_CMP_CHECK_DENORM.
|
||||||
|
|
||||||
* soft-fp/op-common.h (FP_EXTEND): Rename to _FP_EXTEND_CNAN with
|
* soft-fp/op-common.h (FP_EXTEND): Rename to _FP_EXTEND_CNAN with
|
||||||
extra argument CHECK_NAN. Redefine as wrapper around
|
extra argument CHECK_NAN. Redefine as wrapper around
|
||||||
_FP_EXTEND_CNAN.
|
_FP_EXTEND_CNAN.
|
||||||
|
@ -1251,6 +1251,46 @@
|
|||||||
} \
|
} \
|
||||||
while (0)
|
while (0)
|
||||||
|
|
||||||
|
/* Helper for comparisons. If denormal operands would raise an
|
||||||
|
exception, check for them, and flush to zero as appropriate
|
||||||
|
(otherwise, we need only check and flush to zero if it might affect
|
||||||
|
the result, which is done later with _FP_CMP_CHECK_FLUSH_ZERO). */
|
||||||
|
#define _FP_CMP_CHECK_DENORM(fs, wc, X, Y) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (FP_EX_DENORM != 0) \
|
||||||
|
{ \
|
||||||
|
/* We must ensure the correct exceptions are raised for \
|
||||||
|
denormal operands, even though this may not affect the \
|
||||||
|
result of the comparison. */ \
|
||||||
|
if (FP_DENORM_ZERO) \
|
||||||
|
{ \
|
||||||
|
_FP_CHECK_FLUSH_ZERO (fs, wc, X); \
|
||||||
|
_FP_CHECK_FLUSH_ZERO (fs, wc, Y); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
if ((X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X)) \
|
||||||
|
|| (Y##_e == 0 && !_FP_FRAC_ZEROP_##wc (Y))) \
|
||||||
|
FP_SET_EXCEPTION (FP_EX_DENORM); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
|
/* Helper for comparisons. Check for flushing denormals for zero if
|
||||||
|
we didn't need to check earlier for any denormal operands. */
|
||||||
|
#define _FP_CMP_CHECK_FLUSH_ZERO(fs, wc, X, Y) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (FP_EX_DENORM == 0) \
|
||||||
|
{ \
|
||||||
|
_FP_CHECK_FLUSH_ZERO (fs, wc, X); \
|
||||||
|
_FP_CHECK_FLUSH_ZERO (fs, wc, Y); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
|
||||||
/* Main differential comparison routine. The inputs should be raw not
|
/* Main differential comparison routine. The inputs should be raw not
|
||||||
cooked. The return is -1, 0, 1 for normal values, UN
|
cooked. The return is -1, 0, 1 for normal values, UN
|
||||||
otherwise. */
|
otherwise. */
|
||||||
@ -1258,6 +1298,7 @@
|
|||||||
#define _FP_CMP(fs, wc, ret, X, Y, un, ex) \
|
#define _FP_CMP(fs, wc, ret, X, Y, un, ex) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
_FP_CMP_CHECK_DENORM (fs, wc, X, Y); \
|
||||||
/* NANs are unordered. */ \
|
/* NANs are unordered. */ \
|
||||||
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
|
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
|
||||||
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
|
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
|
||||||
@ -1270,8 +1311,7 @@
|
|||||||
int _FP_CMP_is_zero_x; \
|
int _FP_CMP_is_zero_x; \
|
||||||
int _FP_CMP_is_zero_y; \
|
int _FP_CMP_is_zero_y; \
|
||||||
\
|
\
|
||||||
_FP_CHECK_FLUSH_ZERO (fs, wc, X); \
|
_FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \
|
||||||
_FP_CHECK_FLUSH_ZERO (fs, wc, Y); \
|
|
||||||
\
|
\
|
||||||
_FP_CMP_is_zero_x \
|
_FP_CMP_is_zero_x \
|
||||||
= (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \
|
= (!X##_e && _FP_FRAC_ZEROP_##wc (X)) ? 1 : 0; \
|
||||||
@ -1306,6 +1346,7 @@
|
|||||||
#define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \
|
#define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
_FP_CMP_CHECK_DENORM (fs, wc, X, Y); \
|
||||||
/* NANs are unordered. */ \
|
/* NANs are unordered. */ \
|
||||||
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
|
if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
|
||||||
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
|
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \
|
||||||
@ -1315,8 +1356,7 @@
|
|||||||
} \
|
} \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
_FP_CHECK_FLUSH_ZERO (fs, wc, X); \
|
_FP_CMP_CHECK_FLUSH_ZERO (fs, wc, X, Y); \
|
||||||
_FP_CHECK_FLUSH_ZERO (fs, wc, Y); \
|
|
||||||
\
|
\
|
||||||
(ret) = !(X##_e == Y##_e \
|
(ret) = !(X##_e == Y##_e \
|
||||||
&& _FP_FRAC_EQ_##wc (X, Y) \
|
&& _FP_FRAC_EQ_##wc (X, Y) \
|
||||||
@ -1331,6 +1371,7 @@
|
|||||||
#define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \
|
#define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
|
_FP_CMP_CHECK_DENORM (fs, wc, X, Y); \
|
||||||
(ret) = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
|
(ret) = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \
|
||||||
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \
|
|| (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \
|
||||||
if (ret) \
|
if (ret) \
|
||||||
|
Loading…
Reference in New Issue
Block a user