From 73e28d9c885fdfed91e6d70c4aab7e8e801818e3 Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Thu, 9 Oct 2014 01:03:56 +0000 Subject: soft-fp: Refactor exception handling for comparisons. This patch refactors how soft-fp comparisons handle setting exceptions for NaN operands, so that exceptions are set through the FP_CMP macros rather than directly in the C files calling them. The _FP_CMP* and FP_CMP* macros gain an extra argument to specify when exceptions should be set, 0 for no exception setting (I'm not sure this is actually needed - at least it's not needed for IEEE operations in glibc / libgcc, but might be relevant in some cases for kernel use), 1 for exceptions only for signaling NaNs and 2 for exceptions for all NaNs. This argument is handled through _FP_CMP_CHECK_NAN, newly called by the _FP_CMP* macros when a NaN is encountered. Calls to these macros are updated, which eliminates all the existing checking and exception setting in soft-fp *.c files in glibc. Tested for powerpc-nofpu. (The __unord* functions have no code changes; the __eq* / __ge* / __le* functions get slightly larger, but I don't think that's significant.) * soft-fp/op-common.h (_FP_CMP_CHECK_NAN): New macro. (_FP_CMP): Add extra argument EX. Call _FP_CMP_CHECK_NAN. (_FP_CMP_EQ): Likewise. (_FP_CMP_UNORD): Likewise. * soft-fp/double.h (FP_CMP_D): Add extra argument EX. (FP_CMP_EQ_D): Likewise. (FP_CMP_UNORD_D): Likewise. * soft-fp/extended.h (FP_CMP_E): Likewise. (FP_CMP_EQ_E): Likewise. (FP_CMP_UNORD_E): Likewise. * soft-fp/quad.h (FP_CMP_Q): Likewise. (FP_CMP_EQ_Q): Likewise. (FP_CMP_UNORD_Q): Likewise. * soft-fp/single.h (FP_CMP_S): Likewise. (FP_CMP_EQ_S): Likewise. (FP_CMP_UNORD_S): Likewise. * soft-fp/eqdf2.c (__eqdf2): Update call to FP_CMP_EQ_D. * soft-fp/eqsf2.c (__eqsf2): Update call to FP_CMP_EQ_S. * soft-fp/eqtf2.c (__eqtf2): Update call to FP_CMP_EQ_Q. * soft-fp/gedf2.c (__gedf2): Update call to FP_CMP_D. * soft-fp/gesf2.c (__gesf2): Update call to FP_CMP_S. * soft-fp/getf2.c (__getf2): Update call to FP_CMP_Q. * soft-fp/ledf2.c (__ledf2): Update call to FP_CMP_D. * soft-fp/lesf2.c (__lesf2): Update call to FP_CMP_S. * soft-fp/letf2.c (__letf2): Update call to FP_CMP_Q. * soft-fp/unorddf2.c (__unorddf2): Update call to FP_CMP_UNORD_D. * soft-fp/unordsf2.c (__unordsf2): Update call to FP_CMP_UNORD_S. * soft-fp/unordtf2.c (__unordtf2): Update call to FP_CMP_UNORD_Q. * sysdeps/alpha/soft-fp/ots_cmpe.c (internal_compare): Update call to FP_CMP_Q. * sysdeps/sparc/sparc32/soft-fp/q_cmp.c (_Q_cmp): Update call to FP_CMP_Q. * sysdeps/sparc/sparc32/soft-fp/q_cmpe.c (_Q_cmpe): Likewise. * sysdeps/sparc/sparc32/soft-fp/q_feq.c (_Q_feq): Update call to FP_CMP_EQ_Q. * sysdeps/sparc/sparc32/soft-fp/q_fge.c (_Q_fge): Update call to FP_CMP_Q. * sysdeps/sparc/sparc32/soft-fp/q_fgt.c (_Q_fgt): Likewise. * sysdeps/sparc/sparc32/soft-fp/q_fle.c (_Q_fle): Likewise. * sysdeps/sparc/sparc32/soft-fp/q_flt.c (_Q_flt): Likewise. * sysdeps/sparc/sparc32/soft-fp/q_fne.c (_Q_fne): Update call to FP_CMP_EQ_Q. * sysdeps/sparc/sparc64/soft-fp/qp_cmp.c (_Qp_cmp): Update call to FP_CMP_Q. * sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c (_Qp_cmpe): Likewise. * sysdeps/sparc/sparc64/soft-fp/qp_feq.c (_Qp_feq): Update call to FP_CMP_EQ_Q. * sysdeps/sparc/sparc64/soft-fp/qp_fge.c (_Qp_fge): Update call to FP_CMP_Q. * sysdeps/sparc/sparc64/soft-fp/qp_fgt.c (_Qp_fgt): Likewise. * sysdeps/sparc/sparc64/soft-fp/qp_fle.c (_Qp_fle): Likewise. * sysdeps/sparc/sparc64/soft-fp/qp_flt.c (_Qp_flt): Likewise. * sysdeps/sparc/sparc64/soft-fp/qp_fne.c (_Qp_fne): Update call to FP_CMP_EQ_Q. --- soft-fp/op-common.h | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'soft-fp/op-common.h') diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h index e3212ecfd5..e62558e4b4 100644 --- a/soft-fp/op-common.h +++ b/soft-fp/op-common.h @@ -1186,10 +1186,28 @@ while (0) +/* Helper for comparisons. EX is 0 not to raise exceptions, 1 to + raise exceptions for signaling NaN operands, 2 to raise exceptions + for all NaN operands. */ + +#define _FP_CMP_CHECK_NAN(fs, wc, X, Y, ex) \ + do \ + { \ + if (ex) \ + { \ + if ((ex) == 2 \ + || _FP_ISSIGNAN (fs, wc, X) \ + || _FP_ISSIGNAN (fs, wc, Y)) \ + FP_SET_EXCEPTION (FP_EX_INVALID); \ + } \ + } \ + while (0) + /* Main differential comparison routine. The inputs should be raw not - cooked. The return is -1,0,1 for normal values, 2 otherwise. */ + cooked. The return is -1, 0, 1 for normal values, UN + otherwise. */ -#define _FP_CMP(fs, wc, ret, X, Y, un) \ +#define _FP_CMP(fs, wc, ret, X, Y, un, ex) \ do \ { \ /* NANs are unordered. */ \ @@ -1197,6 +1215,7 @@ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ { \ ret = un; \ + _FP_CMP_CHECK_NAN (fs, wc, X, Y, ex); \ } \ else \ { \ @@ -1233,7 +1252,7 @@ /* Simplification for strict equality. */ -#define _FP_CMP_EQ(fs, wc, ret, X, Y) \ +#define _FP_CMP_EQ(fs, wc, ret, X, Y, ex) \ do \ { \ /* NANs are unordered. */ \ @@ -1241,6 +1260,7 @@ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))) \ { \ ret = 1; \ + _FP_CMP_CHECK_NAN (fs, wc, X, Y, ex); \ } \ else \ { \ @@ -1253,11 +1273,13 @@ /* Version to test unordered. */ -#define _FP_CMP_UNORD(fs, wc, ret, X, Y) \ +#define _FP_CMP_UNORD(fs, wc, ret, X, Y, ex) \ do \ { \ ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (X)) \ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc (Y))); \ + if (ret) \ + _FP_CMP_CHECK_NAN (fs, wc, X, Y, ex); \ } \ while (0) -- cgit 1.4.1