From 7e825da03edc82020de4d245b22fb123f5e976d8 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 13 Dec 2005 07:59:01 +0000 Subject: [PATCH] struct-layout-1.exp: Do not link with libiberty. * g++.dg/compat/struct-layout-1.exp: Do not link with libiberty. * g++.dg/compat/struct-layout-1_generate.c (config.h): Do not include. (limits.h): Include unconditionally. (stdlib.h): Likewise. (hashtab.h): Do not include. (getopt.h): Likewise. (stddef.h): Include. (hashval_t): Define. (struct entry): Add "next" field. (HASH_SIZE): New macro. (hash_table): New variable. (switchfiles): Do not use xmalloc. (mix): New macro. (iterative_hash): New function. (hasht): Remove. (e_exists): New function. (e_insert): Likewise. (output): Use, instead of libiberty hashtable functions. (main): Do not use getopt. Do not call htab_create. Co-Authored-By: Jakub Jelinek From-SVN: r108461 --- gcc/testsuite/ChangeLog | 23 +- .../g++.dg/compat/struct-layout-1.exp | 5 +- .../g++.dg/compat/struct-layout-1_generate.c | 234 +++++++++++++++--- 3 files changed, 219 insertions(+), 43 deletions(-) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e71e05ee6d0..9bde74d9640 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,4 +1,25 @@ -2005-12-13 Jakub Jelinek +2005-12-13 Mark Mitchell + Jakub Jelinek + + * g++.dg/compat/struct-layout-1.exp: Do not link with libiberty. + * g++.dg/compat/struct-layout-1_generate.c (config.h): Do not include. + (limits.h): Include unconditionally. + (stdlib.h): Likewise. + (hashtab.h): Do not include. + (getopt.h): Likewise. + (stddef.h): Include. + (hashval_t): Define. + (struct entry): Add "next" field. + (HASH_SIZE): New macro. + (hash_table): New variable. + (switchfiles): Do not use xmalloc. + (mix): New macro. + (iterative_hash): New function. + (hasht): Remove. + (e_exists): New function. + (e_insert): Likewise. + (output): Use, instead of libiberty hashtable functions. + (main): Do not use getopt. Do not call htab_create. PR c++/25331 * gcc.dg/compat/struct-layout-1_generate.c (subfield): Don't diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1.exp b/gcc/testsuite/g++.dg/compat/struct-layout-1.exp index d2e1de9857b..e0a13f7d100 100644 --- a/gcc/testsuite/g++.dg/compat/struct-layout-1.exp +++ b/gcc/testsuite/g++.dg/compat/struct-layout-1.exp @@ -127,10 +127,7 @@ set generator "$tmpdir/g++.dg-struct-layout-1_generate" set generator_src "$srcdir/$subdir/struct-layout-1_generate.c" set generator_src "$generator_src $srcdir/$subdir/../../gcc.dg/compat/generate-random.c" set generator_src "$generator_src $srcdir/$subdir/../../gcc.dg/compat/generate-random_r.c" -set generator_inc "-I$srcdir/$subdir -I$srcdir/../../include" -set generator_inc "$generator_inc -I$rootme/../libiberty" -set generator_lib "-L$rootme/../libiberty -liberty" -set generator_cmd "-o $generator $generator_src $generator_inc $generator_lib" +set generator_cmd "-o $generator $generator_src" set status [remote_exec host "$HOSTCC $HOSTCFLAGS $generator_cmd"] set status [lindex $status 0] diff --git a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c index da915c7cb8f..a2aba71ba8e 100644 --- a/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c @@ -19,23 +19,15 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* Compile with gcc -I$(srcdir)/../include -{I,L}$(objdir)/../libiberty/ \ - -o struct-layout-1_generate{,.c} generate_random{,_r}.c -liberty */ +/* Compile with gcc -o struct-layout-1_generate{,.c} generate_random{,_r}.c */ -#include "config.h" -#ifdef HAVE_LIMITS_H +/* N.B. -- This program cannot use libiberty as that will not work + when testing an installed compiler. */ #include -#endif -#include "libiberty.h" #include -#ifdef HAVE_STDLIB_H #include -#endif -#ifdef HAVE_STRING_H #include -#endif -#include "hashtab.h" -#include "getopt.h" +#include /* We use our own pseudo-random number generator, so that it gives the same values on all hosts. */ #include "../../gcc.dg/compat/generate-random.h" @@ -44,6 +36,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA # error Need 64-bit long long #endif +typedef unsigned int hashval_t; + enum TYPE { TYPE_INT, @@ -390,6 +384,8 @@ struct entry unsigned char arr_len; struct types *type; const char *attrib; + /* Used to chain together entries in the hash table. */ + struct entry *next; }; struct types attrib_array_types[] = { { "Talx1char", TYPE_UINT, 127, 'C' }, @@ -478,6 +474,10 @@ struct types attrib_array_types[] = { #define NAATYPES2 (sizeof (attrib_array_types) / sizeof (attrib_array_types[0])) }; +/* A prime number giving the number of slots in the hash table. */ +#define HASH_SIZE 32749 +static struct entry *hash_table[HASH_SIZE]; + static int idx, limidx, output_one; static const char *destdir; static const char *srcdir; @@ -499,7 +499,9 @@ switchfiles (int fields) if (destbuf == NULL) { size_t len = strlen (destdir); - destbuf = xmalloc (len + 20); + destbuf = malloc (len + 20); + if (!destbuf) + abort (); memcpy (destbuf, destdir, len); if (!len || destbuf[len - 1] != '/') destbuf[len++] = '/'; @@ -916,6 +918,130 @@ subvalues (struct entry *e, char *p, char *letter) } } +/* 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) + { + 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; +} + hashval_t e_hash (const void *a) { @@ -961,24 +1087,45 @@ e_eq (const void *a, const void *b) return 1; } -htab_t hasht; +static int +e_exists (const struct entry *e) +{ + struct entry *h; + hashval_t hval; + + hval = e_hash (e); + for (h = hash_table[hval % HASH_SIZE]; h; h = h->next) + if (e_eq (e, h)) + return 1; + return 0; +} + +static void +e_insert (struct entry *e) +{ + hashval_t hval; + + hval = e_hash (e); + e->next = hash_table[hval % HASH_SIZE]; + hash_table[hval % HASH_SIZE] = e; +} void output (struct entry *e) { int i; char c; - void **p; + struct entry *n; if (e[0].etype != ETYPE_STRUCT && e[0].etype != ETYPE_UNION) abort (); - p = htab_find_slot (hasht, e, INSERT); - if (*p != NULL) + if (e_exists (e)) return; - *p = malloc ((e[0].len + 1) * sizeof (struct entry)); - memcpy (*p, e, (e[0].len + 1) * sizeof (struct entry)); + n = (struct entry *) malloc ((e[0].len + 1) * sizeof (struct entry)); + memcpy (n, e, (e[0].len + 1) * sizeof (struct entry)); + e_insert (n); if (idx == limidx) switchfiles (e[0].len); @@ -1357,29 +1504,41 @@ int main (int argc, char **argv) { int i, j, count, c, n = 3000; + char *optarg; if (sizeof (int) != 4 || sizeof (long long) != 8) return 1; - - while ((c = getopt (argc, argv, "d:i:n:s:")) != -1) - switch (c) - { - case 'n': - n = atoi (optarg); - break; - case 'd': - destdir = optarg; - break; - case 's': - srcdir = optarg; - break; - case 'i': - output_one = 1; - limidx = atoi (optarg); - break; - default: + + i = 1; + while (i < argc) + { + c = '\0'; + if (argv[i][0] == '-' && argv[i][2] == '\0') + c = argv[i][1]; + optarg = argv[i + 1]; + if (!optarg) goto usage; + switch (c) + { + case 'n': + n = atoi (optarg); + break; + case 'd': + destdir = optarg; + break; + case 's': + srcdir = optarg; + break; + case 'i': + output_one = 1; + limidx = atoi (optarg); + break; + default: + fprintf (stderr, "unrecognized option %s\n", argv[i]); + goto usage; } + i += 2; + } if (output_one) { @@ -1404,7 +1563,6 @@ Either -s srcdir -d destdir or -i idx must be used\n", argv[0]); if (srcdir == NULL && !output_one) goto usage; - hasht = htab_create (40000, e_hash, e_eq, NULL); for (i = 0; i < NTYPES2; ++i) if (base_types[i].bitfld) bitfld_types[n_bitfld_types++] = base_types[i];