changeset 9645:c8174371956e

Exploit the __builtin_signbit GCC built-in.
author Bruno Haible <bruno@clisp.org>
date Sat, 26 Jan 2008 02:26:52 +0100
parents 42367c277240
children a113e473cc98
files ChangeLog lib/math.in.h m4/math_h.m4 m4/signbit.m4 modules/math
diffstat 5 files changed, 165 insertions(+), 102 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-01-25  Paul Eggert  <eggert@cs.ucla.edu>
+            Bruno Haible  <bruno@clisp.org>
+
+	* m4/signbit.m4 (gl_SIGNBIT): Require a macro definition. Test whether
+	the GCC builtins for signbits are present and set
+	REPLACE_SIGNBIT_USING_GCC if so.
+	* lib/math.in.h (signbit): Define using GCC builtins if
+	REPLACE_SIGNBIT_USING_GCC is set.
+	* m4/math_h.m4 (gl_MATH_H_DEFAULTS): Initialize
+	REPLACE_SIGNBIT_USING_GCC.
+	* modules/math (Makefile.am): Substitute REPLACE_SIGNBIT_USING_GCC.
+
 2008-01-25  Jim Meyering  <meyering@redhat.com>
 
 	Prefer <config.h> over "config.h".  See autoconf doc for explanation.
--- a/lib/math.in.h
+++ b/lib/math.in.h
@@ -353,6 +353,14 @@
 
 
 #if @GNULIB_SIGNBIT@
+# if @REPLACE_SIGNBIT_USING_GCC@
+#  undef signbit
+   /* GCC 4.0 and newer provides three built-ins for signbit.  */
+#  define signbit(x) \
+   (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \
+    sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \
+    __builtin_signbitf (x))
+# endif
 # if @REPLACE_SIGNBIT@
 #  undef signbit
 extern int gl_signbitf (float arg);
--- a/m4/math_h.m4
+++ b/m4/math_h.m4
@@ -1,5 +1,5 @@
-# math_h.m4 serial 8
-dnl Copyright (C) 2007 Free Software Foundation, Inc.
+# math_h.m4 serial 9
+dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -36,30 +36,31 @@
   GNULIB_TRUNCF=0;   AC_SUBST([GNULIB_TRUNCF])
   GNULIB_TRUNCL=0;   AC_SUBST([GNULIB_TRUNCL])
   dnl Assume proper GNU behavior unless another module says otherwise.
