[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patches] [PATCH] Make libm smaller using wrappers



Joseph S. Myers wrote:
On Mon, 12 Oct 2009, Maxim Kuvyrkov wrote:

Joseph, thank you for reviewing this!

The following patch substitutes several double-precision libm functions with
single-precision counterparts.  This transformation certainly degrades the
precision of computations, but also reduces the size of the libm library by
more than 50% on some architectures.

Although you and the documentation in option-groups.def say this, dbl-wrap.h would appear in fact to be using the long double versions where available.

I meant to not use long double versions in wrappers for double-precision function. After tests on powerpc and i686 it became clear that long double functions take as much space, if not more, as double functions. So I added a similar support for long double functions. See the attached patch.


So far this work was tested on mips-linux-gnu with no changes when the feature
is disabled.  When wrappers are used, several math tests expectedly fail.

I will also run tests on powerpc-linux-gnuspe configuration and will follow up
in a couple of days.

It seems a good idea to test all the different long double configurations. mips-linux-gnu (o32) is one where long double is the same as double. powerpc-linux-gnuspe is one with IBM long double. You also have IEEE extended long double (e.g. x86 or x86_64) and IEEE quad long double (e.g. MIPS64 (n32 or n64)) to cover. Testing should make sure that the same set of symbols at the same versions is still exported from libm (before the patch, after the patch with the default configuration and after the patch with the new option group in use), as well as that there aren't problems with the fallback float or long double functions trying to call back to the double versions at any point.

OK, I've already done some of the testing above and everything looks good so far. I'll follow up once all configurations are covered. BTW, I noted that atest-* do not fail on at least x86, so I will take another look why they fail on MIPS and PPC. I also reconsidered adding new tests as opposed to just fixing the existing ones to handle wrappers, this is why the attached patch doesn't add ldbl-wrap-test.c. We may still want to keep the dbl-wrap-test.c though.


diff --git a/configure.in b/configure.in
index af49d81..eed31a9 100644
--- a/configure.in
+++ b/configure.in
@@ -740,6 +740,10 @@ if test "$elf" = yes; then
   sysnames="`echo $elf_dirs | sed -e 's,//,/,g'` $sysnames"
 fi
+# Peek into option-groups.config to check if sysdeps/ieee754/dbl-wrap needs
+# to be included into $sysnames.
+grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config
+use_dbl_wrap=$?

This looks like it will cause an unwanted line of output on configure's stdout, as well as an error message from grep on configure's stderr if there is no option-groups.config file. The result may still be correct - but the error message should be avoided.

Fixed.

--
Maxim
 configure                               |   21 ++++++++++++++-------
 configure.in                            |   21 ++++++++++++++-------
 math/Makefile                           |    3 +--
 option-groups.def                       |    2 +-
 sysdeps/ieee754/dbl-wrap/dbl-wrap.h     |    7 +------
 sysdeps/ieee754/ldbl-wrap/e_acosl.c     |    9 +++++++++
 sysdeps/ieee754/ldbl-wrap/e_asinl.c     |    9 +++++++++
 sysdeps/ieee754/ldbl-wrap/e_expl.c      |    9 +++++++++
 sysdeps/ieee754/ldbl-wrap/e_j0l.c       |   17 +++++++++++++++++
 sysdeps/ieee754/ldbl-wrap/e_j1l.c       |   17 +++++++++++++++++
 sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c |    9 +++++++++
 sysdeps/ieee754/ldbl-wrap/e_powl.c      |   10 ++++++++++
 sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h   |    3 +++
 sysdeps/ieee754/ldbl-wrap/s_erfl.c      |   19 +++++++++++++++++++
 sysdeps/ieee754/ldbl-wrap/s_log1pl.c    |   11 +++++++++++
 15 files changed, 144 insertions(+), 23 deletions(-)

diff --git a/configure b/configure
index 13f8103..adc318b 100755
--- a/configure
+++ b/configure
@@ -4441,9 +4441,9 @@ if test "$elf" = yes; then
   sysnames="`echo $elf_dirs | sed -e 's,//,/,g'` $sysnames"
 fi
 
-# Peek into option-groups.config to check if sysdeps/ieee754/dbl-wrap needs
+# Peek into option-groups.config to check if sysdeps/ieee754/[l]dbl-wrap needs
 # to be included into $sysnames.
-grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config
+grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config > /dev/null 2>&1
 use_dbl_wrap=$?
 
 # Expand the list of system names into a full list of directories
@@ -4480,8 +4480,11 @@ while test $# -gt 0; do
       if test -d $xsrcdir$name_base/$x; then
 	# If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
 	# ieee754/dbl-64.
-	if test "$use_dbl_wrap" = "0" -a "$x" = "ieee754/dbl-64"; then
-	  implied="$implied $name_base/ieee754/dbl-wrap";
+	if test "$use_dbl_wrap" = "0"; then
+	  case $x in
+	    ieee754/dbl-64) implied="$implied $name_base/ieee754/dbl-wrap" ;;
+	    ieee754/ldbl-*) implied="$implied $name_base/ieee754/ldbl-wrap" ;;
+	  esac
 	fi
 	implied="$implied $name_base/$x";
 	found=yes
