From fe2174256bbe7e54a6a9b9d2c8c2142c78a535ff Mon Sep 17 00:00:00 2001 From: jason Date: Wed, 7 May 2003 18:06:23 +0000 Subject: [PATCH] libiberty/ * hashtab.c (burtle_hash): New fn. * configure.in: Add AC_C_BIGENDIAN_CROSS. * aclocal.m4: Include accross.m4. * configure, config.in: Regenerate. include/ * hashtab.h (burtle_hash): Prototype. (burtle_hash_object): New macro. --- include/ChangeLog | 5 ++ include/hashtab.h | 5 ++ libiberty/ChangeLog | 7 +++ libiberty/aclocal.m4 | 2 + libiberty/configure.in | 1 + libiberty/hashtab.c | 138 +++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 158 insertions(+) diff --git a/include/ChangeLog b/include/ChangeLog index 6d18714eee..ff914e169b 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2003-05-07 Jason Merrill + + * hashtab.h (burtle_hash): Prototype. + (burtle_hash_object): New macro. + 2003-04-28 H.J. Lu * bfdlink.h (bfd_link_info): Add relax_finalizing. diff --git a/include/hashtab.h b/include/hashtab.h index 7acb5eb285..b86bb29b80 100644 --- a/include/hashtab.h +++ b/include/hashtab.h @@ -183,6 +183,11 @@ extern htab_eq htab_eq_pointer; /* A hash function for null-terminated strings. */ extern hashval_t htab_hash_string PARAMS ((const PTR)); +/* An iterative hash function for arbitrary data. */ +extern hashval_t burtle_hash PARAMS ((const PTR, size_t, hashval_t)); +/* Shorthand for hashing something with an intrinsic size. */ +#define burtle_hash_object(OB,INIT) burtle_hash (&OB, sizeof (OB), INIT) + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 9dc9bfeace..90f51febcc 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,10 @@ +2003-05-07 Jason Merrill + + * hashtab.c (burtle_hash): New fn. + * configure.in: Add AC_C_BIGENDIAN_CROSS. + * aclocal.m4: Include accross.m4. + * configure, config.in: Regenerate. + 2003-05-04 Kaveh R. Ghazi * configure.in (AC_CHECK_FUNCS): Don't make multiple calls. diff --git a/libiberty/aclocal.m4 b/libiberty/aclocal.m4 index 6c5dc6ac64..a3349f3b08 100644 --- a/libiberty/aclocal.m4 +++ b/libiberty/aclocal.m4 @@ -1,3 +1,5 @@ +sinclude(../config/accross.m4) + dnl See whether strncmp reads past the end of its string parameters. dnl On some versions of SunOS4 at least, strncmp reads a word at a time dnl but erroneously reads past the end of strings. This can cause diff --git a/libiberty/configure.in b/libiberty/configure.in index d5b3c7bbd3..4a704e8cec 100644 --- a/libiberty/configure.in +++ b/libiberty/configure.in @@ -114,6 +114,7 @@ AC_SUBST(OUTPUT_OPTION) AC_ISC_POSIX AC_C_CONST AC_C_INLINE +AC_C_BIGENDIAN_CROSS dnl When we start using libtool: dnl Default to a non shared library. This may be overridden by the diff --git a/libiberty/hashtab.c b/libiberty/hashtab.c index 32067afb5b..5b58d71ef1 100644 --- a/libiberty/hashtab.c +++ b/libiberty/hashtab.c @@ -709,3 +709,141 @@ htab_hash_string (p) return r; } + +/* DERIVED FROM: +-------------------------------------------------------------------- +lookup2.c, by Bob Jenkins, December 1996, Public Domain. +hash(), hash2(), hash3, and mix() are externally useful functions. +Routines to test the hash are included if SELF_TEST is defined. +You can use this free for any purpose. It has no warranty. +-------------------------------------------------------------------- +*/ + +/* +-------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. +For every delta with one or two bit set, and the deltas of all three + high bits or all three low bits, whether the original value of a,b,c + is almost all zero or is uniformly distributed, +* If mix() is run forward or backward, at least 32 bits in a,b,c + have at least 1/4 probability of changing. +* If mix() is run forward, every bit of c will change between 1/3 and + 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.) +mix() was built out of 36 single-cycle latency instructions in a + structure that could supported 2x parallelism, like so: + a -= b; + a -= c; x = (c>>13); + b -= c; a ^= x; + b -= a; x = (a<<8); + c -= a; b ^= x; + c -= b; x = (b>>13); + ... + Unfortunately, superscalar Pentiums and Sparcs can't take advantage + of that parallelism. They've also turned some of those single-cycle + latency instructions into multi-cycle latency instructions. Still, + this is the fastest good hash I could find. There were about 2^^68 + to choose from. I only looked at a billion or so. +-------------------------------------------------------------------- +*/ +/* same, but slower, works on systems that might have 8 byte hashval_t's */ +#define mix(a,b,c) \ +{ \ + a -= b; a -= c; a ^= (c>>13); \ + b -= c; b -= a; b ^= (a<< 8); \ + c -= a; c -= b; c ^= ((b&0xffffffff)>>13); \ + a -= b; a -= c; a ^= ((c&0xffffffff)>>12); \ + b -= c; b -= a; b = (b ^ (a<<16)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>> 5)) & 0xffffffff; \ + a -= b; a -= c; a = (a ^ (c>> 3)) & 0xffffffff; \ + b -= c; b -= a; b = (b ^ (a<<10)) & 0xffffffff; \ + c -= a; c -= b; c = (c ^ (b>>15)) & 0xffffffff; \ +} + +/* +-------------------------------------------------------------------- +hash() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + len : the length of the key, counting by bytes + level : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Every 1-bit and 2-bit delta achieves avalanche. +About 36+6len instructions. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (ub1 **)k, do it like this: + for (i=0, h=0; i= 12) /* aligned */ + { + a += *(hashval_t *)(k+0); + b += *(hashval_t *)(k+4); + c += *(hashval_t *)(k+8); + mix(a,b,c); + k += 12; len -= 12; + } + else /* unaligned */ +#endif + while (len >= 12) + { + a += (k[0] +((hashval_t)k[1]<<8) +((hashval_t)k[2]<<16) +((hashval_t)k[3]<<24)); + b += (k[4] +((hashval_t)k[5]<<8) +((hashval_t)k[6]<<16) +((hashval_t)k[7]<<24)); + c += (k[8] +((hashval_t)k[9]<<8) +((hashval_t)k[10]<<16)+((hashval_t)k[11]<<24)); + mix(a,b,c); + k += 12; len -= 12; + } + + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch(len) /* all the case statements fall through */ + { + case 11: c+=((hashval_t)k[10]<<24); + case 10: c+=((hashval_t)k[9]<<16); + case 9 : c+=((hashval_t)k[8]<<8); + /* the first byte of c is reserved for the length */ + case 8 : b+=((hashval_t)k[7]<<24); + case 7 : b+=((hashval_t)k[6]<<16); + case 6 : b+=((hashval_t)k[5]<<8); + case 5 : b+=k[4]; + case 4 : a+=((hashval_t)k[3]<<24); + case 3 : a+=((hashval_t)k[2]<<16); + case 2 : a+=((hashval_t)k[1]<<8); + case 1 : a+=k[0]; + /* case 0: nothing left to add */ + } + mix(a,b,c); + /*-------------------------------------------- report the result */ + return c; +} -- 2.11.0