This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Simplify C99 isgreater macros


Simplify the C99 isgreater macros.  Although some support was added
in GCC 2.97, not all targets added support until GCC 3.1.  Therefore
only use the builtins in math.h from GCC 3.1 onwards, and defer to
generic macros otherwise.  Improve the generic isunordered macro
to use compares rather than call fpclassify twice - this is not only faster
but also correct for signaling NaNs.

OK for commit?

ChangeLog:
2017-09-25  Wilco Dijkstra  <wdijkstr@arm.com>

	* math/math.h: Improve handling of C99 isgreater macros.
	* sysdeps/alpha/fpu/bits/mathinline.h: Delete file.
	* sysdeps/m68k/m680x0/fpu/bits/mathinline.h: Remove isgreater macros.
	* sysdeps/powerpc/bits/mathinline.h: Likewise.
	* sysdeps/sparc/fpu/bits/mathinline.h: Likewise.
	* sysdeps/x86/fpu/bits/mathinline.h: Likewise.
--
diff --git a/math/math.h b/math/math.h
index c6c289d5d2f555c8af0ee8963e446c0f960ea882..63002b42cae797f868d771979bd05f7cb7745e96 100644
--- a/math/math.h
+++ b/math/math.h
@@ -652,19 +652,47 @@ iszero (__T __val)
 # define __NO_MATH_INLINES	1
 #endif
 
-#if defined __USE_ISOC99 && __GNUC_PREREQ(2,97)
+#ifdef __USE_ISOC99
+# if __GNUC_PREREQ(3, 1)
 /* ISO C99 defines some macros to compare number while taking care for
    unordered numbers.  Many FPUs provide special instructions to support
    these operations.  Generic support in GCC for these as builtins went
-   in before 3.0.0, but not all cpus added their patterns.  We define
-   versions that use the builtins here, and <bits/mathinline.h> will
-   undef/redefine as appropriate for the specific GCC version in use.  */
-# define isgreater(x, y)	__builtin_isgreater(x, y)
-# define isgreaterequal(x, y)	__builtin_isgreaterequal(x, y)
-# define isless(x, y)		__builtin_isless(x, y)
-# define islessequal(x, y)	__builtin_islessequal(x, y)
-# define islessgreater(x, y)	__builtin_islessgreater(x, y)
-# define isunordered(u, v)	__builtin_isunordered(u, v)
+   in 2.97, but not all cpus added their patterns until 3.1.  Therefore
+   we enable the builtins from 3.1 onwards and use a generic implementation
+   othwerwise.  */
+#  define isgreater(x, y)	__builtin_isgreater(x, y)
+#  define isgreaterequal(x, y)	__builtin_isgreaterequal(x, y)
+#  define isless(x, y)		__builtin_isless(x, y)
+#  define islessequal(x, y)	__builtin_islessequal(x, y)
+#  define islessgreater(x, y)	__builtin_islessgreater(x, y)
+#  define isunordered(u, v)	__builtin_isunordered(u, v)
+# else
+#  define isgreater(x, y) \
+  (__extension__							      \
+   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
+      !isunordered (__x, __y) && __x > __y; }))
+#  define isgreaterequal(x, y) \
+  (__extension__							      \
+   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
+      !isunordered (__x, __y) && __x >= __y; }))
+#  define isless(x, y) \
+  (__extension__							      \
+   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
+      !isunordered (__x, __y) && __x < __y; }))
+#  define islessequal(x, y) \
+  (__extension__							      \
+   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
+      !isunordered (__x, __y) && __x <= __y; }))
+#  define islessgreater(x, y) \
+  (__extension__							      \
+   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
+      !isunordered (__x, __y) && (__x < __y || __y < __x); }))
+/* isunordered must always check both operands first for signaling NaNs.  */
+#  define isunordered(u, v) \
+  (__extension__							      \
+   ({ __typeof__(u) __u = (u); __typeof__(v) __v = (v);			      \
+     __u != __v && (__u != __u || __v != __v); }))
+# endif
 #endif
 
 /* Get machine-dependent inline versions (if there are any).  */
