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.
This commit is contained in:
H. Peter Anvin 2008-06-11 15:49:41 -07:00
parent 7b471fada8
commit ac8f8fcb27
7 changed files with 33 additions and 9 deletions

View file

@ -1,6 +1,5 @@
#include "compiler.h"
#include <inttypes.h>
#include <ctype.h>
#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;

2
nasm.c
View file

@ -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));

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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? */