This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [rfc] division by multiplicative inverse in hashtab.c


I believe I've taken care of all of the comments I recieved.
Committed.


r~



Index: include/hashtab.h
===================================================================
RCS file: /cvs/gcc/gcc/include/hashtab.h,v
retrieving revision 1.21
diff -c -p -d -r1.21 hashtab.h
*** include/hashtab.h	13 Apr 2004 14:48:56 -0000	1.21
--- include/hashtab.h	22 Apr 2004 17:27:17 -0000
***************
*** 1,5 ****
  /* An expandable hash tables datatype.  
!    Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Vladimir Makarov (vmakarov@cygnus.com).
  
  This program is free software; you can redistribute it and/or modify
--- 1,5 ----
  /* An expandable hash tables datatype.  
!    Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
     Contributed by Vladimir Makarov (vmakarov@cygnus.com).
  
  This program is free software; you can redistribute it and/or modify
*************** struct htab GTY(())
*** 126,131 ****
--- 126,135 ----
    PTR GTY((skip)) alloc_arg;
    htab_alloc_with_arg alloc_with_arg_f;
    htab_free_with_arg free_with_arg_f;
+ 
+   /* Current size (in entries) of the hash table, as an index into the
+      table of primes.  */
+   unsigned int size_prime_index;
  };
  
  typedef struct htab *htab_t;
Index: libiberty/configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/configure.ac,v
retrieving revision 1.4
diff -c -p -d -r1.4 configure.ac
*** libiberty/configure.ac	9 Mar 2004 23:02:47 -0000	1.4
--- libiberty/configure.ac	22 Apr 2004 17:27:17 -0000
*************** AC_SUBST_FILE(host_makefile_frag)
*** 159,171 ****
  # It's OK to check for header files.  Although the compiler may not be
  # able to link anything, it had better be able to at least compile
  # something.
! AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h)
  AC_HEADER_SYS_WAIT
  AC_HEADER_TIME
  
  libiberty_AC_DECLARE_ERRNO
  
  AC_CHECK_TYPE(uintptr_t, unsigned long)
  # Given the above check, we always have uintptr_t or a fallback
  # definition.  So define HAVE_UINTPTR_T in case any imported code
  # relies on it.
--- 159,205 ----
  # It's OK to check for header files.  Although the compiler may not be
  # able to link anything, it had better be able to at least compile
  # something.
! AC_CHECK_HEADERS(sys/file.h sys/param.h limits.h stdlib.h malloc.h string.h unistd.h strings.h sys/time.h time.h sys/resource.h sys/stat.h sys/mman.h fcntl.h alloca.h sys/pstat.h sys/sysmp.h sys/sysinfo.h machine/hal_sysinfo.h sys/table.h sys/sysctl.h sys/systemcfg.h stdint.h)
  AC_HEADER_SYS_WAIT
  AC_HEADER_TIME
  
  libiberty_AC_DECLARE_ERRNO
  
  AC_CHECK_TYPE(uintptr_t, unsigned long)