@@ -758,59 +786,6 @@ iszero (__T __val)
 # endif
 #endif /* __FINITE_MATH_ONLY__ > 0.  */
 
-#ifdef __USE_ISOC99
-/* If we've still got undefined comparison macros, provide defaults.  */
-
-/* Return nonzero value if X is greater than Y.  */
-# ifndef isgreater
-#  define isgreater(x, y) \
-  (__extension__							      \
-   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
-      !isunordered (__x, __y) && __x > __y; }))
-# endif
-
-/* Return nonzero value if X is greater than or equal to Y.  */
-# ifndef isgreaterequal
-#  define isgreaterequal(x, y) \
-  (__extension__							      \
-   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
-      !isunordered (__x, __y) && __x >= __y; }))
-# endif
-
-/* Return nonzero value if X is less than Y.  */
-# ifndef isless
-#  define isless(x, y) \
-  (__extension__							      \
-   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
-      !isunordered (__x, __y) && __x < __y; }))
-# endif
-
-/* Return nonzero value if X is less than or equal to Y.  */
-# ifndef islessequal
-#  define islessequal(x, y) \
-  (__extension__							      \
-   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
-      !isunordered (__x, __y) && __x <= __y; }))
-# endif
-
-/* Return nonzero value if either X is less than Y or Y is less than X.  */
-# ifndef islessgreater
-#  define islessgreater(x, y) \
-  (__extension__							      \
-   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
-      !isunordered (__x, __y) && (__x < __y || __y < __x); }))
-# endif
-
-/* Return nonzero value if arguments are unordered.  */
-# ifndef isunordered
-#  define isunordered(u, v) \
-  (__extension__							      \
-   ({ __typeof__(u) __u = (u); __typeof__(v) __v = (v);			      \
-      fpclassify (__u) == FP_NAN || fpclassify (__v) == FP_NAN; }))
-# endif
-
-#endif
-
 #if __GLIBC_USE (IEC_60559_BFP_EXT)
 /* An expression whose type has the widest of the evaluation formats
    of X and Y (which are of floating-point types).  */
diff --git a/sysdeps/alpha/fpu/bits/mathinline.h b/sysdeps/alpha/fpu/bits/mathinline.h
deleted file mode 100644
index ceb8a4416c7b1d8372cd2048893536966de8ead1..0000000000000000000000000000000000000000
--- a/sysdeps/alpha/fpu/bits/mathinline.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Inline math functions for Alpha.
-   Copyright (C) 1996-2017 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-   Contributed by David Mosberger-Tang.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library.  If not, see
-   <http://www.gnu.org/licenses/>.  */
-
-#ifndef _MATH_H
-# error "Never use <bits/mathinline.h> directly; include <math.h> instead."
-#endif
-
-#ifndef __extern_inline
-# define __MATH_INLINE __inline
-#else
-# define __MATH_INLINE __extern_inline
-#endif
-
-#if defined __USE_ISOC99 && defined __GNUC__ && !__GNUC_PREREQ(3,0)
-# undef isgreater
-# undef isgreaterequal
-# undef isless
-# undef islessequal
-# undef islessgreater
-# undef isunordered
-# define isunordered(u, v)				\
-  (__extension__					\
-   ({ double __r, __u = (u), __v = (v);			\
-      __asm ("cmptun/su %1,%2,%0\n\ttrapb"		\
-	     : "=&f" (__r) : "f" (__u), "f"(__v));	\
-      __r != 0; }))
-#endif /* ISO C99 */
-
-#endif /* __NO_MATH_INLINES */
diff --git a/sysdeps/m68k/m680x0/fpu/bits/mathinline.h b/sysdeps/m68k/m680x0/fpu/bits/mathinline.h
index 759c83d2b14323b13eccbfc02c15298fd875257c..dcc2a4e829ee62cad980f574a707d4934cb38002 100644
--- a/sysdeps/m68k/m680x0/fpu/bits/mathinline.h
+++ b/sysdeps/m68k/m680x0/fpu/bits/mathinline.h
@@ -28,64 +28,6 @@
 
 #ifdef	__GNUC__
 
