Exploit the __builtin_signbit GCC built-in.
authorBruno Haible <bruno@clisp.org>
Sat, 26 Jan 2008 01:26:52 +0000 (02:26 +0100)
committerBruno Haible <bruno@clisp.org>
Sat, 26 Jan 2008 01:26:52 +0000 (02:26 +0100)
ChangeLog
lib/math.in.h
m4/math_h.m4
m4/signbit.m4
modules/math

index 91f57ae4ce08603210a2cf18b9f6aec0ed7d775b..9f7c35dd86d1db46e142db7714107156e1aab468 100644 (file)
--- 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.
index 140b96e2a67696272ced7df490c7eed5c19800f0..c3515d73493ec041320d0bb2d6c3b7663a3e3c9d 100644 (file)
@@ -353,6 +353,14 @@ extern int gl_isfinitel (long double x);
 
 
 #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);
index d5b203bd4d456169f3fba41a69e8ad1b620e7d3b..dd99e7f2d7dabb7edece4bef06c0034de9688e71 100644 (file)
@@ -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 @@ AC_DEFUN([gl_MATH_H_DEFAULTS],
   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])
 ])
index 689b929be106013e67a55456b7b7f89ba2f9e0c3..152a32e567d9ef3c23b3cf9c79790badff94df59 100644 (file)
@@ -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_DEFUN([gl_SIGNBIT],
     [
       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 @@ int main ()
       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],
index 971fb55facf9ef30e1579f842f072788dd919c69..9559865d72a723484b2ece83fb11515eaf230cc2 100644 (file)
@@ -64,6 +64,7 @@ math.h: math.in.h
              -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