-  HAVE_DECL_ACOSL=1;    AC_SUBST([HAVE_DECL_ACOSL])
-  HAVE_DECL_ASINL=1;    AC_SUBST([HAVE_DECL_ASINL])
-  HAVE_DECL_ATANL=1;    AC_SUBST([HAVE_DECL_ATANL])
-  HAVE_DECL_COSL=1;     AC_SUBST([HAVE_DECL_COSL])
-  HAVE_DECL_EXPL=1;     AC_SUBST([HAVE_DECL_EXPL])
-  HAVE_DECL_FREXPL=1;   AC_SUBST([HAVE_DECL_FREXPL])
-  HAVE_DECL_LDEXPL=1;   AC_SUBST([HAVE_DECL_LDEXPL])
-  HAVE_DECL_LOGL=1;     AC_SUBST([HAVE_DECL_LOGL])
-  HAVE_DECL_SINL=1;     AC_SUBST([HAVE_DECL_SINL])
-  HAVE_DECL_SQRTL=1;    AC_SUBST([HAVE_DECL_SQRTL])
-  HAVE_DECL_TANL=1;     AC_SUBST([HAVE_DECL_TANL])
-  HAVE_DECL_TRUNC=1;    AC_SUBST([HAVE_DECL_TRUNC])
-  HAVE_DECL_TRUNCF=1;   AC_SUBST([HAVE_DECL_TRUNCF])
-  HAVE_DECL_TRUNCL=1;   AC_SUBST([HAVE_DECL_TRUNCL])
-  REPLACE_CEILF=0;      AC_SUBST([REPLACE_CEILF])
-  REPLACE_CEILL=0;      AC_SUBST([REPLACE_CEILL])
-  REPLACE_FLOORF=0;     AC_SUBST([REPLACE_FLOORF])
-  REPLACE_FLOORL=0;     AC_SUBST([REPLACE_FLOORL])
-  REPLACE_FREXP=0;      AC_SUBST([REPLACE_FREXP])
-  REPLACE_FREXPL=0;     AC_SUBST([REPLACE_FREXPL])
-  REPLACE_ISFINITE=0;   AC_SUBST([REPLACE_ISFINITE])
-  REPLACE_LDEXPL=0;     AC_SUBST([REPLACE_LDEXPL])
-  REPLACE_ROUND=0;      AC_SUBST([REPLACE_ROUND])
-  REPLACE_ROUNDF=0;     AC_SUBST([REPLACE_ROUNDF])
-  REPLACE_ROUNDL=0;     AC_SUBST([REPLACE_ROUNDL])
-  REPLACE_SIGNBIT=0;    AC_SUBST([REPLACE_SIGNBIT])
+  HAVE_DECL_ACOSL=1;           AC_SUBST([HAVE_DECL_ACOSL])
+  HAVE_DECL_ASINL=1;           AC_SUBST([HAVE_DECL_ASINL])
+  HAVE_DECL_ATANL=1;           AC_SUBST([HAVE_DECL_ATANL])
+  HAVE_DECL_COSL=1;            AC_SUBST([HAVE_DECL_COSL])
+  HAVE_DECL_EXPL=1;            AC_SUBST([HAVE_DECL_EXPL])
+  HAVE_DECL_FREXPL=1;          AC_SUBST([HAVE_DECL_FREXPL])
+  HAVE_DECL_LDEXPL=1;          AC_SUBST([HAVE_DECL_LDEXPL])
+  HAVE_DECL_LOGL=1;            AC_SUBST([HAVE_DECL_LOGL])
+  HAVE_DECL_SINL=1;            AC_SUBST([HAVE_DECL_SINL])
+  HAVE_DECL_SQRTL=1;           AC_SUBST([HAVE_DECL_SQRTL])
+  HAVE_DECL_TANL=1;            AC_SUBST([HAVE_DECL_TANL])
+  HAVE_DECL_TRUNC=1;           AC_SUBST([HAVE_DECL_TRUNC])
+  HAVE_DECL_TRUNCF=1;          AC_SUBST([HAVE_DECL_TRUNCF])
+  HAVE_DECL_TRUNCL=1;          AC_SUBST([HAVE_DECL_TRUNCL])
+  REPLACE_CEILF=0;             AC_SUBST([REPLACE_CEILF])
+  REPLACE_CEILL=0;             AC_SUBST([REPLACE_CEILL])
+  REPLACE_FLOORF=0;            AC_SUBST([REPLACE_FLOORF])
+  REPLACE_FLOORL=0;            AC_SUBST([REPLACE_FLOORL])
+  REPLACE_FREXP=0;             AC_SUBST([REPLACE_FREXP])
+  REPLACE_FREXPL=0;            AC_SUBST([REPLACE_FREXPL])
+  REPLACE_ISFINITE=0;          AC_SUBST([REPLACE_ISFINITE])
+  REPLACE_LDEXPL=0;            AC_SUBST([REPLACE_LDEXPL])
+  REPLACE_ROUND=0;             AC_SUBST([REPLACE_ROUND])
+  REPLACE_ROUNDF=0;            AC_SUBST([REPLACE_ROUNDF])
+  REPLACE_ROUNDL=0;            AC_SUBST([REPLACE_ROUNDL])
+  REPLACE_SIGNBIT=0;           AC_SUBST([REPLACE_SIGNBIT])
+  REPLACE_SIGNBIT_USING_GCC=0; AC_SUBST([REPLACE_SIGNBIT_USING_GCC])
 ])