-#ifdef __USE_ISOC99
-/* GCC 3.1 and up have builtins that actually can be used.  */
-# if !__GNUC_PREREQ (3,1)
-/* ISO C99 defines some macros to perform unordered comparisons.  The
-   m68k FPU supports this with special opcodes and we should use them.
-   These must not be inline functions since we have to be able to handle
-   all floating-point types.  */
-#  undef isgreater
-#  undef isgreaterequal
-#  undef isless
-#  undef islessequal
-#  undef islessgreater
-#  undef isunordered
-#  define isgreater(x, y)					\
-   __extension__					\
-   ({ char __result;					\
-      __asm__ ("fcmp%.x %2,%1; fsogt %0"		\
-	       : "=dm" (__result) : "f" (x), "f" (y));	\
-      __result != 0; })
-
-#  define isgreaterequal(x, y)				\
-   __extension__					\
-   ({ char __result;					\
-      __asm__ ("fcmp%.x %2,%1; fsoge %0"		\
-	       : "=dm" (__result) : "f" (x), "f" (y));	\
-      __result != 0; })
-
-#  define isless(x, y)					\
-   __extension__					\
-   ({ char __result;					\
-      __asm__ ("fcmp%.x %2,%1; fsolt %0"		\
-	       : "=dm" (__result) : "f" (x), "f" (y));	\
-      __result != 0; })
-
-#  define islessequal(x, y)				\
-   __extension__					\
-   ({ char __result;					\
-      __asm__ ("fcmp%.x %2,%1; fsole %0"		\
-	       : "=dm" (__result) : "f" (x), "f" (y));	\
-      __result != 0; })
-
-#  define islessgreater(x, y)				\
-   __extension__					\
-   ({ char __result;					\
-      __asm__ ("fcmp%.x %2,%1; fsogl %0"		\
-	       : "=dm" (__result) : "f" (x), "f" (y));	\
-      __result != 0; })
-
-#  define isunordered(x, y)				\
-   __extension__					\
-   ({ char __result;					\
-      __asm__ ("fcmp%.x %2,%1; fsun %0"			\
-	       : "=dm" (__result) : "f" (x), "f" (y));	\
-      __result != 0; })
-# endif /* GCC 3.1 */
-#endif
-
-
 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
     || defined __LIBC_INTERNAL_MATH_INLINES
 
diff --git a/sysdeps/powerpc/bits/mathinline.h b/sysdeps/powerpc/bits/mathinline.h
index 3c297899c50bb148059e6339db9c68d8da93229c..a5f63e452bc147056c5b234753218af20c326329 100644
--- a/sysdeps/powerpc/bits/mathinline.h
+++ b/sysdeps/powerpc/bits/mathinline.h
@@ -28,34 +28,6 @@
 
 #if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_FPRS__
 
-#ifdef __USE_ISOC99
-# if !__GNUC_PREREQ (2,97)
-#  define __unordered_cmp(x, y) \
-  (__extension__							      \
-   ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y);			      \
-      unsigned __r;							      \
-      __asm__("fcmpu 7,%1,%2 ; mfcr %0" : "=r" (__r) : "f" (__x), "f"(__y)    \
-              : "cr7");  \
-      __r; }))
-
-#  undef isgreater
-#  undef isgreaterequal
-#  undef isless
-#  undef islessequal
-#  undef islessgreater
-#  undef isunordered
-
-#  define isgreater(x, y) (__unordered_cmp (x, y) >> 2 & 1)
-#  define isgreaterequal(x, y) ((__unordered_cmp (x, y) & 6) != 0)
-#  define isless(x, y) (__unordered_cmp (x, y) >> 3 & 1)
-#  define islessequal(x, y) ((__unordered_cmp (x, y) & 0xA) != 0)
-#  define islessgreater(x, y) ((__unordered_cmp (x, y) & 0xC) != 0)
-#  define isunordered(x, y) (__unordered_cmp (x, y) & 1)
-
-# endif /* __GNUC_PREREQ (2,97) */
-
-#endif /* __USE_ISOC99 */
-
 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
 
 #ifdef __USE_ISOC99
