From 9e5d31d2e79e6d6a002d8270ca92e99abc39ead4 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 9 Feb 2009 13:10:12 +0000 Subject: Hand-optimize wrappers on i386: -83 ec 10 sub $0x10,%esp -db 6c 24 14 fldt 0x14(%esp) -dd 5c 24 08 fstpl 0x8(%esp) -dd 44 24 08 fldl 0x8(%esp) -dd 1c 24 fstpl (%esp) -e8 fc ff ff ff call __GI_trunc -83 c4 10 add $0x10,%esp +db 6c 24 04 fldt 0x4(%esp) +dd 5c 24 04 fstpl 0x4(%esp) +e9 fc ff ff ff jmp __GI_trunc c3 ret text data bss dec hex filename - 42749 176 4 42929 a7b1 lib/libm-0.9.30-svn.so + 42085 176 4 42265 a519 lib/libm-0.9.30-svn.so --- libm/ldouble_wrappers.c | 260 +++++++++++++++++++----------------------------- 1 file changed, 104 insertions(+), 156 deletions(-) (limited to 'libm/ldouble_wrappers.c') diff --git a/libm/ldouble_wrappers.c b/libm/ldouble_wrappers.c index 688bff4bc..6e253fad1 100644 --- a/libm/ldouble_wrappers.c +++ b/libm/ldouble_wrappers.c @@ -16,6 +16,71 @@ #include "math.h" #include +#define STRINGIZE(s) #s + +#define WRAPPER1(func) \ +long double func##l(long double x) \ +{ \ + return (long double) func((double) x); \ +} + +#define int_WRAPPER1(func) \ +int func##l(long double x) \ +{ \ + return func((double) x); \ +} + +#if defined __i386__ && defined __OPTIMIZE__ +# undef WRAPPER1 +# undef int_WRAPPER1 +/* gcc 4.3.1 generates really ugly code with redundant pair of store/load: + * sub $0x10,%esp + * fldt 0x14(%esp) + * fstpl 0x8(%esp) + * fldl 0x8(%esp) <-- ?? + * fstpl (%esp) <-- ?? + * call function + * add $0x10,%esp + * ret + * I can hope newer gcc will eliminate that. However, I don't think + * it will be smart enough to reuse argument stack space and use + * jump instead of call. Let's do it by hand. + * The asm below loads long double x into st(0), then stores it back + * to the same location as a double. At this point, stack looks exactly + * as "double func(double)" expects it to be. + * The return value is returned in st(0) per ABI in both cases (returning + * a long double or returning a double). So we can simply jump to func. + * Using __GI_func in jump to make optimized intra-library jump. + * gcc will still generate a useless "ret" after asm. Oh well... + */ +# define WRAPPER1(func) \ +long double func##l(long double x) \ +{ \ + long double fp_top; \ + __asm ( \ + " fldt %1\n" \ + " fstpl %1\n" \ + " jmp " STRINGIZE(__GI_##func) "\n" \ + : "=t" (fp_top) \ + : "m" (x) \ + ); \ + return fp_top; \ +} +# define int_WRAPPER1(func) \ +int func##l(long double x) \ +{ \ + int ret; \ + __asm ( \ + " fldt %1\n" \ + " fstpl %1\n" \ + " jmp " STRINGIZE(__GI_##func) "\n" \ + : "=a" (ret) \ + : "m" (x) \ + ); \ + return ret; \ +} +#endif /* __i386__ */ + /* Implement the following, as defined by SuSv3 */ #if 0 @@ -79,31 +144,19 @@ long double truncl(long double); #endif #ifdef L_acoshl -long double acoshl (long double x) -{ - return (long double) acosh( (double)x ); -} +WRAPPER1(acosh) #endif #ifdef L_acosl -long double acosl (long double x) -{ - return (long double) acos( (double)x ); -} +WRAPPER1(acos) #endif #ifdef L_asinhl -long double asinhl (long double x) -{ - return (long double) asinh( (double)x ); -} +WRAPPER1(asinh) #endif #ifdef L_asinl -long double asinl (long double x) -{ - return (long double) asin( (double)x ); -} +WRAPPER1(asin) #endif #ifdef L_atan2l @@ -114,17 +167,11 @@ long double atan2l (long double x, long double y) #endif #ifdef L_atanhl -long double atanhl (long double x) -{ - return (long double) atanh( (double)x ); -} +WRAPPER1(atanh) #endif #ifdef L_atanl -long double atanl (long double x) -{ - return (long double) atan( (double)x ); -} +WRAPPER1(atan) #endif #ifdef L_cargl @@ -135,17 +182,11 @@ long double cargl (long double complex x) #endif #ifdef L_cbrtl -long double cbrtl (long double x) -{ - return (long double) cbrt( (double)x ); -} +WRAPPER1(cbrt) #endif #ifdef L_ceill -long double ceill (long double x) -{ - return (long double) ceil( (double)x ); -} +WRAPPER1(ceil) #endif #ifdef L_copysignl @@ -156,59 +197,35 @@ long double copysignl (long double x, long double y) #endif #ifdef L_coshl -long double coshl (long double x) -{ - return (long double) cosh( (double)x ); -} +WRAPPER1(cosh) #endif #ifdef L_cosl -long double cosl (long double x) -{ - return (long double) cos( (double)x ); -} +WRAPPER1(cos) #endif #ifdef L_erfcl -long double erfcl (long double x) -{ - return (long double) erfc( (double)x ); -} +WRAPPER1(erfc) #endif #ifdef L_erfl -long double erfl (long double x) -{ - return (long double) erf( (double)x ); -} +WRAPPER1(erf) #endif #ifdef L_exp2l -long double exp2l (long double x) -{ - return (long double) exp2( (double)x ); -} +WRAPPER1(exp2) #endif #ifdef L_expl -long double expl (long double x) -{ - return (long double) exp( (double)x ); -} +WRAPPER1(exp) #endif #ifdef L_expm1l -long double expm1l (long double x) -{ - return (long double) expm1( (double)x ); -} +WRAPPER1(expm1) #endif #ifdef L_fabsl -long double fabsl (long double x) -{ - return (long double) fabs( (double)x ); -} +WRAPPER1(fabs) #endif #ifdef L_fdiml @@ -219,10 +236,7 @@ long double fdiml (long double x, long double y) #endif #ifdef L_floorl -long double floorl (long double x) -{ - return (long double) floor( (double)x ); -} +WRAPPER1(floor) #endif #ifdef L_fmal @@ -268,10 +282,7 @@ long double hypotl (long double x, long double y) #endif #ifdef L_ilogbl -int ilogbl (long double x) -{ - return (long double) ilogb( (double)x ); -} +int_WRAPPER1(ilogb) #endif #ifdef L_ldexpl @@ -282,10 +293,7 @@ long double ldexpl (long double x, int exp) #endif #ifdef L_lgammal -long double lgammal (long double x) -{ - return (long double) lgamma( (double)x ); -} +WRAPPER1(lgamma) #endif #ifdef L_llrintl @@ -303,38 +311,23 @@ long long llroundl (long double x) #endif #ifdef L_log10l -long double log10l (long double x) -{ - return (long double) log10( (double)x ); -} +WRAPPER1(log10) #endif #ifdef L_log1pl -long double log1pl (long double x) -{ - return (long double) log1p( (double)x ); -} +WRAPPER1(log1p) #endif #ifdef L_log2l -long double log2l (long double x) -{ - return (long double) log2( (double)x ); -} +WRAPPER1(log2) #endif #ifdef L_logbl -long double logbl (long double x) -{ - return (long double) logb( (double)x ); -} +WRAPPER1(logb) #endif #ifdef L_logl -long double logl (long double x) -{ - return (long double) log( (double)x ); -} +WRAPPER1(log) #endif #ifdef L_lrintl @@ -362,10 +355,7 @@ long double modfl (long double x, long double *iptr) #endif #ifdef L_nearbyintl -long double nearbyintl (long double x) -{ - return (long double) nearbyint( (double)x ); -} +WRAPPER1(nearbyint) #endif #ifdef L_nextafterl @@ -404,17 +394,11 @@ long double remquol (long double x, long double y, int *quo) #endif #ifdef L_rintl -long double rintl (long double x) -{ - return (long double) rint( (double)x ); -} +WRAPPER1(rint) #endif #ifdef L_roundl -long double roundl (long double x) -{ - return (long double) round( (double)x ); -} +WRAPPER1(round) #endif #ifdef L_scalblnl @@ -432,90 +416,54 @@ long double scalbnl (long double x, int exp) #endif #ifdef L_sinhl -long double sinhl (long double x) -{ - return (long double) sinh( (double)x ); -} +WRAPPER1(sinh) #endif #ifdef L_sinl -long double sinl (long double x) -{ - return (long double) sin( (double)x ); -} +WRAPPER1(sin) #endif #ifdef L_sqrtl -long double sqrtl (long double x) -{ - return (long double) sqrt( (double)x ); -} +WRAPPER1(sqrt) #endif #ifdef L_tanhl -long double tanhl (long double x) -{ - return (long double) tanh( (double)x ); -} +WRAPPER1(tanh) #endif #ifdef L_tanl -long double tanl (long double x) -{ - return (long double) tan( (double)x ); -} +WRAPPER1(tan) #endif #ifdef L_tgammal -long double tgammal (long double x) -{ - return (long double) tgamma( (double)x ); -} +WRAPPER1(tgamma) #endif #ifdef L_truncl -long double truncl (long double x) -{ - return (long double) trunc( (double)x ); -} +WRAPPER1(trunc) #endif #ifdef __DO_C99_MATH__ #ifdef L_fpclassifyl -int __fpclassifyl (long double x) -{ - return __fpclassify ( (double) x ); -} +int_WRAPPER1(__fpclassify); #endif #ifdef L_finitel -int __finitel (long double x) -{ - return __finite ( (double)x ); -} +int_WRAPPER1(__finite) #endif #ifdef L___signbitl -int __signbitl (long double x) -{ - return __signbit ( (double)x ); -} +int_WRAPPER1(__signbit) #endif #ifdef L_isnanl -int __isnanl (long double x) -{ - return __isnan ( (double)x ); -} +int_WRAPPER1(__isnan) libm_hidden_def(__isnanl) #endif #ifdef L_isinfl -int __isinfl (long double x) -{ - return __isinf ( (double)x ); -} +int_WRAPPER1(__isinf) libm_hidden_def(__isinfl) #endif -- cgit v1.2.3