--- a/m4/signbit.m4
+++ b/m4/signbit.m4
@@ -1,5 +1,5 @@
-# signbit.m4 serial 2
-dnl Copyright (C) 2007 Free Software Foundation, Inc.
+# signbit.m4 serial 3
+dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -11,7 +11,119 @@
     [
       AC_TRY_RUN([
 #include <math.h>
+/* If signbit is defined as a function, don't use it, since calling it for
+   'float' or 'long double' arguments would involve conversions.
+   If signbit is not declared at all but exists as a library function, don't
+   use it, since the prototype may not match.
+   If signbit is not declared at all but exists as a compiler built-in, don't
+   use it, since it's preferable to use __builtin_signbit* (no warnings,
+   no conversions).  */
+#ifndef signbit
+# error "signbit should be a macro"
+#endif
 #include <string.h>
+]gl_SIGNBIT_TEST_PROGRAM
+, [gl_cv_func_signbit=yes], [gl_cv_func_signbit=no],
+        [gl_cv_func_signbit="guessing no"])
+    ])
+  dnl GCC 4.0 and newer provides three built-ins for signbit.
+  dnl They can be used without warnings, also in C++, regardless of <math.h>.
+  dnl But they may expand to calls to functions, which may or may not be in
+  dnl libc.
+  AC_CACHE_CHECK([for signbit compiler built-ins], [gl_cv_func_signbit_gcc],
+    [
+      AC_TRY_RUN([
+#if __GNUC__ >= 4
+# define signbit(x) \
+   (sizeof (x) == sizeof (long double) ? __builtin_signbitl (x) : \
+    sizeof (x) == sizeof (double) ? __builtin_signbit (x) : \
+    __builtin_signbitf (x))
+#else
+# error "signbit should be three compiler built-ins"
+#endif
+#include <string.h>
+]gl_SIGNBIT_TEST_PROGRAM
+, [gl_cv_func_signbit_gcc=yes], [gl_cv_func_signbit_gcc=no],
+        [gl_cv_func_signbit_gcc="guessing no"])
+    ])
+  dnl Use the compiler built-ins whenever possible, because they are more
+  dnl efficient than the system library functions (if they exist).
+  if test "$gl_cv_func_signbit_gcc" = yes; then
+    REPLACE_SIGNBIT_USING_GCC=1
+  else
+    if test "$gl_cv_func_signbit" != yes; then
+      REPLACE_SIGNBIT=1
+      AC_LIBOBJ([signbitf])
+      AC_LIBOBJ([signbitd])
+      AC_LIBOBJ([signbitl])
+      gl_FLOAT_SIGN_LOCATION
+      gl_DOUBLE_SIGN_LOCATION
+      gl_LONG_DOUBLE_SIGN_LOCATION
+      if test "$gl_cv_cc_float_signbit" = unknown; then
+        dnl Test whether copysignf() is declared.
+        AC_CHECK_DECLS([copysignf], , , [#include <math.h>])
+        if test "$ac_cv_have_decl_copysignf" = yes; then
+          dnl Test whether copysignf() can be used without libm.
+          AC_CACHE_CHECK([whether copysignf can be used without linking with libm],
+            [gl_cv_func_copysignf_no_libm],
+            [
+              AC_TRY_LINK([#include <math.h>
+                           float x, y;],
+                          [return copysignf (x, y) < 0;],
+                [gl_cv_func_copysignf_no_libm=yes],
+                [gl_cv_func_copysignf_no_libm=no])
+            ])
+          if test $gl_cv_func_copysignf_no_libm = yes; then
+            AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], 1,
+              [Define if the copysignf function is declared in <math.h> and available in libc.])
+          fi
+        fi
+      fi
+      if test "$gl_cv_cc_double_signbit" = unknown; then
+        dnl Test whether copysign() is declared.
+        AC_CHECK_DECLS([copysign], , , [#include <math.h>])
+        if test "$ac_cv_have_decl_copysign" = yes; then
+          dnl Test whether copysign() can be used without libm.
+          AC_CACHE_CHECK([whether copysign can be used without linking with libm],
+            [gl_cv_func_copysign_no_libm],
+            [
+              AC_TRY_LINK([#include <math.h>
+                           double x, y;],
+                          [return copysign (x, y) < 0;],
+                [gl_cv_func_copysign_no_libm=yes],
+                [gl_cv_func_copysign_no_libm=no])
+            ])
+          if test $gl_cv_func_copysign_no_libm = yes; then
+            AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], 1,
+              [Define if the copysign function is declared in <math.h> and available in libc.])
+          fi
+        fi
+      fi
+      if test "$gl_cv_cc_long_double_signbit" = unknown; then
+        dnl Test whether copysignl() is declared.
+        AC_CHECK_DECLS([copysignl], , , [#include <math.h>])
+        if test "$ac_cv_have_decl_copysignl" = yes; then
+          dnl Test whether copysignl() can be used without libm.
+          AC_CACHE_CHECK([whether copysignl can be used without linking with libm],
+            [gl_cv_func_copysignl_no_libm],
+            [
+              AC_TRY_LINK([#include <math.h>
+                           long double x, y;],
+                          [return copysignl (x, y) < 0;],
+                [gl_cv_func_copysignl_no_libm=yes],
+                [gl_cv_func_copysignl_no_libm=no])
+            ])
+          if test $gl_cv_func_copysignl_no_libm = yes; then
+            AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], 1,
+              [Define if the copysignl function is declared in <math.h> and available in libc.])
+          fi
+        fi
+      fi
+    fi
+  fi
+])
+
+AC_DEFUN([gl_SIGNBIT_TEST_PROGRAM], [
 float p0f = 0.0f;
 float m0f = -0.0f;
 double p0d = 0.0;
@@ -54,78 +166,7 @@
       return 1;
   }
   return 0;
-}], [gl_cv_func_signbit=yes], [gl_cv_func_signbit=no],
-        [gl_cv_func_signbit="guessing no"])
-    ])
-  if test "$gl_cv_func_signbit" != yes; then
-    REPLACE_SIGNBIT=1
-    AC_LIBOBJ([signbitf])
-    AC_LIBOBJ([signbitd])
-    AC_LIBOBJ([signbitl])
-    gl_FLOAT_SIGN_LOCATION
-    gl_DOUBLE_SIGN_LOCATION
-    gl_LONG_DOUBLE_SIGN_LOCATION
-    if test "$gl_cv_cc_float_signbit" = unknown; then
-      dnl Test whether copysignf() is declared.
-      AC_CHECK_DECLS([copysignf], , , [#include <math.h>])
-      if test "$ac_cv_have_decl_copysignf" = yes; then
-        dnl Test whether copysignf() can be used without libm.
-        AC_CACHE_CHECK([whether copysignf can be used without linking with libm],
-          [gl_cv_func_copysignf_no_libm],
-          [
-            AC_TRY_LINK([#include <math.h>
-                         float x, y;],
-                        [return copysignf (x, y) < 0;],
-              [gl_cv_func_copysignf_no_libm=yes],
-              [gl_cv_func_copysignf_no_libm=no])
-          ])
-        if test $gl_cv_func_copysignf_no_libm = yes; then
-          AC_DEFINE([HAVE_COPYSIGNF_IN_LIBC], 1,
-            [Define if the copysignf function is declared in <math.h> and available in libc.])
-        fi
-      fi
-    fi
-    if test "$gl_cv_cc_double_signbit" = unknown; then
-      dnl Test whether copysign() is declared.
-      AC_CHECK_DECLS([copysign], , , [#include <math.h>])
-      if test "$ac_cv_have_decl_copysign" = yes; then
-        dnl Test whether copysign() can be used without libm.
-        AC_CACHE_CHECK([whether copysign can be used without linking with libm],
-          [gl_cv_func_copysign_no_libm],
-          [
-            AC_TRY_LINK([#include <math.h>
-                         double x, y;],
-                        [return copysign (x, y) < 0;],
-              [gl_cv_func_copysign_no_libm=yes],
-              [gl_cv_func_copysign_no_libm=no])
-          ])
-        if test $gl_cv_func_copysign_no_libm = yes; then
-          AC_DEFINE([HAVE_COPYSIGN_IN_LIBC], 1,
-            [Define if the copysign function is declared in <math.h> and available in libc.])
-        fi
-      fi
-    fi
-    if test "$gl_cv_cc_long_double_signbit" = unknown; then
-      dnl Test whether copysignl() is declared.
-      AC_CHECK_DECLS([copysignl], , , [#include <math.h>])
-      if test "$ac_cv_have_decl_copysignl" = yes; then
-        dnl Test whether copysignl() can be used without libm.
-        AC_CACHE_CHECK([whether copysignl can be used without linking with libm],
-          [gl_cv_func_copysignl_no_libm],
-          [
-            AC_TRY_LINK([#include <math.h>
-                         long double x, y;],
-                        [return copysignl (x, y) < 0;],
-              [gl_cv_func_copysignl_no_libm=yes],
-              [gl_cv_func_copysignl_no_libm=no])
-          ])
-        if test $gl_cv_func_copysignl_no_libm = yes; then
-          AC_DEFINE([HAVE_COPYSIGNL_IN_LIBC], 1,
-            [Define if the copysignl function is declared in <math.h> and available in libc.])
-        fi
-      fi
-    fi
-  fi
+}
 ])
 
 AC_DEFUN([gl_FLOAT_SIGN_LOCATION],
--- a/modules/math
+++ b/modules/math
@@ -64,6 +64,7 @@
 	      -e 's|@''REPLACE_ROUNDF''@|$(REPLACE_ROUNDF)|g' \
 	      -e 's|@''REPLACE_ROUNDL''@|$(REPLACE_ROUNDL)|g' \
 	      -e 's|@''REPLACE_SIGNBIT''@|$(REPLACE_SIGNBIT)|g' \
+	      -e 's|@''REPLACE_SIGNBIT_USING_GCC''@|$(REPLACE_SIGNBIT_USING_GCC)|g' \
 	      -e '/definition of GL_LINK_WARNING/r $(LINK_WARNING_H)' \
 	      < $(srcdir)/math.in.h; \
 	} > $@-t