diff --git a/sysdeps/sparc/fpu/bits/mathinline.h b/sysdeps/sparc/fpu/bits/mathinline.h
index 9b2847b6a882c2eb029c835c1e34101257240928..3654938b1ca3115ba4d570eefebc1e762b8bca02 100644
--- a/sysdeps/sparc/fpu/bits/mathinline.h
+++ b/sysdeps/sparc/fpu/bits/mathinline.h
@@ -25,105 +25,6 @@
 
 #ifdef __GNUC__
 
-#if defined __USE_ISOC99 && !__GNUC_PREREQ (3, 0)
-# undef isgreater
-# undef isgreaterequal
-# undef isless
-# undef islessequal
-# undef islessgreater
-# undef isunordered
-
-# if __WORDSIZE == 32
-
-#  ifndef __NO_LONG_DOUBLE_MATH
-
-#   define __unordered_cmp(x, y) \
-  (__extension__							      \
-   ({ unsigned __r;							      \
-      if (sizeof (x) == 4 && sizeof (y) == 4)				      \
-	{								      \
-	  float __x = (x); float __y = (y);				      \
-	  __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),      \
-		   "f" (__y) : "cc");					      \
-	}								      \
-      else if (sizeof (x) <= 8 && sizeof (y) <= 8)			      \
-	{								      \
-	  double __x = (x); double __y = (y);				      \
-	  __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
-		   "f" (__y) : "cc");					      \
-	}								      \
-      else								      \
-	{								      \
-	  long double __x = (x); long double __y = (y);			      \
-	  extern int _Q_cmp (const long double a, const long double b);	      \
-	  __r = _Q_cmp (__x, __y) << 10;				      \
-	}								      \
-      __r; }))
-
-#  else
-
-#   define __unordered_cmp(x, y) \
-  (__extension__							      \
-   ({ unsigned __r;							      \
-      if (sizeof (x) == 4 && sizeof (y) == 4)				      \
-	{								      \
-	  float __x = (x); float __y = (y);				      \
-	  __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x),      \
-		   "f" (__y) : "cc");					      \
-	}								      \
-      else								      \
-	{								      \
-	  double __x = (x); double __y = (y);				      \
-	  __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
-		   "f" (__y) : "cc");					      \
-	}								      \
-      __r; }))
-
-#  endif
-
-#  define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10))
-#  define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0)
-#  define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10))
-#  define islessequal(x, y) ((__unordered_cmp (x, y) & (2 << 10)) == 0)
-#  define islessgreater(x, y) (((__unordered_cmp (x, y) + (1 << 10)) & (2 << 10)) != 0)
-#  define isunordered(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (3 << 10))
-
-# else /* sparc64 */
-
-#  define __unordered_v9cmp(x, y, op, qop) \
-  (__extension__							      \
-   ({ unsigned __r;						      	      \
-      if (sizeof (x) == 4 && sizeof (y) == 4)				      \
-	{								      \
-	  float __x = (x); float __y = (y);				      \
-	  __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"	      \
-		   : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
-	}								      \
-      else if (sizeof (x) <= 8 && sizeof (y) <= 8)			      \
-	{								      \
-	  double __x = (x); double __y = (y);				      \
-	  __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"	      \
-		   : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
-	}								      \
-      else								      \
-	{								      \
-	  long double __x = (x); long double __y = (y);			      \
-	  extern int _Qp_cmp (const long double *a, const long double *b);    \
-	  __r = qop;						      	      \
-	}								      \
-      __r; }))
-
-#  define isgreater(x, y) __unordered_v9cmp(x, y, "g", _Qp_cmp (&__x, &__y) == 2)
-#  define isgreaterequal(x, y) __unordered_v9cmp(x, y, "ge", (_Qp_cmp (&__x, &__y) & 1) == 0)
-#  define isless(x, y) __unordered_v9cmp(x, y, "l", _Qp_cmp (&__x, &__y) == 1)
-#  define islessequal(x, y) __unordered_v9cmp(x, y, "le", (_Qp_cmp (&__x, &__y) & 2) == 0)
-#  define islessgreater(x, y) __unordered_v9cmp(x, y, "lg", ((_Qp_cmp (&__x, &__y) + 1) & 2) != 0)
-#  define isunordered(x, y) __unordered_v9cmp(x, y, "u", _Qp_cmp (&__x, &__y) == 3)
-
-# endif /* sparc64 */
-
-#endif /* __USE_ISOC99 */
-
 #if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__
 
 # ifndef __extern_inline
