soft-fp: Refactor exception handling for comparisons
diff mbox

Message ID Pine.LNX.4.64.1409182321370.20342@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Sept. 18, 2014, 11:24 p.m. UTC
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.)

2014-09-18  Joseph Myers  <joseph@codesourcery.com>

	* 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.

Comments

Joseph Myers Sept. 24, 2014, 8:56 a.m. UTC | #1
Ping.  This patch 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00461.html> is pending 
review.
Joseph Myers Sept. 30, 2014, 2:41 p.m. UTC | #2
Ping^2.  This patch 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00461.html> is still 
pending review.
Joseph Myers Oct. 6, 2014, 10:02 a.m. UTC | #3
Ping^3.  This patch 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00461.html> is still 
pending review.
Carlos O'Donell Oct. 9, 2014, 12:10 a.m. UTC | #4
On 09/18/2014 07:24 PM, Joseph S. Myers wrote:
> 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.)
> 
> 2014-09-18  Joseph Myers  <joseph@codesourcery.com>
> 
> 	* 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.

Looks good to me.

I got the same list of places in soft-fp that needed updates to use the macros.

I had only one nit, which wasn't a correctness issue, but just a code-generation
question regarding the _FP_CMP_CHECK_NAN macro.

> diff --git a/soft-fp/double.h b/soft-fp/double.h
> index 7782994..1e6283e 100644
> --- a/soft-fp/double.h
> +++ b/soft-fp/double.h
> @@ -177,9 +177,9 @@ union _FP_UNION_D
>  # define _FP_SQRT_MEAT_D(R, S, T, X, Q)	_FP_SQRT_MEAT_2 (R, S, T, X, Q)
>  # define FP_FMA_D(R, X, Y, Z)		_FP_FMA (D, 2, 4, R, X, Y, Z)
>  
> -# define FP_CMP_D(r, X, Y, un)		_FP_CMP (D, 2, r, X, Y, un)
> -# define FP_CMP_EQ_D(r, X, Y)		_FP_CMP_EQ (D, 2, r, X, Y)
> -# define FP_CMP_UNORD_D(r, X, Y)	_FP_CMP_UNORD (D, 2, r, X, Y)
> +# define FP_CMP_D(r, X, Y, un, ex)	_FP_CMP (D, 2, r, X, Y, un, ex)
> +# define FP_CMP_EQ_D(r, X, Y, ex)	_FP_CMP_EQ (D, 2, r, X, Y, ex)
> +# define FP_CMP_UNORD_D(r, X, Y, ex)	_FP_CMP_UNORD (D, 2, r, X, Y, ex)

OK.

>  
>  # define FP_TO_INT_D(r, X, rsz, rsg)	_FP_TO_INT (D, 2, r, X, rsz, rsg)
>  # define FP_FROM_INT_D(X, r, rs, rt)	_FP_FROM_INT (D, 2, X, r, rs, rt)
> @@ -299,9 +299,9 @@ union _FP_UNION_D
>  /* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
>     the target machine.  */
>  
> -# define FP_CMP_D(r, X, Y, un)		_FP_CMP (D, 1, r, X, Y, un)
> -# define FP_CMP_EQ_D(r, X, Y)		_FP_CMP_EQ (D, 1, r, X, Y)
> -# define FP_CMP_UNORD_D(r, X, Y)	_FP_CMP_UNORD (D, 1, r, X, Y)
> +# define FP_CMP_D(r, X, Y, un, ex)	_FP_CMP (D, 1, r, X, Y, un, ex)
> +# define FP_CMP_EQ_D(r, X, Y, ex)	_FP_CMP_EQ (D, 1, r, X, Y, ex)
> +# define FP_CMP_UNORD_D(r, X, Y, ex)	_FP_CMP_UNORD (D, 1, r, X, Y, ex)

OK.