@@ -4498,9 +4501,13 @@ while test $# -gt 0; do
 	then
 	  # If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
 	  # ieee754/dbl-64.
-	  if test "$use_dbl_wrap" = "0" -a "$try" = "sysdeps/ieee754/dbl-64";
-	  then
-	    implied="$implied sysdeps/ieee754/dbl-wrap";
+	  if test "$use_dbl_wrap" = "0"; then
+	    case $try in
+	    sysdeps/ieee754/dbl-64)
+	      implied="$implied sysdeps/ieee754/dbl-wrap" ;;
+	    sysdeps/ieee754/ldbl-*)
+	      implied="$implied sysdeps/ieee754/ldbl-wrap" ;;
+	    esac
 	  fi
 	  implied="$implied $try"
 	  found=yes
diff --git a/configure.in b/configure.in
index eed31a9..525564c 100644
--- a/configure.in
+++ b/configure.in
@@ -740,9 +740,9 @@ if test "$elf" = yes; then
   sysnames="`echo $elf_dirs | sed -e 's,//,/,g'` $sysnames"
 fi
 
-# Peek into option-groups.config to check if sysdeps/ieee754/dbl-wrap needs
+# Peek into option-groups.config to check if sysdeps/ieee754/[l]dbl-wrap needs
 # to be included into $sysnames.
-grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config
+grep "OPTION_EGLIBC_LIBM_BIG = n" option-groups.config > /dev/null 2>&1
 use_dbl_wrap=$?
 
 # Expand the list of system names into a full list of directories
@@ -779,8 +779,11 @@ while test $# -gt 0; do
       if test -d $xsrcdir$name_base/$x; then
 	# If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
 	# ieee754/dbl-64.
-	if test "$use_dbl_wrap" = "0" -a "$x" = "ieee754/dbl-64"; then
-	  implied="$implied $name_base/ieee754/dbl-wrap";
+	if test "$use_dbl_wrap" = "0"; then
+	  case $x in
+	    ieee754/dbl-64) implied="$implied $name_base/ieee754/dbl-wrap" ;;
+	    ieee754/ldbl-*) implied="$implied $name_base/ieee754/ldbl-wrap" ;;
+	  esac
 	fi
 	implied="$implied $name_base/$x";
 	found=yes
@@ -797,9 +800,13 @@ while test $# -gt 0; do
 	then
 	  # If !OPTION_EGLIBC_LIBM_BIG, add ieee754/dbl-wrap just before
 	  # ieee754/dbl-64.
-	  if test "$use_dbl_wrap" = "0" -a "$try" = "sysdeps/ieee754/dbl-64";
-	  then
-	    implied="$implied sysdeps/ieee754/dbl-wrap";
+	  if test "$use_dbl_wrap" = "0"; then
+	    case $try in
+	    sysdeps/ieee754/dbl-64)
+	      implied="$implied sysdeps/ieee754/dbl-wrap" ;;
+	    sysdeps/ieee754/ldbl-*)
+	      implied="$implied sysdeps/ieee754/ldbl-wrap" ;;
+	    esac
 	  fi
 	  implied="$implied $try"
 	  found=yes
diff --git a/math/Makefile b/math/Makefile
index 7d01be1..f4d743b 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -90,11 +90,10 @@ long-c-yes = $(calls:=l)
 distribute += $(filter-out $(generated),$(long-m-yes:=.c) $(long-c-yes:=.c))
 
 # Rules for the test suite.
-tests = test-matherr test-fenv basic-test \
+tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
 	test-misc test-fpucw tst-definitions test-tgmath test-tgmath-ret \
 	bug-nextafter bug-nexttoward bug-tgmath1 test-tgmath-int test-tgmath2 \
 	test-dbl-wrap
-tests-$(OPTION_EGLIBC_LIBM_BIG) += atest-exp atest-sincos atest-exp2
 # We do the `long double' tests only if this data type is available and
 # distinct from `double'.
 test-longdouble-yes = test-ldouble test-ildoubl
diff --git a/option-groups.def b/option-groups.def
index 240cf52..940b625 100644
--- a/option-groups.def
+++ b/option-groups.def
@@ -438,7 +438,7 @@ config OPTION_EGLIBC_LIBM_BIG
    bool "Math library size"
    help
        This option group enables default configuration of the math library.
-       Not selecting this option group removes most of extended and 
+       Not selecting this option group removes most of the extended and
        double precision math functions and replaces them with wrappers
        to the single precision couterparts.
        Doing so greatly degrades quality of calculations carried