diff --git a/sysdeps/x86/fpu/bits/mathinline.h b/sysdeps/x86/fpu/bits/mathinline.h
index 41250b452c7c291537a7ba3718b55f58c90a4600..cf29751a2781d11cd835b2e8213443b52d84f10f 100644
--- a/sysdeps/x86/fpu/bits/mathinline.h
+++ b/sysdeps/x86/fpu/bits/mathinline.h
@@ -26,100 +26,6 @@
 # define __MATH_INLINE __extern_always_inline
 #endif
 
-
-#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2
-/* GCC 2.97 and up have builtins that actually can be used.  */
-# if !__GNUC_PREREQ (2,97)
-/* ISO C99 defines some macros to perform unordered comparisons.  The
-   ix87 FPU supports this with special opcodes and we should use them.
-   These must not be inline functions since we have to be able to handle
-   all floating-point types.  */
-#  undef isgreater
-#  undef isgreaterequal
-#  undef isless
-#  undef islessequal
-#  undef islessgreater
-#  undef isunordered
-#  ifdef __i686__
-/* For the PentiumPro and more recent processors we can provide
-   better code.  */
-#   define isgreater(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucomip %%st(1), %%st; seta %%al"			      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");	      \
-	__result; })
-#   define isgreaterequal(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucomip %%st(1), %%st; setae %%al"			      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");	      \
-	__result; })
-
-#   define isless(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucomip %%st(1), %%st; seta %%al"			      \
-		 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");	      \
-	__result; })
-
-#   define islessequal(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucomip %%st(1), %%st; setae %%al"			      \
-		 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st");	      \
-	__result; })
-
-#   define islessgreater(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucomip %%st(1), %%st; setne %%al"			      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");	      \
-	__result; })
-
-#   define isunordered(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucomip %%st(1), %%st; setp %%al"			      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st");	      \
-	__result; })
-#  else
-/* This is the dumb, portable code for i386 and above.  */
-#   define isgreater(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"	      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
-	__result; })
-
-#   define isgreaterequal(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"	      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
-	__result; })
-
-#   define isless(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al"	      \
-		 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
-	__result; })
-
-#   define islessequal(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al"	      \
-		 : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \
-	__result; })
-
-#   define islessgreater(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al"	      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
-	__result; })
-
-#   define isunordered(x, y) \
-     ({ register char __result;						      \
-	__asm__ ("fucompp; fnstsw; sahf; setp %%al"			      \
-		 : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \
-	__result; })
-#  endif /* __i686__ */
-# endif	/* GCC 2.97 */
-
-#endif
-
-
 /* The gcc, version 2.7 or below, has problems with all this inlining
    code.  So disable it for this version of the compiler.  */
 #if __GNUC_PREREQ (2, 8)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]