>  
>  # define FP_TO_INT_D(r, X, rsz, rsg)	_FP_TO_INT (D, 1, r, X, rsz, rsg)
>  # define FP_FROM_INT_D(X, r, rs, rt)	_FP_FROM_INT (D, 1, X, r, rs, rt)
> diff --git a/soft-fp/eqdf2.c b/soft-fp/eqdf2.c
> index 006b1ef..e8ce12d 100644
> --- a/soft-fp/eqdf2.c
> +++ b/soft-fp/eqdf2.c
> @@ -42,9 +42,7 @@ __eqdf2 (DFtype a, DFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_D (A, a);
>    FP_UNPACK_RAW_D (B, b);
> -  FP_CMP_EQ_D (r, A, B);
> -  if (r && (FP_ISSIGNAN_D (A) || FP_ISSIGNAN_D (B)))
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_EQ_D (r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/eqsf2.c b/soft-fp/eqsf2.c
> index 437ef99..2ee837d 100644
> --- a/soft-fp/eqsf2.c
> +++ b/soft-fp/eqsf2.c
> @@ -42,9 +42,7 @@ __eqsf2 (SFtype a, SFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_S (A, a);
>    FP_UNPACK_RAW_S (B, b);
> -  FP_CMP_EQ_S (r, A, B);
> -  if (r && (FP_ISSIGNAN_S (A) || FP_ISSIGNAN_S (B)))
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_EQ_S (r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/eqtf2.c b/soft-fp/eqtf2.c
> index ffc558c..17b9d40 100644
> --- a/soft-fp/eqtf2.c
> +++ b/soft-fp/eqtf2.c
> @@ -42,9 +42,7 @@ __eqtf2 (TFtype a, TFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_Q (A, a);
>    FP_UNPACK_RAW_Q (B, b);
> -  FP_CMP_EQ_Q (r, A, B);
> -  if (r && (FP_ISSIGNAN_Q (A) || FP_ISSIGNAN_Q (B)))
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_EQ_Q (r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/extended.h b/soft-fp/extended.h
> index 989b056..0dd6a87 100644
> --- a/soft-fp/extended.h
> +++ b/soft-fp/extended.h
> @@ -287,9 +287,9 @@ union _FP_UNION_E
>      }							\
>    while (0)
>  
> -# define FP_CMP_E(r, X, Y, un)		_FP_CMP (E, 4, r, X, Y, un)
> -# define FP_CMP_EQ_E(r, X, Y)		_FP_CMP_EQ (E, 4, r, X, Y)
> -# define FP_CMP_UNORD_E(r, X, Y)	_FP_CMP_UNORD (E, 4, r, X, Y)
> +# define FP_CMP_E(r, X, Y, un, ex)	_FP_CMP (E, 4, r, X, Y, un, ex)
> +# define FP_CMP_EQ_E(r, X, Y, ex)	_FP_CMP_EQ (E, 4, r, X, Y, ex)
> +# define FP_CMP_UNORD_E(r, X, Y, ex)	_FP_CMP_UNORD (E, 4, r, X, Y, ex)

OK.

>  
>  # define FP_TO_INT_E(r, X, rsz, rsg)	_FP_TO_INT (E, 4, r, X, rsz, rsg)
>  # define FP_FROM_INT_E(X, r, rs, rt)	_FP_FROM_INT (E, 4, X, r, rs, rt)
> @@ -489,9 +489,9 @@ union _FP_UNION_E
>      }							\
>    while (0)
>  
> -# define FP_CMP_E(r, X, Y, un)		_FP_CMP (E, 2, r, X, Y, un)
> -# define FP_CMP_EQ_E(r, X, Y)		_FP_CMP_EQ (E, 2, r, X, Y)
> -# define FP_CMP_UNORD_E(r, X, Y)	_FP_CMP_UNORD (E, 2, r, X, Y)
> +# define FP_CMP_E(r, X, Y, un, ex)	_FP_CMP (E, 2, r, X, Y, un, ex)
> +# define FP_CMP_EQ_E(r, X, Y, ex)	_FP_CMP_EQ (E, 2, r, X, Y, ex)
> +# define FP_CMP_UNORD_E(r, X, Y, ex)	_FP_CMP_UNORD (E, 2, r, X, Y, ex)

OK.

>  
>  # define FP_TO_INT_E(r, X, rsz, rsg)	_FP_TO_INT (E, 2, r, X, rsz, rsg)
>  # define FP_FROM_INT_E(X, r, rs, rt)	_FP_FROM_INT (E, 2, X, r, rs, rt)
> diff --git a/soft-fp/gedf2.c b/soft-fp/gedf2.c
> index 4ff9756..a8cc949 100644
> --- a/soft-fp/gedf2.c
> +++ b/soft-fp/gedf2.c
> @@ -42,9 +42,7 @@ __gedf2 (DFtype a, DFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_D (A, a);
>    FP_UNPACK_RAW_D (B, b);
> -  FP_CMP_D (r, A, B, -2);
> -  if (r == -2)
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_D (r, A, B, -2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/gesf2.c b/soft-fp/gesf2.c
> index f3c5d2d..aa84b26 100644
> --- a/soft-fp/gesf2.c
> +++ b/soft-fp/gesf2.c
> @@ -42,9 +42,7 @@ __gesf2 (SFtype a, SFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_S (A, a);
>    FP_UNPACK_RAW_S (B, b);
> -  FP_CMP_S (r, A, B, -2);
> -  if (r == -2)
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_S (r, A, B, -2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/getf2.c b/soft-fp/getf2.c
> index fb82b79..c852228 100644
> --- a/soft-fp/getf2.c
> +++ b/soft-fp/getf2.c
> @@ -42,9 +42,7 @@ __getf2 (TFtype a, TFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_Q (A, a);
>    FP_UNPACK_RAW_Q (B, b);
> -  FP_CMP_Q (r, A, B, -2);
> -  if (r == -2)
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_Q (r, A, B, -2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/ledf2.c b/soft-fp/ledf2.c
> index 8b15d32..fb5bbb2 100644
> --- a/soft-fp/ledf2.c
> +++ b/soft-fp/ledf2.c
> @@ -42,9 +42,7 @@ __ledf2 (DFtype a, DFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_D (A, a);
>    FP_UNPACK_RAW_D (B, b);
> -  FP_CMP_D (r, A, B, 2);
> -  if (r == 2)
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_D (r, A, B, 2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/lesf2.c b/soft-fp/lesf2.c
> index e86ac3f..1b67204 100644
> --- a/soft-fp/lesf2.c
> +++ b/soft-fp/lesf2.c
> @@ -42,9 +42,7 @@ __lesf2 (SFtype a, SFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_S (A, a);
>    FP_UNPACK_RAW_S (B, b);
> -  FP_CMP_S (r, A, B, 2);
> -  if (r == 2)
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_S (r, A, B, 2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/letf2.c b/soft-fp/letf2.c
> index 94b7d78..1293519 100644
> --- a/soft-fp/letf2.c
> +++ b/soft-fp/letf2.c
> @@ -42,9 +42,7 @@ __letf2 (TFtype a, TFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_Q (A, a);
>    FP_UNPACK_RAW_Q (B, b);
> -  FP_CMP_Q (r, A, B, 2);
> -  if (r == 2)
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_Q (r, A, B, 2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
> index ec0bc42..af859e2 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)						\

Does the soft-fp code care about implicit boolean coersion?

If I had to write this it would have written:

if ((ex) == 1 
    && (_FP_ISSIGNAN (fs, wc, X) 
        || _FP_ISSIGNAN (fs, wc, Y))
  FP_SET_EXCEPTION (FP_EX_INVALID);

if ((ex) == 2)
  FP_SET_EXCEPTION (FP_EX_INVALID);

Since this is *very* easy to read and understand given the description,
but I don't know if the compiler generates better or worse code given
the above.

> +	{						\
> +	  if ((ex) == 2					\
> +	      || _FP_ISSIGNAN (fs, wc, X)		\
> +	      || _FP_ISSIGNAN (fs, wc, Y))		\
> +	    FP_SET_EXCEPTION (FP_EX_INVALID);		\

OK.

> +	}						\
> +    }							\
> +  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);				\

OK.

>  	}								\
>        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);				\

OK.

>  	}								\
>        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);				\

OK.

>      }									\
>    while (0)
>  
> diff --git a/soft-fp/quad.h b/soft-fp/quad.h
> index 16e362f..c2e4133 100644
> --- a/soft-fp/quad.h
> +++ b/soft-fp/quad.h
> @@ -182,9 +182,9 @@ union _FP_UNION_Q
>  # define _FP_SQRT_MEAT_Q(R, S, T, X, Q)	_FP_SQRT_MEAT_4 (R, S, T, X, Q)
>  # define FP_FMA_Q(R, X, Y, Z)		_FP_FMA (Q, 4, 8, R, X, Y, Z)
>  
> -# define FP_CMP_Q(r, X, Y, un)		_FP_CMP (Q, 4, r, X, Y, un)
> -# define FP_CMP_EQ_Q(r, X, Y)		_FP_CMP_EQ (Q, 4, r, X, Y)
> -# define FP_CMP_UNORD_Q(r, X, Y)	_FP_CMP_UNORD (Q, 4, r, X, Y)
> +# define FP_CMP_Q(r, X, Y, un, ex)	_FP_CMP (Q, 4, r, X, Y, un, ex)
> +# define FP_CMP_EQ_Q(r, X, Y, ex)	_FP_CMP_EQ (Q, 4, r, X, Y, ex)
> +# define FP_CMP_UNORD_Q(r, X, Y, ex)	_FP_CMP_UNORD (Q, 4, r, X, Y, ex)

OK.

>  
>  # define FP_TO_INT_Q(r, X, rsz, rsg)	_FP_TO_INT (Q, 4, r, X, rsz, rsg)
>  # define FP_FROM_INT_Q(X, r, rs, rt)	_FP_FROM_INT (Q, 4, X, r, rs, rt)
> @@ -306,9 +306,9 @@ union _FP_UNION_Q
>  # define _FP_SQRT_MEAT_Q(R, S, T, X, Q)	_FP_SQRT_MEAT_2 (R, S, T, X, Q)
>  # define FP_FMA_Q(R, X, Y, Z)		_FP_FMA (Q, 2, 4, R, X, Y, Z)
>  
> -# define FP_CMP_Q(r, X, Y, un)		_FP_CMP (Q, 2, r, X, Y, un)
> -# define FP_CMP_EQ_Q(r, X, Y)		_FP_CMP_EQ (Q, 2, r, X, Y)
> -# define FP_CMP_UNORD_Q(r, X, Y)	_FP_CMP_UNORD (Q, 2, r, X, Y)
> +# define FP_CMP_Q(r, X, Y, un, ex)	_FP_CMP (Q, 2, r, X, Y, un, ex)
> +# define FP_CMP_EQ_Q(r, X, Y, ex)	_FP_CMP_EQ (Q, 2, r, X, Y, ex)
> +# define FP_CMP_UNORD_Q(r, X, Y, ex)	_FP_CMP_UNORD (Q, 2, r, X, Y, ex)

OK.

>  
>  # define FP_TO_INT_Q(r, X, rsz, rsg)	_FP_TO_INT (Q, 2, r, X, rsz, rsg)
>  # define FP_FROM_INT_Q(X, r, rs, rt)	_FP_FROM_INT (Q, 2, X, r, rs, rt)
> diff --git a/soft-fp/single.h b/soft-fp/single.h
> index 19fd647..efa8294 100644
> --- a/soft-fp/single.h
> +++ b/soft-fp/single.h
> @@ -175,9 +175,9 @@ union _FP_UNION_S
>  # define FP_FMA_S(R, X, Y, Z)	_FP_FMA (S, 1, 1, R, X, Y, Z)
>  #endif
>  
> -#define FP_CMP_S(r, X, Y, un)	_FP_CMP (S, 1, r, X, Y, un)
> -#define FP_CMP_EQ_S(r, X, Y)	_FP_CMP_EQ (S, 1, r, X, Y)
> -#define FP_CMP_UNORD_S(r, X, Y)	_FP_CMP_UNORD (S, 1, r, X, Y)
> +#define FP_CMP_S(r, X, Y, un, ex)	_FP_CMP (S, 1, r, X, Y, un, ex)
> +#define FP_CMP_EQ_S(r, X, Y, ex)	_FP_CMP_EQ (S, 1, r, X, Y, ex)
> +#define FP_CMP_UNORD_S(r, X, Y, ex)	_FP_CMP_UNORD (S, 1, r, X, Y, ex)

OK.

>  
>  #define FP_TO_INT_S(r, X, rsz, rsg)	_FP_TO_INT (S, 1, r, X, rsz, rsg)
>  #define FP_FROM_INT_S(X, r, rs, rt)	_FP_FROM_INT (S, 1, X, r, rs, rt)
> diff --git a/soft-fp/unorddf2.c b/soft-fp/unorddf2.c
> index ceacb9e..e09a1ec 100644
> --- a/soft-fp/unorddf2.c
> +++ b/soft-fp/unorddf2.c
> @@ -41,9 +41,7 @@ __unorddf2 (DFtype a, DFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_D (A, a);
>    FP_UNPACK_RAW_D (B, b);
> -  FP_CMP_UNORD_D (r, A, B);
> -  if (r && (FP_ISSIGNAN_D (A) || FP_ISSIGNAN_D (B)))
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_UNORD_D (r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/unordsf2.c b/soft-fp/unordsf2.c
> index 057f2c4..4d6be98 100644
> --- a/soft-fp/unordsf2.c
> +++ b/soft-fp/unordsf2.c
> @@ -41,9 +41,7 @@ __unordsf2 (SFtype a, SFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_S (A, a);
>    FP_UNPACK_RAW_S (B, b);
> -  FP_CMP_UNORD_S (r, A, B);
> -  if (r && (FP_ISSIGNAN_S (A) || FP_ISSIGNAN_S (B)))
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_UNORD_S (r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/soft-fp/unordtf2.c b/soft-fp/unordtf2.c
> index 433a84f..79d3421 100644
> --- a/soft-fp/unordtf2.c
> +++ b/soft-fp/unordtf2.c
> @@ -41,9 +41,7 @@ __unordtf2 (TFtype a, TFtype b)
>    FP_INIT_EXCEPTIONS;
>    FP_UNPACK_RAW_Q (A, a);
>    FP_UNPACK_RAW_Q (B, b);
> -  FP_CMP_UNORD_Q (r, A, B);
> -  if (r && (FP_ISSIGNAN_Q (A) || FP_ISSIGNAN_Q (B)))
> -    FP_SET_EXCEPTION (FP_EX_INVALID);
> +  FP_CMP_UNORD_Q (r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/sysdeps/alpha/soft-fp/ots_cmpe.c b/sysdeps/alpha/soft-fp/ots_cmpe.c
> index adeda84..41586ee 100644
> --- a/sysdeps/alpha/soft-fp/ots_cmpe.c
> +++ b/sysdeps/alpha/soft-fp/ots_cmpe.c
> @@ -29,14 +29,9 @@ internal_compare (long al, long ah, long bl, long bh)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q (r, A, B, 2);
> +  FP_CMP_Q (r, A, B, 2, 2);
>  
> -  /* Relative comparisons signal invalid operation if either operand is NaN. */
> -  if (r == 2)
> -    {
> -      FP_SET_EXCEPTION(FP_EX_INVALID);
> -      FP_HANDLE_EXCEPTIONS;
> -    }
> +  FP_HANDLE_EXCEPTIONS;

OK.
>  
>    return r;
>  }
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_cmp.c b/sysdeps/sparc/sparc32/soft-fp/q_cmp.c
> index 837b3dd..acc1d1d 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_cmp.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_cmp.c
> @@ -30,10 +30,8 @@ int _Q_cmp(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> +  FP_CMP_Q(r, B, A, 3, 1);
>    if (r == -1) r = 2;
> -  if (r == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
> -    FP_SET_EXCEPTION(FP_EX_INVALID);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c b/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c
> index d4ac7bd..a5d4670 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c
> @@ -31,10 +31,8 @@ int _Q_cmpe(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> +  FP_CMP_Q(r, B, A, 3, 2);
>    if (r == -1) r = 2;
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_feq.c b/sysdeps/sparc/sparc32/soft-fp/q_feq.c
> index 61a8ff1..cb7db6d 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_feq.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_feq.c
> @@ -30,9 +30,7 @@ int _Q_feq(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_EQ_Q(r, A, B);
> -  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_EQ_Q(r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return !r;
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fge.c b/sysdeps/sparc/sparc32/soft-fp/q_fge.c
> index 7fca349..cca1003 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_fge.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_fge.c
> @@ -30,9 +30,7 @@ int _Q_fge(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, 3, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return (r <= 0);
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fgt.c b/sysdeps/sparc/sparc32/soft-fp/q_fgt.c
> index f5b2acf..00f837d 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_fgt.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_fgt.c
> @@ -30,9 +30,7 @@ int _Q_fgt(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, 3, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return (r == -1);
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fle.c b/sysdeps/sparc/sparc32/soft-fp/q_fle.c
> index c108fb9..b44f448 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_fle.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_fle.c
> @@ -30,9 +30,7 @@ int _Q_fle(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q(r, B, A, -2);
> -  if (r == -2)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, -2, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return (r >= 0);
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_flt.c b/sysdeps/sparc/sparc32/soft-fp/q_flt.c
> index 56d140e..caa188d 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_flt.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_flt.c
> @@ -30,9 +30,7 @@ int _Q_flt(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, 3, 2);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return (r == 1);
> diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fne.c b/sysdeps/sparc/sparc32/soft-fp/q_fne.c
> index 78c2d6f..e22f6c9 100644
> --- a/sysdeps/sparc/sparc32/soft-fp/q_fne.c
> +++ b/sysdeps/sparc/sparc32/soft-fp/q_fne.c
> @@ -30,9 +30,7 @@ int _Q_fne(const long double a, const long double b)
>  
>    FP_UNPACK_RAW_Q(A, a);
>    FP_UNPACK_RAW_Q(B, b);
> -  FP_CMP_EQ_Q(r, A, B);
> -  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_EQ_Q(r, A, B, 1);

OK.

>    FP_HANDLE_EXCEPTIONS;
>  
>    return r;
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c b/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c
> index 1929a08..dadb369 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c
> @@ -31,10 +31,8 @@ int _Qp_cmp(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> +  FP_CMP_Q(r, B, A, 3, 1);
>    if (r == -1) r = 2;
> -  if (r == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
> -    FP_SET_EXCEPTION(FP_EX_INVALID);

OK.

>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
>  "	ldd [%0], %%f52\n"
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c b/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c
> index ee25b5e..c56d623 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c
> @@ -32,10 +32,8 @@ int _Qp_cmpe(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> +  FP_CMP_Q(r, B, A, 3, 2);
>    if (r == -1) r = 2;
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);

OK.

>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
>  "	ldd [%0], %%f52\n"
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_feq.c b/sysdeps/sparc/sparc64/soft-fp/qp_feq.c
> index 36eef5a..67b6b87 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_feq.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_feq.c
> @@ -31,9 +31,7 @@ int _Qp_feq(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_EQ_Q(r, A, B);
> -  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_EQ_Q(r, A, B, 1);

OK.

>  
>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fge.c b/sysdeps/sparc/sparc64/soft-fp/qp_fge.c
> index 3f0c16b..690a741 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_fge.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_fge.c
> @@ -31,9 +31,7 @@ int _Qp_fge(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, 3, 2);

OK.

>  
>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c b/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c
> index 2b915be..423bd5a 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c
> @@ -31,9 +31,7 @@ int _Qp_fgt(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, 3, 2);

OK.

>  
>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fle.c b/sysdeps/sparc/sparc64/soft-fp/qp_fle.c
> index 74f80f4..f915152 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_fle.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_fle.c
> @@ -31,9 +31,7 @@ int _Qp_fle(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_Q(r, B, A, -2);
> -  if (r == -2)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, -2, 2);

OK.

>  
>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_flt.c b/sysdeps/sparc/sparc64/soft-fp/qp_flt.c
> index a4c8e05..c03cd72 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_flt.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_flt.c
> @@ -31,9 +31,7 @@ int _Qp_flt(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_Q(r, B, A, 3);
> -  if (r == 3)
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_Q(r, B, A, 3, 2);

OK.

>  
>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
> diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fne.c b/sysdeps/sparc/sparc64/soft-fp/qp_fne.c
> index 828c394..948077c 100644
> --- a/sysdeps/sparc/sparc64/soft-fp/qp_fne.c
> +++ b/sysdeps/sparc/sparc64/soft-fp/qp_fne.c
> @@ -31,9 +31,7 @@ int _Qp_fne(const long double *a, const long double *b)
>    FP_INIT_ROUNDMODE;
>    FP_UNPACK_RAW_QP(A, a);
>    FP_UNPACK_RAW_QP(B, b);
> -  FP_CMP_EQ_Q(r, A, B);
> -  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
> -    FP_SET_EXCEPTION(FP_EX_INVALID);
> +  FP_CMP_EQ_Q(r, A, B, 1);

OK.

>  
>    QP_HANDLE_EXCEPTIONS(
>  	__asm (
> 

Cheers,
Carlos.
Joseph Myers Oct. 9, 2014, 12:31 a.m. UTC | #5
On Wed, 8 Oct 2014, Carlos O'Donell wrote:

> > +/* 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)						\
> 
> Does the soft-fp code care about implicit boolean coersion?

Not based on existing handling of rsigned in _FP_TO_INT.  I've made a note 
to review that as a coding style issue (I have a few other residual coding 
style issues in this code to deal with, although lots have been fixed).

> If I had to write this it would have written:
> 
> if ((ex) == 1 
>     && (_FP_ISSIGNAN (fs, wc, X) 
>         || _FP_ISSIGNAN (fs, wc, Y))
>   FP_SET_EXCEPTION (FP_EX_INVALID);
> 
> if ((ex) == 2)
>   FP_SET_EXCEPTION (FP_EX_INVALID);
> 
> Since this is *very* easy to read and understand given the description,
> but I don't know if the compiler generates better or worse code given
> the above.

The code is written to make it obvious that things can be folded for 
constant arguments to the macros, rather than based on what code a 
particular compiler version does or does not generate.  (If it's 
convenient to do things in a way that doesn't change compiler code 
generation at all, so making it obvious that a patch is safe for existing 
users not using the new features, that's a bonus, though it wasn't 
possible for this patch.)
Carlos O'Donell Oct. 9, 2014, 12:44 a.m. UTC | #6
On 10/08/2014 08:31 PM, Joseph S. Myers wrote:
> On Wed, 8 Oct 2014, Carlos O'Donell wrote:
> 
>>> +/* 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)						\
>>
>> Does the soft-fp code care about implicit boolean coersion?
> 
> Not based on existing handling of rsigned in _FP_TO_INT.  I've made a note 
> to review that as a coding style issue (I have a few other residual coding 
> style issues in this code to deal with, although lots have been fixed).

Thanks.

>> If I had to write this it would have written:
>>
>> if ((ex) == 1 
>>     && (_FP_ISSIGNAN (fs, wc, X) 
>>         || _FP_ISSIGNAN (fs, wc, Y))
>>   FP_SET_EXCEPTION (FP_EX_INVALID);
>>
>> if ((ex) == 2)
>>   FP_SET_EXCEPTION (FP_EX_INVALID);
>>
>> Since this is *very* easy to read and understand given the description,
>> but I don't know if the compiler generates better or worse code given
>> the above.
> 
> The code is written to make it obvious that things can be folded for 
> constant arguments to the macros, rather than based on what code a 
> particular compiler version does or does not generate.  (If it's 
> convenient to do things in a way that doesn't change compiler code 
> generation at all, so making it obvious that a patch is safe for existing 
> users not using the new features, that's a bonus, though it wasn't 
> possible for this patch.)

Oh well. I guess my objection to your even further complication to this
macro does not stand.

Would you consider adding a comment stating why the macro is written
as such?

Cheers,
Carlos.

Patch
diff mbox

diff --git a/soft-fp/double.h b/soft-fp/double.h
index 7782994..1e6283e 100644
--- a/soft-fp/double.h
+++ b/soft-fp/double.h
@@ -177,9 +177,9 @@  union _FP_UNION_D
 # define _FP_SQRT_MEAT_D(R, S, T, X, Q)	_FP_SQRT_MEAT_2 (R, S, T, X, Q)
 # define FP_FMA_D(R, X, Y, Z)		_FP_FMA (D, 2, 4, R, X, Y, Z)
 
-# define FP_CMP_D(r, X, Y, un)		_FP_CMP (D, 2, r, X, Y, un)
-# define FP_CMP_EQ_D(r, X, Y)		_FP_CMP_EQ (D, 2, r, X, Y)
-# define FP_CMP_UNORD_D(r, X, Y)	_FP_CMP_UNORD (D, 2, r, X, Y)
+# define FP_CMP_D(r, X, Y, un, ex)	_FP_CMP (D, 2, r, X, Y, un, ex)
+# define FP_CMP_EQ_D(r, X, Y, ex)	_FP_CMP_EQ (D, 2, r, X, Y, ex)
+# define FP_CMP_UNORD_D(r, X, Y, ex)	_FP_CMP_UNORD (D, 2, r, X, Y, ex)
 
 # define FP_TO_INT_D(r, X, rsz, rsg)	_FP_TO_INT (D, 2, r, X, rsz, rsg)
 # define FP_FROM_INT_D(X, r, rs, rt)	_FP_FROM_INT (D, 2, X, r, rs, rt)
@@ -299,9 +299,9 @@  union _FP_UNION_D
 /* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
    the target machine.  */
 
-# define FP_CMP_D(r, X, Y, un)		_FP_CMP (D, 1, r, X, Y, un)
-# define FP_CMP_EQ_D(r, X, Y)		_FP_CMP_EQ (D, 1, r, X, Y)
-# define FP_CMP_UNORD_D(r, X, Y)	_FP_CMP_UNORD (D, 1, r, X, Y)
+# define FP_CMP_D(r, X, Y, un, ex)	_FP_CMP (D, 1, r, X, Y, un, ex)
+# define FP_CMP_EQ_D(r, X, Y, ex)	_FP_CMP_EQ (D, 1, r, X, Y, ex)
+# define FP_CMP_UNORD_D(r, X, Y, ex)	_FP_CMP_UNORD (D, 1, r, X, Y, ex)
 
 # define FP_TO_INT_D(r, X, rsz, rsg)	_FP_TO_INT (D, 1, r, X, rsz, rsg)
 # define FP_FROM_INT_D(X, r, rs, rt)	_FP_FROM_INT (D, 1, X, r, rs, rt)
diff --git a/soft-fp/eqdf2.c b/soft-fp/eqdf2.c
index 006b1ef..e8ce12d 100644
--- a/soft-fp/eqdf2.c
+++ b/soft-fp/eqdf2.c
@@ -42,9 +42,7 @@  __eqdf2 (DFtype a, DFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_D (A, a);
   FP_UNPACK_RAW_D (B, b);
-  FP_CMP_EQ_D (r, A, B);
-  if (r && (FP_ISSIGNAN_D (A) || FP_ISSIGNAN_D (B)))
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_EQ_D (r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/eqsf2.c b/soft-fp/eqsf2.c
index 437ef99..2ee837d 100644
--- a/soft-fp/eqsf2.c
+++ b/soft-fp/eqsf2.c
@@ -42,9 +42,7 @@  __eqsf2 (SFtype a, SFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_S (A, a);
   FP_UNPACK_RAW_S (B, b);
-  FP_CMP_EQ_S (r, A, B);
-  if (r && (FP_ISSIGNAN_S (A) || FP_ISSIGNAN_S (B)))
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_EQ_S (r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/eqtf2.c b/soft-fp/eqtf2.c
index ffc558c..17b9d40 100644
--- a/soft-fp/eqtf2.c
+++ b/soft-fp/eqtf2.c
@@ -42,9 +42,7 @@  __eqtf2 (TFtype a, TFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_Q (A, a);
   FP_UNPACK_RAW_Q (B, b);
-  FP_CMP_EQ_Q (r, A, B);
-  if (r && (FP_ISSIGNAN_Q (A) || FP_ISSIGNAN_Q (B)))
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_EQ_Q (r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/extended.h b/soft-fp/extended.h
index 989b056..0dd6a87 100644
--- a/soft-fp/extended.h
+++ b/soft-fp/extended.h
@@ -287,9 +287,9 @@  union _FP_UNION_E
     }							\
   while (0)
 
-# define FP_CMP_E(r, X, Y, un)		_FP_CMP (E, 4, r, X, Y, un)
-# define FP_CMP_EQ_E(r, X, Y)		_FP_CMP_EQ (E, 4, r, X, Y)
-# define FP_CMP_UNORD_E(r, X, Y)	_FP_CMP_UNORD (E, 4, r, X, Y)
+# define FP_CMP_E(r, X, Y, un, ex)	_FP_CMP (E, 4, r, X, Y, un, ex)
+# define FP_CMP_EQ_E(r, X, Y, ex)	_FP_CMP_EQ (E, 4, r, X, Y, ex)
+# define FP_CMP_UNORD_E(r, X, Y, ex)	_FP_CMP_UNORD (E, 4, r, X, Y, ex)
 
 # define FP_TO_INT_E(r, X, rsz, rsg)	_FP_TO_INT (E, 4, r, X, rsz, rsg)
 # define FP_FROM_INT_E(X, r, rs, rt)	_FP_FROM_INT (E, 4, X, r, rs, rt)
@@ -489,9 +489,9 @@  union _FP_UNION_E
     }							\
   while (0)
 
-# define FP_CMP_E(r, X, Y, un)		_FP_CMP (E, 2, r, X, Y, un)
-# define FP_CMP_EQ_E(r, X, Y)		_FP_CMP_EQ (E, 2, r, X, Y)
-# define FP_CMP_UNORD_E(r, X, Y)	_FP_CMP_UNORD (E, 2, r, X, Y)
+# define FP_CMP_E(r, X, Y, un, ex)	_FP_CMP (E, 2, r, X, Y, un, ex)
+# define FP_CMP_EQ_E(r, X, Y, ex)	_FP_CMP_EQ (E, 2, r, X, Y, ex)
+# define FP_CMP_UNORD_E(r, X, Y, ex)	_FP_CMP_UNORD (E, 2, r, X, Y, ex)
 
 # define FP_TO_INT_E(r, X, rsz, rsg)	_FP_TO_INT (E, 2, r, X, rsz, rsg)
 # define FP_FROM_INT_E(X, r, rs, rt)	_FP_FROM_INT (E, 2, X, r, rs, rt)
diff --git a/soft-fp/gedf2.c b/soft-fp/gedf2.c
index 4ff9756..a8cc949 100644
--- a/soft-fp/gedf2.c
+++ b/soft-fp/gedf2.c
@@ -42,9 +42,7 @@  __gedf2 (DFtype a, DFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_D (A, a);
   FP_UNPACK_RAW_D (B, b);
-  FP_CMP_D (r, A, B, -2);
-  if (r == -2)
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_D (r, A, B, -2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/gesf2.c b/soft-fp/gesf2.c
index f3c5d2d..aa84b26 100644
--- a/soft-fp/gesf2.c
+++ b/soft-fp/gesf2.c
@@ -42,9 +42,7 @@  __gesf2 (SFtype a, SFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_S (A, a);
   FP_UNPACK_RAW_S (B, b);
-  FP_CMP_S (r, A, B, -2);
-  if (r == -2)
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_S (r, A, B, -2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/getf2.c b/soft-fp/getf2.c
index fb82b79..c852228 100644
--- a/soft-fp/getf2.c
+++ b/soft-fp/getf2.c
@@ -42,9 +42,7 @@  __getf2 (TFtype a, TFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_Q (A, a);
   FP_UNPACK_RAW_Q (B, b);
-  FP_CMP_Q (r, A, B, -2);
-  if (r == -2)
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_Q (r, A, B, -2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/ledf2.c b/soft-fp/ledf2.c
index 8b15d32..fb5bbb2 100644
--- a/soft-fp/ledf2.c
+++ b/soft-fp/ledf2.c
@@ -42,9 +42,7 @@  __ledf2 (DFtype a, DFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_D (A, a);
   FP_UNPACK_RAW_D (B, b);
-  FP_CMP_D (r, A, B, 2);
-  if (r == 2)
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_D (r, A, B, 2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/lesf2.c b/soft-fp/lesf2.c
index e86ac3f..1b67204 100644
--- a/soft-fp/lesf2.c
+++ b/soft-fp/lesf2.c
@@ -42,9 +42,7 @@  __lesf2 (SFtype a, SFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_S (A, a);
   FP_UNPACK_RAW_S (B, b);
-  FP_CMP_S (r, A, B, 2);
-  if (r == 2)
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_S (r, A, B, 2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/letf2.c b/soft-fp/letf2.c
index 94b7d78..1293519 100644
--- a/soft-fp/letf2.c
+++ b/soft-fp/letf2.c
@@ -42,9 +42,7 @@  __letf2 (TFtype a, TFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_Q (A, a);
   FP_UNPACK_RAW_Q (B, b);
-  FP_CMP_Q (r, A, B, 2);
-  if (r == 2)
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_Q (r, A, B, 2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index ec0bc42..af859e2 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)
 
diff --git a/soft-fp/quad.h b/soft-fp/quad.h
index 16e362f..c2e4133 100644
--- a/soft-fp/quad.h
+++ b/soft-fp/quad.h
@@ -182,9 +182,9 @@  union _FP_UNION_Q
 # define _FP_SQRT_MEAT_Q(R, S, T, X, Q)	_FP_SQRT_MEAT_4 (R, S, T, X, Q)
 # define FP_FMA_Q(R, X, Y, Z)		_FP_FMA (Q, 4, 8, R, X, Y, Z)
 
-# define FP_CMP_Q(r, X, Y, un)		_FP_CMP (Q, 4, r, X, Y, un)
-# define FP_CMP_EQ_Q(r, X, Y)		_FP_CMP_EQ (Q, 4, r, X, Y)
-# define FP_CMP_UNORD_Q(r, X, Y)	_FP_CMP_UNORD (Q, 4, r, X, Y)
+# define FP_CMP_Q(r, X, Y, un, ex)	_FP_CMP (Q, 4, r, X, Y, un, ex)
+# define FP_CMP_EQ_Q(r, X, Y, ex)	_FP_CMP_EQ (Q, 4, r, X, Y, ex)
+# define FP_CMP_UNORD_Q(r, X, Y, ex)	_FP_CMP_UNORD (Q, 4, r, X, Y, ex)
 
 # define FP_TO_INT_Q(r, X, rsz, rsg)	_FP_TO_INT (Q, 4, r, X, rsz, rsg)
 # define FP_FROM_INT_Q(X, r, rs, rt)	_FP_FROM_INT (Q, 4, X, r, rs, rt)
@@ -306,9 +306,9 @@  union _FP_UNION_Q
 # define _FP_SQRT_MEAT_Q(R, S, T, X, Q)	_FP_SQRT_MEAT_2 (R, S, T, X, Q)
 # define FP_FMA_Q(R, X, Y, Z)		_FP_FMA (Q, 2, 4, R, X, Y, Z)
 
-# define FP_CMP_Q(r, X, Y, un)		_FP_CMP (Q, 2, r, X, Y, un)
-# define FP_CMP_EQ_Q(r, X, Y)		_FP_CMP_EQ (Q, 2, r, X, Y)
-# define FP_CMP_UNORD_Q(r, X, Y)	_FP_CMP_UNORD (Q, 2, r, X, Y)
+# define FP_CMP_Q(r, X, Y, un, ex)	_FP_CMP (Q, 2, r, X, Y, un, ex)
+# define FP_CMP_EQ_Q(r, X, Y, ex)	_FP_CMP_EQ (Q, 2, r, X, Y, ex)
+# define FP_CMP_UNORD_Q(r, X, Y, ex)	_FP_CMP_UNORD (Q, 2, r, X, Y, ex)
 
 # define FP_TO_INT_Q(r, X, rsz, rsg)	_FP_TO_INT (Q, 2, r, X, rsz, rsg)
 # define FP_FROM_INT_Q(X, r, rs, rt)	_FP_FROM_INT (Q, 2, X, r, rs, rt)
diff --git a/soft-fp/single.h b/soft-fp/single.h
index 19fd647..efa8294 100644
--- a/soft-fp/single.h
+++ b/soft-fp/single.h
@@ -175,9 +175,9 @@  union _FP_UNION_S
 # define FP_FMA_S(R, X, Y, Z)	_FP_FMA (S, 1, 1, R, X, Y, Z)
 #endif
 
-#define FP_CMP_S(r, X, Y, un)	_FP_CMP (S, 1, r, X, Y, un)
-#define FP_CMP_EQ_S(r, X, Y)	_FP_CMP_EQ (S, 1, r, X, Y)
-#define FP_CMP_UNORD_S(r, X, Y)	_FP_CMP_UNORD (S, 1, r, X, Y)
+#define FP_CMP_S(r, X, Y, un, ex)	_FP_CMP (S, 1, r, X, Y, un, ex)
+#define FP_CMP_EQ_S(r, X, Y, ex)	_FP_CMP_EQ (S, 1, r, X, Y, ex)
+#define FP_CMP_UNORD_S(r, X, Y, ex)	_FP_CMP_UNORD (S, 1, r, X, Y, ex)
 
 #define FP_TO_INT_S(r, X, rsz, rsg)	_FP_TO_INT (S, 1, r, X, rsz, rsg)
 #define FP_FROM_INT_S(X, r, rs, rt)	_FP_FROM_INT (S, 1, X, r, rs, rt)
diff --git a/soft-fp/unorddf2.c b/soft-fp/unorddf2.c
index ceacb9e..e09a1ec 100644
--- a/soft-fp/unorddf2.c
+++ b/soft-fp/unorddf2.c
@@ -41,9 +41,7 @@  __unorddf2 (DFtype a, DFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_D (A, a);
   FP_UNPACK_RAW_D (B, b);
-  FP_CMP_UNORD_D (r, A, B);
-  if (r && (FP_ISSIGNAN_D (A) || FP_ISSIGNAN_D (B)))
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_UNORD_D (r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/unordsf2.c b/soft-fp/unordsf2.c
index 057f2c4..4d6be98 100644
--- a/soft-fp/unordsf2.c
+++ b/soft-fp/unordsf2.c
@@ -41,9 +41,7 @@  __unordsf2 (SFtype a, SFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_S (A, a);
   FP_UNPACK_RAW_S (B, b);
-  FP_CMP_UNORD_S (r, A, B);
-  if (r && (FP_ISSIGNAN_S (A) || FP_ISSIGNAN_S (B)))
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_UNORD_S (r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/soft-fp/unordtf2.c b/soft-fp/unordtf2.c
index 433a84f..79d3421 100644
--- a/soft-fp/unordtf2.c
+++ b/soft-fp/unordtf2.c
@@ -41,9 +41,7 @@  __unordtf2 (TFtype a, TFtype b)
   FP_INIT_EXCEPTIONS;
   FP_UNPACK_RAW_Q (A, a);
   FP_UNPACK_RAW_Q (B, b);
-  FP_CMP_UNORD_Q (r, A, B);
-  if (r && (FP_ISSIGNAN_Q (A) || FP_ISSIGNAN_Q (B)))
-    FP_SET_EXCEPTION (FP_EX_INVALID);
+  FP_CMP_UNORD_Q (r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/sysdeps/alpha/soft-fp/ots_cmpe.c b/sysdeps/alpha/soft-fp/ots_cmpe.c
index adeda84..41586ee 100644
--- a/sysdeps/alpha/soft-fp/ots_cmpe.c
+++ b/sysdeps/alpha/soft-fp/ots_cmpe.c
@@ -29,14 +29,9 @@  internal_compare (long al, long ah, long bl, long bh)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q (r, A, B, 2);
+  FP_CMP_Q (r, A, B, 2, 2);
 
-  /* Relative comparisons signal invalid operation if either operand is NaN. */
-  if (r == 2)
-    {
-      FP_SET_EXCEPTION(FP_EX_INVALID);
-      FP_HANDLE_EXCEPTIONS;
-    }
+  FP_HANDLE_EXCEPTIONS;
 
   return r;
 }
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_cmp.c b/sysdeps/sparc/sparc32/soft-fp/q_cmp.c
index 837b3dd..acc1d1d 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_cmp.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_cmp.c
@@ -30,10 +30,8 @@  int _Q_cmp(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q(r, B, A, 3);
+  FP_CMP_Q(r, B, A, 3, 1);
   if (r == -1) r = 2;
-  if (r == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-    FP_SET_EXCEPTION(FP_EX_INVALID);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c b/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c
index d4ac7bd..a5d4670 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_cmpe.c
@@ -31,10 +31,8 @@  int _Q_cmpe(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q(r, B, A, 3);
+  FP_CMP_Q(r, B, A, 3, 2);
   if (r == -1) r = 2;
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_feq.c b/sysdeps/sparc/sparc32/soft-fp/q_feq.c
index 61a8ff1..cb7db6d 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_feq.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_feq.c
@@ -30,9 +30,7 @@  int _Q_feq(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_EQ_Q(r, A, B);
-  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_EQ_Q(r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return !r;
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fge.c b/sysdeps/sparc/sparc32/soft-fp/q_fge.c
index 7fca349..cca1003 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_fge.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_fge.c
@@ -30,9 +30,7 @@  int _Q_fge(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q(r, B, A, 3);
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, 3, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return (r <= 0);
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fgt.c b/sysdeps/sparc/sparc32/soft-fp/q_fgt.c
index f5b2acf..00f837d 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_fgt.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_fgt.c
@@ -30,9 +30,7 @@  int _Q_fgt(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q(r, B, A, 3);
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, 3, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return (r == -1);
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fle.c b/sysdeps/sparc/sparc32/soft-fp/q_fle.c
index c108fb9..b44f448 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_fle.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_fle.c
@@ -30,9 +30,7 @@  int _Q_fle(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q(r, B, A, -2);
-  if (r == -2)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, -2, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return (r >= 0);
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_flt.c b/sysdeps/sparc/sparc32/soft-fp/q_flt.c
index 56d140e..caa188d 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_flt.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_flt.c
@@ -30,9 +30,7 @@  int _Q_flt(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_Q(r, B, A, 3);
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, 3, 2);
   FP_HANDLE_EXCEPTIONS;
 
   return (r == 1);
diff --git a/sysdeps/sparc/sparc32/soft-fp/q_fne.c b/sysdeps/sparc/sparc32/soft-fp/q_fne.c
index 78c2d6f..e22f6c9 100644
--- a/sysdeps/sparc/sparc32/soft-fp/q_fne.c
+++ b/sysdeps/sparc/sparc32/soft-fp/q_fne.c
@@ -30,9 +30,7 @@  int _Q_fne(const long double a, const long double b)
 
   FP_UNPACK_RAW_Q(A, a);
   FP_UNPACK_RAW_Q(B, b);
-  FP_CMP_EQ_Q(r, A, B);
-  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_EQ_Q(r, A, B, 1);
   FP_HANDLE_EXCEPTIONS;
 
   return r;
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c b/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c
index 1929a08..dadb369 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_cmp.c
@@ -31,10 +31,8 @@  int _Qp_cmp(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_Q(r, B, A, 3);
+  FP_CMP_Q(r, B, A, 3, 1);
   if (r == -1) r = 2;
-  if (r == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-    FP_SET_EXCEPTION(FP_EX_INVALID);
   QP_HANDLE_EXCEPTIONS(
 	__asm (
 "	ldd [%0], %%f52\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c b/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c
index ee25b5e..c56d623 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_cmpe.c
@@ -32,10 +32,8 @@  int _Qp_cmpe(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_Q(r, B, A, 3);
+  FP_CMP_Q(r, B, A, 3, 2);
   if (r == -1) r = 2;
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
   QP_HANDLE_EXCEPTIONS(
 	__asm (
 "	ldd [%0], %%f52\n"
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_feq.c b/sysdeps/sparc/sparc64/soft-fp/qp_feq.c
index 36eef5a..67b6b87 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_feq.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_feq.c
@@ -31,9 +31,7 @@  int _Qp_feq(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_EQ_Q(r, A, B);
-  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_EQ_Q(r, A, B, 1);
 
   QP_HANDLE_EXCEPTIONS(
 	__asm (
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fge.c b/sysdeps/sparc/sparc64/soft-fp/qp_fge.c
index 3f0c16b..690a741 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_fge.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_fge.c
@@ -31,9 +31,7 @@  int _Qp_fge(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_Q(r, B, A, 3);
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, 3, 2);
 
   QP_HANDLE_EXCEPTIONS(
 	__asm (
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c b/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c
index 2b915be..423bd5a 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_fgt.c
@@ -31,9 +31,7 @@  int _Qp_fgt(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_Q(r, B, A, 3);
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, 3, 2);
 
   QP_HANDLE_EXCEPTIONS(
 	__asm (
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fle.c b/sysdeps/sparc/sparc64/soft-fp/qp_fle.c
index 74f80f4..f915152 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_fle.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_fle.c
@@ -31,9 +31,7 @@  int _Qp_fle(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_Q(r, B, A, -2);
-  if (r == -2)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, -2, 2);
 
   QP_HANDLE_EXCEPTIONS(
 	__asm (
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_flt.c b/sysdeps/sparc/sparc64/soft-fp/qp_flt.c
index a4c8e05..c03cd72 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_flt.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_flt.c
@@ -31,9 +31,7 @@  int _Qp_flt(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_Q(r, B, A, 3);
-  if (r == 3)
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_Q(r, B, A, 3, 2);
 
   QP_HANDLE_EXCEPTIONS(
 	__asm (
diff --git a/sysdeps/sparc/sparc64/soft-fp/qp_fne.c b/sysdeps/sparc/sparc64/soft-fp/qp_fne.c
index 828c394..948077c 100644
--- a/sysdeps/sparc/sparc64/soft-fp/qp_fne.c
+++ b/sysdeps/sparc/sparc64/soft-fp/qp_fne.c
@@ -31,9 +31,7 @@  int _Qp_fne(const long double *a, const long double *b)
   FP_INIT_ROUNDMODE;
   FP_UNPACK_RAW_QP(A, a);
   FP_UNPACK_RAW_QP(B, b);
-  FP_CMP_EQ_Q(r, A, B);
-  if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
-    FP_SET_EXCEPTION(FP_EX_INVALID);
+  FP_CMP_EQ_Q(r, A, B, 1);
 
   QP_HANDLE_EXCEPTIONS(
 	__asm (