+ 
+ # Look for a 64-bit type.
+ AC_MSG_CHECKING([for a 64-bit type])
+ AC_CACHE_VAL(liberty_cv_uint64,
+ [AC_TRY_COMPILE(
+ [#ifdef HAVE_STDINT_H
+ #include <stdint.h>
+ #endif],
+ [extern uint64_t foo;],
+ liberty_cv_uint64=uint64_t,
+ [AC_TRY_COMPILE(
+ [#ifdef HAVE_LIMITS_H
+ #include <limits.h>
+ #endif
+ #ifndef CHAR_BIT
+ #define CHAR_BIT 8
+ #endif],
+ [extern char foo[sizeof(long) * CHAR_BIT >= 64 ? 1 : -1];],
+ liberty_cv_uint64="unsigned long",
+ [AC_TRY_COMPILE(
+ [#ifdef HAVE_LIMITS_H
+ #include <limits.h>
+ #endif
+ #ifndef CHAR_BIT
+ #define CHAR_BIT 8
+ #endif],
+ [extern char foo[sizeof(long long) * CHAR_BIT >= 64 ? 1 : -1];],
+ liberty_cv_uint64="unsigned long long", liberty_cv_uint64=none)])])])
+ AC_MSG_RESULT($liberty_cv_uint64)
+ if test "$liberty_cv_uint64" != none; then
+   AC_DEFINE(UNSIGNED_64BIT_TYPE, $liberty_cv_uint64,
+             [Define to an unsigned 64-bit type available in the compiler.])
+ fi
+ 
  # Given the above check, we always have uintptr_t or a fallback
  # definition.  So define HAVE_UINTPTR_T in case any imported code
  # relies on it.
Index: libiberty/hashtab.c
===================================================================
RCS file: /cvs/gcc/gcc/libiberty/hashtab.c,v
retrieving revision 1.40
diff -c -p -d -r1.40 hashtab.c
*** libiberty/hashtab.c	13 Apr 2004 14:48:55 -0000	1.40
--- libiberty/hashtab.c	22 Apr 2004 17:27:17 -0000
***************
*** 1,5 ****
  /* An expandable hash tables datatype.  
!    Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
     Contributed by Vladimir Makarov (vmakarov@cygnus.com).
  
  This file is part of the libiberty library.
--- 1,6 ----
  /* An expandable hash tables datatype.  
!    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
!    Free Software Foundation, Inc.
     Contributed by Vladimir Makarov (vmakarov@cygnus.com).
  
  This file is part of the libiberty library.
*************** Boston, MA 02111-1307, USA.  */
*** 40,59 ****
  #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
  #endif
- 
  #ifdef HAVE_STRING_H
  #include <string.h>
  #endif
- 
  #ifdef HAVE_MALLOC_H
  #include <malloc.h>
  #endif
  
  #include <stdio.h>
  
  #include "libiberty.h"
  #include "hashtab.h"
  
  /* This macro defines reserved value for empty table entry. */
  
  #define EMPTY_ENTRY    ((PTR) 0)
--- 41,69 ----
  #ifdef HAVE_STDLIB_H
  #include <stdlib.h>
  #endif
  #ifdef HAVE_STRING_H
  #include <string.h>
  #endif
  #ifdef HAVE_MALLOC_H
  #include <malloc.h>
  #endif
+ #ifdef HAVE_LIMITS_H
+ #include <limits.h>
+ #endif
+ #ifdef HAVE_STDINT_H
+ #include <stdint.h>
+ #endif
  
  #include <stdio.h>
  
  #include "libiberty.h"
+ #include "ansidecl.h"
  #include "hashtab.h"
  
+ #ifndef CHAR_BIT
+ #define CHAR_BIT 8
+ #endif
+ 
  /* This macro defines reserved value for empty table entry. */
  
  #define EMPTY_ENTRY    ((PTR) 0)
*************** Boston, MA 02111-1307, USA.  */
*** 63,69 ****
  
  #define DELETED_ENTRY  ((PTR) 1)
  
! static unsigned long higher_prime_number PARAMS ((unsigned long));
  static hashval_t hash_pointer PARAMS ((const void *));
  static int eq_pointer PARAMS ((const void *, const void *));
  static int htab_expand PARAMS ((htab_t));
--- 73,82 ----
  
  #define DELETED_ENTRY  ((PTR) 1)
  
! static unsigned int higher_prime_index PARAMS ((unsigned long));
! static hashval_t htab_mod_1 PARAMS ((hashval_t, hashval_t, hashval_t, int));
! static hashval_t htab_mod PARAMS ((hashval_t, htab_t));
! static hashval_t htab_mod_m2 PARAMS ((hashval_t, htab_t));
  static hashval_t hash_pointer PARAMS ((const void *));
  static int eq_pointer PARAMS ((const void *, const void *));
  static int htab_expand PARAMS ((htab_t));
*************** static PTR *find_empty_slot_for_expand  
*** 75,143 ****
  htab_hash htab_hash_pointer = hash_pointer;
  htab_eq htab_eq_pointer = eq_pointer;
  
! /* The following function returns a nearest prime number which is
!    greater than N, and near a power of two. */
  
! static unsigned long
! higher_prime_number (n)
!      unsigned long n;
  {
!   /* These are primes that are near, but slightly smaller than, a
!      power of two.  */
!   static const unsigned long primes[] = {
!     (unsigned long) 7,
!     (unsigned long) 13,
!     (unsigned long) 31,
!     (unsigned long) 61,
!     (unsigned long) 127,
!     (unsigned long) 251,
!     (unsigned long) 509,
!     (unsigned long) 1021,
!     (unsigned long) 2039,
!     (unsigned long) 4093,
!     (unsigned long) 8191,
!     (unsigned long) 16381,
!     (unsigned long) 32749,
!     (unsigned long) 65521,
!     (unsigned long) 131071,
!     (unsigned long) 262139,
!     (unsigned long) 524287,
!     (unsigned long) 1048573,
!     (unsigned long) 2097143,
!     (unsigned long) 4194301,
!     (unsigned long) 8388593,
!     (unsigned long) 16777213,
!     (unsigned long) 33554393,
!     (unsigned long) 67108859,
!     (unsigned long) 134217689,
!     (unsigned long) 268435399,
!     (unsigned long) 536870909,
!     (unsigned long) 1073741789,
!     (unsigned long) 2147483647,
! 					/* 4294967291L */
!     ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
!   };
  
!   const unsigned long *low = &primes[0];
!   const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
  
    while (low != high)
      {
!       const unsigned long *mid = low + (high - low) / 2;
!       if (n > *mid)
  	low = mid + 1;
        else
  	high = mid;
      }
  
    /* If we've run out of primes, abort.  */
!   if (n > *low)
      {
        fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
        abort ();
      }
  
!   return *low;
  }
  
  /* Returns a hash code for P.  */
--- 88,204 ----
  htab_hash htab_hash_pointer = hash_pointer;
  htab_eq htab_eq_pointer = eq_pointer;
  
! /* Table of primes and multiplicative inverses.
  
!    Note that these are not minimally reduced inverses.  Unlike when generating
!    code to divide by a constant, we want to be able to use the same algorithm
!    all the time.  All of these inverses (are implied to) have bit 32 set.
! 
!    For the record, here's the function that computed the table; it's a 
!    vastly simplified version of the function of the same name from gcc.  */
! 
! #if 0
! unsigned int
! ceil_log2 (unsigned int x)
  {
!   int i;
!   for (i = 31; i >= 0 ; --i)
!     if (x > (1u << i))
!       return i+1;
!   abort ();
! }
  
! unsigned int
! choose_multiplier (unsigned int d, unsigned int *mlp, unsigned char *shiftp)
! {
!   unsigned long long mhigh;
!   double nx;
!   int lgup, post_shift;
!   int pow, pow2;
!   int n = 32, precision = 32;
! 
!   lgup = ceil_log2 (d);
!   pow = n + lgup;
!   pow2 = n + lgup - precision;
! 
!   nx = ldexp (1.0, pow) + ldexp (1.0, pow2);
!   mhigh = nx / d;
! 
!   *shiftp = lgup - 1;
!   *mlp = mhigh;
!   return mhigh >> 32;
! }
! #endif
! 
! struct prime_ent
! {
!   hashval_t prime;
!   hashval_t inv;
!   hashval_t inv_m2;	/* inverse of prime-2 */
!   hashval_t shift;
! };
! 
! static struct prime_ent const prime_tab[] = {
!   {          7, 0x24924925, 0x9999999b, 2 },
!   {         13, 0x3b13b13c, 0x745d1747, 3 },
!   {         31, 0x08421085, 0x1a7b9612, 4 },
!   {         61, 0x0c9714fc, 0x15b1e5f8, 5 },
!   {        127, 0x02040811, 0x0624dd30, 6 },
!   {        251, 0x05197f7e, 0x073260a5, 7 },
!   {        509, 0x01824366, 0x02864fc8, 8 },
!   {       1021, 0x00c0906d, 0x014191f7, 9 },
!   {       2039, 0x0121456f, 0x0161e69e, 10 },
!   {       4093, 0x00300902, 0x00501908, 11 },
!   {       8191, 0x00080041, 0x00180241, 12 },
!   {      16381, 0x000c0091, 0x00140191, 13 },
!   {      32749, 0x002605a5, 0x002a06e6, 14 },
!   {      65521, 0x000f00e2, 0x00110122, 15 },
!   {     131071, 0x00008001, 0x00018003, 16 },
!   {     262139, 0x00014002, 0x0001c004, 17 },
!   {     524287, 0x00002001, 0x00006001, 18 },
!   {    1048573, 0x00003001, 0x00005001, 19 },
!   {    2097143, 0x00004801, 0x00005801, 20 },
!   {    4194301, 0x00000c01, 0x00001401, 21 },
!   {    8388593, 0x00001e01, 0x00002201, 22 },
!   {   16777213, 0x00000301, 0x00000501, 23 },
!   {   33554393, 0x00001381, 0x00001481, 24 },
!   {   67108859, 0x00000141, 0x000001c1, 25 },
!   {  134217689, 0x000004e1, 0x00000521, 26 },
!   {  268435399, 0x00000391, 0x000003b1, 27 },
!   {  536870909, 0x00000019, 0x00000029, 28 },
!   { 1073741789, 0x0000008d, 0x00000095, 29 },
!   { 2147483647, 0x00000003, 0x00000007, 30 },
!   /* Avoid "decimal constant so large it is unsigned" for 4294967291.  */
!   { 0xfffffffb, 0x00000006, 0x00000008, 31 }
! };
! 
! /* The following function returns an index into the above table of the
!    nearest prime number which is greater than N, and near a power of two. */
! 
! static unsigned int
! higher_prime_index (n)
!      unsigned long n;
! {
!   unsigned int low = 0;
!   unsigned int high = sizeof(prime_tab) / sizeof(prime_tab[0]);
  
    while (low != high)
      {
!       unsigned int mid = low + (high - low) / 2;
!       if (n > prime_tab[mid].prime)
  	low = mid + 1;
        else
  	high = mid;
      }
  
    /* If we've run out of primes, abort.  */
!   if (n > prime_tab[low].prime)
      {
        fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
        abort ();
      }
  
!   return low;
  }
  
  /* Returns a hash code for P.  */
*************** htab_elements (htab)
*** 177,182 ****
--- 238,273 ----
    return htab->n_elements - htab->n_deleted;
  }
  
+ /* Return X % Y.  */
+ 
+ static inline hashval_t
+ htab_mod_1 (x, y, inv, shift)
+      hashval_t x, y, inv;
+      int shift;
+ {
+   /* The multiplicative inverses computed above are for 32-bit types, and
+      requires that we be able to compute a highpart multiply.  */
+ #ifdef UNSIGNED_64BIT_TYPE
+   __extension__ typedef UNSIGNED_64BIT_TYPE ull;
+   if (sizeof (hashval_t) * CHAR_BIT <= 32)
+     {
+       hashval_t t1, t2, t3, t4, q, r;
+ 
+       t1 = ((ull)x * inv) >> 32;
+       t2 = x - t1;
+       t3 = t2 >> 1;
+       t4 = t1 + t3;
+       q  = t4 >> shift;
+       r  = x - (q * y);
+ 
+       return r;
+     }
+ #endif
+ 
+   /* Otherwise just use the native division routines.  */
+   return x % y;
+ }
+ 
  /* Compute the primary hash for HASH given HTAB's current size.  */
  
  static inline hashval_t
*************** htab_mod (hash, htab)
*** 184,190 ****
       hashval_t hash;
       htab_t htab;
  {
!   return hash % htab_size (htab);
  }
  
  /* Compute the secondary hash for HASH given HTAB's current size.  */
--- 275,282 ----
       hashval_t hash;
       htab_t htab;
  {
!   const struct prime_ent *p = &prime_tab[htab->size_prime_index];
!   return htab_mod_1 (hash, p->prime, p->inv, p->shift);
  }
  
  /* Compute the secondary hash for HASH given HTAB's current size.  */
*************** htab_mod_m2 (hash, htab)
*** 194,200 ****
       hashval_t hash;
       htab_t htab;
  {
!   return 1 + hash % (htab_size (htab) - 2);
  }
  
  /* This function creates table with length slightly longer than given
--- 286,293 ----
       hashval_t hash;
       htab_t htab;
  {
!   const struct prime_ent *p = &prime_tab[htab->size_prime_index];
!   return 1 + htab_mod_1 (hash, p->prime - 2, p->inv_m2, p->shift);
  }
  
  /* This function creates table with length slightly longer than given
*************** htab_create_alloc (size, hash_f, eq_f, d
*** 212,219 ****
       htab_free free_f;
  {
    htab_t result;
  
-   size = higher_prime_number (size);
    result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
    if (result == NULL)
      return NULL;
--- 305,315 ----
       htab_free free_f;
  {
    htab_t result;
+   unsigned int size_prime_index;
+ 
+   size_prime_index = higher_prime_index (size);
+   size = prime_tab[size_prime_index].prime;
  
    result = (htab_t) (*alloc_f) (1, sizeof (struct htab));
    if (result == NULL)
      return NULL;
*************** htab_create_alloc (size, hash_f, eq_f, d
*** 225,230 ****
--- 321,327 ----
        return NULL;
      }
    result->size = size;
+   result->size_prime_index = size_prime_index;
    result->hash_f = hash_f;
    result->eq_f = eq_f;
    result->del_f = del_f;
*************** htab_create_alloc_ex (size, hash_f, eq_f
*** 248,255 ****
       htab_free_with_arg free_f;
  {
    htab_t result;
  
-   size = higher_prime_number (size);
    result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
    if (result == NULL)
      return NULL;
--- 345,355 ----
       htab_free_with_arg free_f;
  {
    htab_t result;
+   unsigned int size_prime_index;
+ 
+   size_prime_index = higher_prime_index (size);
+   size = prime_tab[size_prime_index].prime;
  
    result = (htab_t) (*alloc_f) (alloc_arg, 1, sizeof (struct htab));
    if (result == NULL)
      return NULL;
*************** htab_create_alloc_ex (size, hash_f, eq_f
*** 261,266 ****
--- 361,367 ----
        return NULL;
      }
    result->size = size;
+   result->size_prime_index = size_prime_index;
    result->hash_f = hash_f;
    result->eq_f = eq_f;
    result->del_f = del_f;
*************** htab_expand (htab)
*** 412,430 ****
    PTR *olimit;
    PTR *p;
    PTR *nentries;
!   size_t nsize;
  
    oentries = htab->entries;
!   olimit = oentries + htab->size;
  
    /* Resize only when table after removal of unused elements is either
       too full or too empty.  */
!   if ((htab->n_elements - htab->n_deleted) * 2 > htab->size
!       || ((htab->n_elements - htab->n_deleted) * 8 < htab->size
! 	  && htab->size > 32))
!     nsize = higher_prime_number ((htab->n_elements - htab->n_deleted) * 2);
    else
!     nsize = htab->size;
  
    if (htab->alloc_with_arg_f != NULL)
      nentries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
--- 513,539 ----
    PTR *olimit;
    PTR *p;
    PTR *nentries;
!   size_t nsize, osize, elts;
!   unsigned int oindex, nindex;
  
    oentries = htab->entries;
!   oindex = htab->size_prime_index;
!   osize = htab->size;
!   olimit = oentries + osize;
!   elts = htab_elements (htab);
  
    /* Resize only when table after removal of unused elements is either
       too full or too empty.  */
!   if (elts * 2 > osize || (elts * 8 < osize && osize > 32))
!     {
!       nindex = higher_prime_index (elts * 2);
!       nsize = prime_tab[nindex].prime;
!     }
    else
!     {
!       nindex = oindex;
!       nsize = osize;
!     }
  
    if (htab->alloc_with_arg_f != NULL)
      nentries = (PTR *) (*htab->alloc_with_arg_f) (htab->alloc_arg, nsize,
*************** htab_expand (htab)
*** 435,441 ****
      return 0;
    htab->entries = nentries;
    htab->size = nsize;
! 
    htab->n_elements -= htab->n_deleted;
    htab->n_deleted = 0;
  
--- 544,550 ----
      return 0;
    htab->entries = nentries;
    htab->size = nsize;
!   htab->size_prime_index = nindex;
    htab->n_elements -= htab->n_deleted;
    htab->n_deleted = 0;
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]