From ac8f8fcb27a063fbf7ec3ad3de18f6586e9e95b8 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Wed, 11 Jun 2008 15:49:41 -0700 Subject: [PATCH] Use an explicit table for tolower() to avoid a function call On some platforms, tolower() is implemented as a function call, in order to handle locale support. We never change locales, so can the result of tolower() into a table, so we don't have to sit through the function call every time. ~1.3% overall performance improvement on a macro-heavy benchmark under Linux x86-64. --- crc64.c | 6 ++---- nasm.c | 2 ++ nasmlib.c | 19 +++++++++++++++++-- nasmlib.h | 8 ++++++++ ndisasm.c | 3 ++- preproc.c | 2 +- stdscan.c | 2 +- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/crc64.c b/crc64.c index fc165b78..e8639c86 100644 --- a/crc64.c +++ b/crc64.c @@ -1,6 +1,5 @@ #include "compiler.h" -#include -#include +#include "nasmlib.h" static const uint64_t crc64_tab[256] = { UINT64_C(0x0000000000000000), UINT64_C(0x7ad870c830358979), @@ -149,8 +148,7 @@ uint64_t crc64i(uint64_t crc, const char *str) uint8_t c; while ((c = *str++) != 0) { - c = tolower(c); - crc = crc64_tab[(uint8_t)crc ^ c] ^ (crc >> 8); + crc = crc64_tab[(uint8_t)crc ^ nasm_tolower(c)] ^ (crc >> 8); } return crc; diff --git a/nasm.c b/nasm.c index a8efbb2b..416cee84 100644 --- a/nasm.c +++ b/nasm.c @@ -298,6 +298,8 @@ int main(int argc, char **argv) error_file = stderr; + tolower_init(); + nasm_set_malloc_error(report_error); offsets = raa_init(); forwrefs = saa_init((int32_t)sizeof(struct forwrefinfo)); diff --git a/nasmlib.c b/nasmlib.c index db4b2f17..9a49090e 100644 --- a/nasmlib.c +++ b/nasmlib.c @@ -25,6 +25,21 @@ efunc nasm_malloc_error; /* Exported for the benefit of vsnprintf.c */ static FILE *logfp; #endif +/* + * Prepare a table of tolower() results. This avoids function calls + * on some platforms. + */ + +unsigned char nasm_tolower_tab[256]; + +void tolower_init(void) +{ + int i; + + for (i = 0; i < 256; i++) + nasm_tolower_tab[i] = tolower(i); +} + void nasm_set_malloc_error(efunc error) { nasm_malloc_error = error; @@ -192,8 +207,8 @@ int nasm_memicmp(const char *s1, const char *s2, size_t n) int d; while (n--) { - c1 = tolower(*s1++); - c2 = tolower(*s2++); + c1 = nasm_tolower(*s1++); + c2 = nasm_tolower(*s2++); d = c1-c2; if (d) return d; diff --git a/nasmlib.h b/nasmlib.h index 837d679c..7391564c 100644 --- a/nasmlib.h +++ b/nasmlib.h @@ -175,6 +175,14 @@ void standard_extension(char *inname, char *outname, char *extension, #define elements(x) ( sizeof(x) / sizeof(*(x)) ) +/* + * tolower table -- avoids a function call on some platforms. + * NOTE: unlike the tolower() function in ctype, EOF is *NOT* + * a permitted value, for obvious reasons. + */ +void tolower_init(void); +extern unsigned char nasm_tolower_tab[256]; +#define nasm_tolower(x) nasm_tolower_tab[(unsigned char)(x)] /* * some handy macros that will probably be of use in more than one diff --git a/ndisasm.c b/ndisasm.c index 8f912f83..b5001bde 100644 --- a/ndisasm.c +++ b/ndisasm.c @@ -67,6 +67,7 @@ int main(int argc, char **argv) int32_t offset; FILE *fp; + tolower_init(); nasm_set_malloc_error(ndisasm_error); offset = 0; @@ -77,7 +78,7 @@ int main(int argc, char **argv) if (*p == '-' && p[1]) { p++; while (*p) - switch (tolower(*p)) { + switch (nasm_tolower(*p)) { case 'a': /* auto or intelligent sync */ case 'i': autosync = true; diff --git a/preproc.c b/preproc.c index 5bdd32cb..8859005b 100644 --- a/preproc.c +++ b/preproc.c @@ -1123,7 +1123,7 @@ static int ppscan(void *private_data, struct tokenval *tokval) for (r = p, s = ourcopy; *r; r++) { if (r >= p+MAX_KEYWORD) return tokval->t_type = TOKEN_ID; /* Not a keyword */ - *s++ = tolower(*r); + *s++ = nasm_tolower(*r); } *s = '\0'; /* right, so we have an identifier sitting in temp storage. now, diff --git a/stdscan.c b/stdscan.c index f0d165f8..60982a48 100644 --- a/stdscan.c +++ b/stdscan.c @@ -97,7 +97,7 @@ int stdscan(void *private_data, struct tokenval *tv) return tv->t_type = TOKEN_ID; /* bypass all other checks */ for (s = tv->t_charptr, r = ourcopy; *s; s++) - *r++ = tolower(*s); + *r++ = nasm_tolower(*s); *r = '\0'; /* right, so we have an identifier sitting in temp storage. now, * is it actually a register or instruction name, or what? */ -- 2.11.4.GIT