From ce8675631414567e50a77fdd43196f5882172ca7 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sat, 26 Jan 2008 02:26:52 +0100 Subject: [PATCH] Exploit the __builtin_signbit GCC built-in. --- ChangeLog | 12 ++++ lib/math.in.h | 8 +++ m4/math_h.m4 | 57 +++++++++--------- m4/signbit.m4 | 189 +++++++++++++++++++++++++++++++++++----------------------- modules/math | 1 + 5 files changed, 165 insertions(+), 102 deletions(-) diff --git a/ChangeLog b/ChangeLog index 91f57ae4c..9f7c35dd8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-01-25 Paul Eggert + Bruno Haible + + * 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 Prefer over "config.h". See autoconf doc for explanation. diff --git a/lib/math.in.h b/lib/math.in.h index 140b96e2a..c3515d734 100644 --- a/lib/math.in.h +++ b/lib/math.in.h @@ -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); diff --git a/m4/math_h.m4 b/m4/math_h.m4 index d5b203bd4..dd99e7f2d 100644 --- 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 @@ 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]) ]) diff --git a/m4/signbit.m4 b/m4/signbit.m4 index 689b929be..152a32e56 100644 --- 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_DEFUN([gl_SIGNBIT], [ AC_TRY_RUN([ #include +/* 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 +]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 . + 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 +]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 ]) + 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 + 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 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 ]) + 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 + 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 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 ]) + 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 + 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 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 ]) - 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 - 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 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 ]) - 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 - 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 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 ]) - 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 - 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 and available in libc.]) - fi - fi - fi - fi +} ]) AC_DEFUN([gl_FLOAT_SIGN_LOCATION], diff --git a/modules/math b/modules/math index 971fb55fa..9559865d7 100644 --- a/modules/math +++ b/modules/math @@ -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 -- 2.11.0