From af15df12ee43a459fabd607148124d64db26407a Mon Sep 17 00:00:00 2001 From: Ulrich Drepper Date: Thu, 25 Mar 2004 22:58:59 +0000 Subject: (__strtol_ul_max_tab, __strtol_ull_max_tab, __strtol_ull_rem_tab, __strtol_ul_rem_tab, cutoff_tab, cutlim_tab, jmax_tab): New. (__strtol_l): Use them to avoid runtime division. --- sysdeps/generic/strtol_l.c | 50 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'sysdeps/generic/strtol_l.c') diff --git a/sysdeps/generic/strtol_l.c b/sysdeps/generic/strtol_l.c index a3800d6f78..50b7861bd0 100644 --- a/sysdeps/generic/strtol_l.c +++ b/sysdeps/generic/strtol_l.c @@ -44,6 +44,7 @@ #include #include #include +#include #ifdef USE_NUMBER_GROUPING # include "../locale/localeinfo.h" @@ -164,6 +165,48 @@ #endif +/* Define tables of maximum values and remainders in order to detect + overflow. Do this at compile-time in order to avoid the runtime + overhead of the division. */ + +#define DEF(TYPE, NAME) \ + const TYPE NAME[] attribute_hidden \ + __attribute__((section(".gnu.linkonce.ro." #NAME))) = \ + { \ + F(2), F(3), F(4), F(5), F(6), F(7), F(8), F(9), F(10), \ + F(11), F(12), F(13), F(14), F(15), F(16), F(17), F(18), F(19), F(20), \ + F(21), F(22), F(23), F(24), F(25), F(26), F(27), F(28), F(29), F(30), \ + F(31), F(32), F(33), F(34), F(35), F(36) \ + } + +#define F(X) ULONG_MAX / X + DEF (unsigned long, __strtol_ul_max_tab); +#undef F +#if defined(QUAD) && __WORDSIZE == 32 +# define F(X) ULONG_LONG_MAX / X + DEF (unsigned long long, __strtol_ull_max_tab); +# undef F +# define F(X) ULONG_LONG_MAX % X + DEF (unsigned char, __strtol_ull_rem_tab); +# undef F +#else +# define F(X) ULONG_MAX % X + DEF (unsigned char, __strtol_ul_rem_tab); +# undef F +#endif +#undef DEF + +/* Define some more readable aliases for these arrays which correspond + to how they'll be used in the function below. */ +#define jmax_tab __strtol_ul_max_tab +#if defined(QUAD) && __WORDSIZE == 32 +# define cutoff_tab __strtol_ull_max_tab +# define cutlim_tab __strtol_ull_rem_tab +#else +# define cutoff_tab __strtol_ul_max_tab +# define cutlim_tab __strtol_ul_rem_tab +#endif + /* Convert NPTR to an `unsigned long int' or `long int' in base BASE. If BASE is 0 the base is determined by the presence of a leading @@ -325,8 +368,9 @@ INTERNAL (__strtol_l) (nptr, endptr, base, group, loc) #endif end = NULL; - cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base; - cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base; + /* Avoid runtime division; lookup cutoff and limit. */ + cutoff = cutoff_tab[base - 2]; + cutlim = cutlim_tab[base - 2]; overflow = 0; i = 0; @@ -334,7 +378,7 @@ INTERNAL (__strtol_l) (nptr, endptr, base, group, loc) if (sizeof (long int) != sizeof (LONG int)) { unsigned long int j = 0; - unsigned long int jmax = ULONG_MAX / base; + unsigned long int jmax = jmax_tab[base - 2]; for (;c != L_('\0'); c = *++s) { -- cgit 1.4.1