[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [patches] [PATCH] Make libm smaller using wrappers
- To: "Joseph S. Myers" <joseph@xxxxxxxxxxxxxxxx>
- Subject: Re: [patches] [PATCH] Make libm smaller using wrappers
- From: Maxim Kuvyrkov <maxim@xxxxxxxxxxxxxxxx>
- Date: Mon, 16 Nov 2009 14:26:45 +0300
Joseph S. Myers wrote:
On Wed, 28 Oct 2009, Maxim Kuvyrkov wrote:
@@ -645,19 +652,19 @@ sub get_ulps {
# Return 0 instead of BUILD_COMPLEX (0,0)
if (!exists $results{$test}{'real'}{'ulp'}{$float} &&
!exists $results{$test}{'imag'}{'ulp'}{$float}) {
- return "0";
+ return "BUILD_COMPLEX ($default_ulp, $default_ulp)";
Note the comment saying it is deliberately doing something that it is no
longer doing after your patch. How is the result used, and why is this
change OK? Certainly the comment will need removing or changing if the
output change stays.
This clause outputs default error with which results of complex
functions are compared against expected [complex] values. If I
understand GNU C __complex__ correctly, there's no difference between
'0' and '0 + 0i'; if so, then using "0" instead of "BUILD_COMPLEX (0,0)"
in the above clause is just an optimization. The result of the above
clause is passed to a function that expects '__complex__ <float type>'
parameter, so the optimization appears to be quite minor in practice.
All new tests should be using the test-skeleton infrastructure if
possible.
Noted. I'll update the testcase.
Otherwise the patch seems OK, though it would be good to have specific
guidance somewhere (a mailing list message would be OK) on how to
determine what changes are needed to keep this option group working
correctly if a new libm function is added.
That's good suggestion! See below.
Do I understand correctly that
no change is strictly needed for any given function - but if no change is
made all three versions of the new function will be present whatever the
setting for this option group?
Yes, that's correct given that implementation of the new function does
not directly include any of the .c files. Implementations of the new
functions have little value in including other .c files, so special care
is need only when dealing with compatibility code like in ldbl-opt/.
If the implementation does include .c files, then it will need changes
to include the correct file which depends on the option group selection.
Generally, something like this
<cut>
--- a/sysdeps/ieee754/ldbl-opt/s_atan.c
+++ b/sysdeps/ieee754/ldbl-opt/s_atan.c
@@ -1,5 +1,10 @@
#include <math_ldbl_opt.h>
-#include <sysdeps/ieee754/dbl-64/s_atan.c>
+#include <gnu/option-groups.h>
+#if __OPTION_EGLIBC_LIBM_BIG
+# include <sysdeps/ieee754/dbl-64/s_atan.c>
+#else
+# include <sysdeps/ieee754/dbl-wrap/s_atan.c>
+#endif
#if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0)
compat_symbol (libm, atan, atanl, GLIBC_2_0);
#endif
</cut>
will be enough.
If so, the documentation would be saying
how to make the option group effective for a new function that is making a
significant contribution to libm size. (It might of course also be useful
for any new functions to get an associated option group to disable a
family of functions.)
The process of adding handling of a new function to wrappers has the
following steps:
0. We have a new function 'ret_type __fnl (arg_type arg)' with
implemention in, say, ldbl-xxx/fnl.c. This function has an alias 'long
double fnl (long double arg)'.
1. Create file ldbl-wrap/fnl-wrap.c following the template:
<cut>
#include "ldbl-wrap.h"
/* This expands into 'float __fnf (float)'. */
wrap_type_t WRAP_FUNC (__fn) (wrap_type_t);
long double
__fnl (long double x)
{
/* This expands into
return (long double) __fnf ((float) x); */
return (long double) WRAP_FUNC (__fn) ((wrap_type_t) x);
}
</cut>
2. Use "#if __OPTION_EGLIBC_LIBM_BIG" to disable original code in
ldbl-xxx/fnl.c.
+#include <gnu/option-groups.h>
+
+#if __OPTION_EGLIBC_LIBM_BIG
/* Big chunk of code */
+#else /* !__OPTION_EGLIBC_LIBM_BIG */
3. In the #else branch include ldbl-wrap/fnl-wrap.c.
+# include <sysdeps/ieee754/ldbl-wrap/fnl-wrap.c>
4. With the big chunk of code you've probably also disabled creation of
alias from __fnl() to fnl(); add a copy of alias after the #include.
Don't forget to close the #if statement.
+weak_alias (__erfl, erfl)
+#endif /* __OPTION_EGLIBC_LIBM_BIG */
The work I've done follows the above recipe for ldbl-* functions. The
wrappers for dbl-64/ can be optimized a bit due to the fact that there's
only one dbl implementation, so alias handling does not require special
attention. One can use dbl-wrap/fn.c instead of dbl-wrap/fn-wrap.c and
have the alias directives right there.
--
Maxim Kuvyrkov
CodeSourcery
maxim@xxxxxxxxxxxxxxxx
(650) 331-3385 x724