diff --git a/sysdeps/ieee754/dbl-wrap/dbl-wrap.h b/sysdeps/ieee754/dbl-wrap/dbl-wrap.h
index 81c0faa..b381828 100644
--- a/sysdeps/ieee754/dbl-wrap/dbl-wrap.h
+++ b/sysdeps/ieee754/dbl-wrap/dbl-wrap.h
@@ -1,7 +1,2 @@
-#ifdef NO_LONG_DOUBLE
 typedef float wrap_type_t;
-# define WRAP_FUNC(func) func ## f
-#else
-typedef long double wrap_type_t;
-# define WRAP_FUNC(func) func ## l
-#endif
+#define WRAP_FUNC(func) func ## f
diff --git a/sysdeps/ieee754/ldbl-wrap/e_acosl.c b/sysdeps/ieee754/ldbl-wrap/e_acosl.c
new file mode 100644
index 0000000..ab0c879
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_acosl.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_acos) (wrap_type_t);
+
+long double
+__ieee754_acosl (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_acos) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_asinl.c b/sysdeps/ieee754/ldbl-wrap/e_asinl.c
new file mode 100644
index 0000000..71ee4f9
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_asinl.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_asin) (wrap_type_t);
+
+long double
+__ieee754_asinl (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_asin) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_expl.c b/sysdeps/ieee754/ldbl-wrap/e_expl.c
new file mode 100644
index 0000000..75a5343
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_expl.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_exp) (wrap_type_t);
+
+long double
+__ieee754_expl (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_exp) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_j0l.c b/sysdeps/ieee754/ldbl-wrap/e_j0l.c
new file mode 100644
index 0000000..a213d70
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_j0l.c
@@ -0,0 +1,17 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_j0) (wrap_type_t);
+
+long double
+__ieee754_j0l (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_j0) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__ieee754_y0) (wrap_type_t);
+
+long double
+__ieee754_y0l (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_y0) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_j1l.c b/sysdeps/ieee754/ldbl-wrap/e_j1l.c
new file mode 100644
index 0000000..b2c7de1
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_j1l.c
@@ -0,0 +1,17 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_j1) (wrap_type_t);
+
+long double
+__ieee754_j1l (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_j1) ((wrap_type_t) x);
+}
+
+wrap_type_t WRAP_FUNC (__ieee754_y1) (wrap_type_t);
+
+long double
+__ieee754_y1l (long double x)
+{
+  return (long double) WRAP_FUNC (__ieee754_y1) ((wrap_type_t) x);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c b/sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c
new file mode 100644
index 0000000..80d6153
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_lgammal_r.c
@@ -0,0 +1,9 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC2 (__ieee754_lgamma, _r) (wrap_type_t, int *);
+
+long double
+__ieee754_lgammal_r (long double x, int *s)
+{
+  return (long double) WRAP_FUNC2 (__ieee754_lgamma, _r) ((wrap_type_t) x, s);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/e_powl.c b/sysdeps/ieee754/ldbl-wrap/e_powl.c
new file mode 100644
index 0000000..ef779ce
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/e_powl.c
@@ -0,0 +1,10 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__ieee754_pow) (wrap_type_t, wrap_type_t);
+
+long double
+__ieee754_powl (long double x, long double y)
+{
+  return (long double) WRAP_FUNC (__ieee754_pow) ((wrap_type_t) x,
+						  (wrap_type_t) y);
+}
diff --git a/sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h b/sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h
new file mode 100644
index 0000000..36aeffe
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/ldbl-wrap.h
@@ -0,0 +1,3 @@
+typedef float wrap_type_t;
+#define WRAP_FUNC(func) func ## f
+#define WRAP_FUNC2(func, suffix) func ## f ## suffix
diff --git a/sysdeps/ieee754/ldbl-wrap/s_erfl.c b/sysdeps/ieee754/ldbl-wrap/s_erfl.c
new file mode 100644
index 0000000..03d9dc6
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/s_erfl.c
@@ -0,0 +1,19 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__erf) (wrap_type_t);
+
+long double
+__erfl (long double x)
+{
+  return (long double) WRAP_FUNC (__erf) ((wrap_type_t) x);
+}
+weak_alias (__erfl, erfl)
+
+wrap_type_t WRAP_FUNC (__erfc) (wrap_type_t);
+
+long double
+__erfcl (long double x)
+{
+  return (long double) WRAP_FUNC (__erfc) ((wrap_type_t) x);
+}
+weak_alias (__erfcl, erfcl)
diff --git a/sysdeps/ieee754/ldbl-wrap/s_log1pl.c b/sysdeps/ieee754/ldbl-wrap/s_log1pl.c
new file mode 100644
index 0000000..9fcf640
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-wrap/s_log1pl.c
@@ -0,0 +1,11 @@
+#include "ldbl-wrap.h"
+
+wrap_type_t WRAP_FUNC (__log1p) (wrap_type_t);
+
+long double
+__log1pl (long double x)
+{
+  return (long double) WRAP_FUNC (__log1p) ((wrap_type_t) x);
+}
+
+weak_alias (__log1pl, log1pl)