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:
parent
7b471fada8
commit
ac8f8fcb27
7 changed files with 33 additions and 9 deletions
6
crc64.c
6
crc64.c
|
@ -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
2
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));
|
||||
|
|
19
nasmlib.c
19
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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? */
|
||||
|
|
Loading…
Reference in a new issue