On Wed, 15 Aug 2012, Michael Matz wrote:

> Hi,
> 
> On Wed, 15 Aug 2012, Richard Guenther wrote:
> 
> > Like the following, only the coverage.c use is converted.  I've never 
> > seen template function arguments anywhere and having to repeat them all 
> > over the place is really really ugly (yes, even if only in the 
> > implementation).
> > 
> > This goes with static member functions and not wrapping any data. It 
> > goes away with the requirement of having externally visible global 
> > functions for the hash/compare functions as well (which was ugly 
> > anyway).
> > 
> > Comments?
> 
> Well, it looks nicer than what's there currently.  As the element 
> functions now are scoped and normal member functions, they should be named 
> with lower case characters of course.  I do like that the hash table would 
> then only have one real template argument; the Allocator, well, no better 
> idea comes to my mind.

Yeah.  Updated patch below, all users converted.  I probably missed
to revert some of the globalizations of hash/compare fns.

Comments?
Richard.

Index: gcc/hash-table.h
===================================================================
*** gcc/hash-table.h.orig       2012-08-15 15:39:34.000000000 +0200
--- gcc/hash-table.h    2012-08-15 16:17:06.613628039 +0200
*************** xcallocator <Type>::data_free (Type *mem
*** 83,127 ****
  }
  
  
- /* A common function for hashing a CANDIDATE typed pointer.  */
- 
  template <typename Element>
! inline hashval_t
! typed_pointer_hash (const Element *candidate)
  {
!   /* This is a really poor hash function, but it is what the current code 
uses,
!      so I am reusing it to avoid an additional axis in testing.  */
!   return (hashval_t) ((intptr_t)candidate >> 3);
! }
  
  
- /* A common function for comparing an EXISTING and CANDIDATE typed pointers
-    for equality. */
  
  template <typename Element>
! inline int
! typed_pointer_equal (const Element *existing, const Element * candidate)
  {
!   return existing == candidate;
! }
  
  
! /* A common function for doing nothing on removing a RETIRED slot.  */
  
  template <typename Element>
! inline void
! typed_null_remove (Element *retired ATTRIBUTE_UNUSED)
  {
  }
  
- 
- /* A common function for using free on removing a RETIRED slot.  */
- 
  template <typename Element>
! inline void
! typed_free_remove (Element *retired)
  {
!   free (retired);
  }
  
  
--- 83,132 ----
  }
  
  
  template <typename Element>
! class typed_free_remove
  {
! public:
!   static inline void remove (Element *p) { free (p); }
! };
  
+ template <typename Element>
+ class typed_noop_remove
+ {
+ public:
+   static inline void remove (Element *) {}
+ };
  
  
+ /* Pointer hash.  */
  template <typename Element>
! class pointer_hash : public typed_noop_remove <Element>
  {
! public:
!   typedef Element Element_t;
  
+   static inline hashval_t
+   hash (const Element_t *);
  
!   static inline int
!   equal (const Element_t *existing, const Element_t * candidate);
! };
  
  template <typename Element>
! inline hashval_t
! pointer_hash<Element>::hash (const Element_t *candidate)
  {
+   /* This is a really poor hash function, but it is what the current code 
uses,
+      so I am reusing it to avoid an additional axis in testing.  */
+   return (hashval_t) ((intptr_t)candidate >> 3);
  }
  
  template <typename Element>
! inline int
! pointer_hash<Element>::equal (const Element_t *existing,
!                             const Element_t *candidate)
  {
!   return existing == candidate;
  }
  
  
*************** struct hash_table_control
*** 180,194 ****
  
     The table stores elements of type Element.
  
!    It hashes elements with the Hash function.
       The table currently works with relatively weak hash functions.
       Use typed_pointer_hash <Element> when hashing pointers instead of 
objects.
  
!    It compares elements with the Equal function.
       Two elements with the same hash may not be equal.
       Use typed_pointer_equal <Element> when hashing pointers instead of 
objects.
  
!    It removes elements with the Remove function.
       This feature is useful for freeing memory.
       Use typed_null_remove <Element> when not freeing objects.
       Use typed_free_remove <Element> when doing a simple object free.
--- 185,199 ----
  
     The table stores elements of type Element.
  
!    It hashes elements with the hash function.
       The table currently works with relatively weak hash functions.
       Use typed_pointer_hash <Element> when hashing pointers instead of 
objects.
  
!    It compares elements with the equal function.
       Two elements with the same hash may not be equal.
       Use typed_pointer_equal <Element> when hashing pointers instead of 
objects.
  
!    It removes elements with the remove function.
       This feature is useful for freeing memory.
       Use typed_null_remove <Element> when not freeing objects.
       Use typed_free_remove <Element> when doing a simple object free.
*************** struct hash_table_control
*** 199,243 ****
  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator = xcallocator>
  class hash_table
  {
  
  private:
  
!   hash_table_control <Element> *htab;
! 
!   Element **find_empty_slot_for_expand (hashval_t hash);
    void expand ();
  
  public:
- 
    hash_table ();
    void create (size_t initial_slots);
    bool is_created ();
    void dispose ();
!   Element *find (Element *comparable);
!   Element *find_with_hash (Element *comparable, hashval_t hash);
!   Element **find_slot (Element *comparable, enum insert_option insert);
!   Element **find_slot_with_hash (Element *comparable, hashval_t hash,
!                                enum insert_option insert);
    void empty ();
!   void clear_slot (Element **slot);
!   void remove_elt (Element *comparable);
!   void remove_elt_with_hash (Element *comparable, hashval_t hash);
    size_t size();
    size_t elements();
    double collisions();
  
    template <typename Argument,
!           int (*Callback) (Element **slot, Argument argument)>
    void traverse_noresize (Argument argument);
  
    template <typename Argument,
!           int (*Callback) (Element **slot, Argument argument)>
    void traverse (Argument argument);
  };
  
--- 204,245 ----
  */
  
  template <typename Element,
          template <typename Type> class Allocator = xcallocator>
  class hash_table
  {
+ public:
+   typedef typename Element::Element_t Element_t;
  
  private:
+   hash_table_control <Element_t> *htab;
  
!   Element_t **find_empty_slot_for_expand (hashval_t hash);
    void expand ();
  
  public:
    hash_table ();
    void create (size_t initial_slots);
    bool is_created ();
    void dispose ();
!   Element_t *find (Element_t *comparable);
!   Element_t *find_with_hash (Element_t *comparable, hashval_t hash);
!   Element_t **find_slot (Element_t *comparable, enum insert_option insert);
!   Element_t **find_slot_with_hash (Element_t *comparable, hashval_t hash,
!                                  enum insert_option insert);
    void empty ();
!   void clear_slot (Element_t **slot);
!   void remove_elt (Element_t *comparable);
!   void remove_elt_with_hash (Element_t *comparable, hashval_t hash);
    size_t size();
    size_t elements();
    double collisions();
  
    template <typename Argument,
!           int (*Callback) (Element_t **slot, Argument argument)>
    void traverse_noresize (Argument argument);
  
    template <typename Argument,
!           int (*Callback) (Element_t **slot, Argument argument)>
    void traverse (Argument argument);
  };
  
*************** public:
*** 245,256 ****
  /* Construct the hash table.  The only useful operation next is create.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  inline
! hash_table <Element, Hash, Equal, Remove, Allocator>::hash_table ()
  : htab (NULL)
  {
  }
--- 247,255 ----
  /* Construct the hash table.  The only useful operation next is create.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  inline
! hash_table <Element, Allocator>::hash_table ()
  : htab (NULL)
  {
  }
*************** hash_table <Element, Hash, Equal, Remove
*** 259,270 ****
  /* See if the table has been created, as opposed to constructed.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  inline bool
! hash_table <Element, Hash, Equal, Remove, Allocator>::is_created ()
  {
    return htab != NULL;
  }
--- 258,266 ----
  /* See if the table has been created, as opposed to constructed.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  inline bool
! hash_table <Element, Allocator>::is_created ()
  {
    return htab != NULL;
  }
*************** hash_table <Element, Hash, Equal, Remove
*** 273,328 ****
  /* Like find_with_hash, but compute the hash value from the element.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
! inline Element *
! hash_table <Element, Hash, Equal, Remove, Allocator>::find (Element 
*comparable)
  {
!   return find_with_hash (comparable, Hash (comparable));
  }
  
  
  /* Like find_slot_with_hash, but compute the hash value from the element.  */
  
  template <typename Element,
!         hashval_t (*Hash) (const Element *candidate),
!         int (*Equal) (const Element *existing, const Element * candidate),
!         void (*Remove) (Element *retired),
!         template <typename Type> class Allocator>
! inline Element **
! hash_table <Element, Hash, Equal, Remove, Allocator>
! ::find_slot (Element *comparable, enum insert_option insert)
  {
!   return find_slot_with_hash (comparable, Hash (comparable), insert);
  }
  
  
  /* Like remove_elt_with_hash, but compute the hash value from the element.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  inline void
! hash_table <Element, Hash, Equal, Remove, Allocator>
! ::remove_elt (Element *comparable)
  {
!   remove_elt_with_hash (comparable, Hash (comparable));
  }
  
  
  /* Return the current size of this hash table.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  inline size_t
! hash_table <Element, Hash, Equal, Remove, Allocator>::size()
  {
    return htab->size;
  }
--- 269,312 ----
  /* Like find_with_hash, but compute the hash value from the element.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
! inline typename Element::Element_t *
! hash_table <Element, Allocator>::find (Element_t *comparable)
  {
!   return find_with_hash (comparable, Element::hash (comparable));
  }
  
  
  /* Like find_slot_with_hash, but compute the hash value from the element.  */
  
  template <typename Element,
!         template <typename Type> class Allocator>
! inline typename Element::Element_t **
! hash_table <Element, Allocator>
! ::find_slot (Element_t *comparable, enum insert_option insert)
  {
!   return find_slot_with_hash (comparable, Element::hash (comparable), insert);
  }
  
  
  /* Like remove_elt_with_hash, but compute the hash value from the element.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  inline void
! hash_table <Element, Allocator>
! ::remove_elt (Element_t *comparable)
  {
!   remove_elt_with_hash (comparable, Element::hash (comparable));
  }
  
  
  /* Return the current size of this hash table.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  inline size_t
! hash_table <Element, Allocator>::size()
  {
    return htab->size;
  }
*************** hash_table <Element, Hash, Equal, Remove
*** 331,342 ****
  /* Return the current number of elements in this hash table. */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  inline size_t
! hash_table <Element, Hash, Equal, Remove, Allocator>::elements()
  {
    return htab->n_elements - htab->n_deleted;
  }
--- 315,323 ----
  /* Return the current number of elements in this hash table. */
  
  template <typename Element,
          template <typename Type> class Allocator>
  inline size_t
! hash_table <Element, Allocator>::elements()
  {
    return htab->n_elements - htab->n_deleted;
  }
*************** hash_table <Element, Hash, Equal, Remove
*** 346,357 ****
       hash table. */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  inline double
! hash_table <Element, Hash, Equal, Remove, Allocator>::collisions()
  {
    if (htab->searches == 0)
      return 0.0;
--- 327,335 ----
       hash table. */
  
  template <typename Element,
          template <typename Type> class Allocator>
  inline double
! hash_table <Element, Allocator>::collisions()
  {
    if (htab->searches == 0)
      return 0.0;
*************** hash_table <Element, Hash, Equal, Remove
*** 363,383 ****
  /* Create a hash table with at least the given number of INITIAL_SLOTS.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>::create (size_t size)
  {
    unsigned int size_prime_index;
  
    size_prime_index = hash_table_higher_prime_index (size);
    size = prime_tab[size_prime_index].prime;
  
!   htab = Allocator <hash_table_control <Element> > ::control_alloc (1);
    gcc_assert (htab != NULL);
!   htab->entries = Allocator <Element*> ::data_alloc (size);
    gcc_assert (htab->entries != NULL);
    htab->size = size;
    htab->size_prime_index = size_prime_index;
--- 341,358 ----
  /* Create a hash table with at least the given number of INITIAL_SLOTS.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  void
! hash_table <Element, Allocator>::create (size_t size)
  {
    unsigned int size_prime_index;
  
    size_prime_index = hash_table_higher_prime_index (size);
    size = prime_tab[size_prime_index].prime;
  
!   htab = Allocator <hash_table_control <Element_t> > ::control_alloc (1);
    gcc_assert (htab != NULL);
!   htab->entries = Allocator <Element_t*> ::data_alloc (size);
    gcc_assert (htab->entries != NULL);
    htab->size = size;
    htab->size_prime_index = size_prime_index;
*************** hash_table <Element, Hash, Equal, Remove
*** 388,432 ****
     the non-created state.  Naturally the hash table must already exist.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>::dispose ()
  {
    size_t size = htab->size;
!   Element **entries = htab->entries;
  
    for (int i = size - 1; i >= 0; i--)
      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
!       Remove (entries[i]);
  
!   Allocator <Element *> ::data_free (entries);
!   Allocator <hash_table_control <Element> > ::control_free (htab);
    htab = NULL;
  }
  
  
  /* Similar to find_slot, but without several unwanted side effects:
!     - Does not call Equal when it finds an existing entry.
      - Does not change the count of elements/searches/collisions in the
        hash table.
     This function also assumes there are no deleted entries in the table.
     HASH is the hash value for the element to be inserted.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
! Element **
! hash_table <Element, Hash, Equal, Remove, Allocator>
  ::find_empty_slot_for_expand (hashval_t hash)
  {
    hashval_t index = hash_table_mod1 (hash, htab->size_prime_index);
    size_t size = htab->size;
!   Element **slot = htab->entries + index;
    hashval_t hash2;
  
    if (*slot == HTAB_EMPTY_ENTRY)
--- 363,401 ----
     the non-created state.  Naturally the hash table must already exist.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  void
! hash_table <Element, Allocator>::dispose ()
  {
    size_t size = htab->size;
!   Element_t **entries = htab->entries;
  
    for (int i = size - 1; i >= 0; i--)
      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
!       Element::remove (entries[i]);
  
!   Allocator <Element_t *> ::data_free (entries);
!   Allocator <hash_table_control <Element_t> > ::control_free (htab);
    htab = NULL;
  }
  
  
  /* Similar to find_slot, but without several unwanted side effects:
!     - Does not call equal when it finds an existing entry.
      - Does not change the count of elements/searches/collisions in the
        hash table.
     This function also assumes there are no deleted entries in the table.
     HASH is the hash value for the element to be inserted.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
! typename Element::Element_t **
! hash_table <Element, Allocator>
  ::find_empty_slot_for_expand (hashval_t hash)
  {
    hashval_t index = hash_table_mod1 (hash, htab->size_prime_index);
    size_t size = htab->size;
!   Element_t **slot = htab->entries + index;
    hashval_t hash2;
  
    if (*slot == HTAB_EMPTY_ENTRY)
*************** hash_table <Element, Hash, Equal, Remove
*** 458,474 ****
     will abort.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>::expand ()
  {
!   Element **oentries;
!   Element **olimit;
!   Element **p;
!   Element **nentries;
    size_t nsize, osize, elts;
    unsigned int oindex, nindex;
  
--- 427,440 ----
     will abort.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  void
! hash_table <Element, Allocator>::expand ()
  {
!   Element_t **oentries;
!   Element_t **olimit;
!   Element_t **p;
!   Element_t **nentries;
    size_t nsize, osize, elts;
    unsigned int oindex, nindex;
  
*************** hash_table <Element, Hash, Equal, Remove
*** 491,497 ****
        nsize = osize;
      }
  
!   nentries = Allocator <Element *> ::data_alloc (nsize);
    gcc_assert (nentries != NULL);
    htab->entries = nentries;
    htab->size = nsize;
--- 457,463 ----
        nsize = osize;
      }
  
!   nentries = Allocator <Element_t *> ::data_alloc (nsize);
    gcc_assert (nentries != NULL);
    htab->entries = nentries;
    htab->size = nsize;
*************** hash_table <Element, Hash, Equal, Remove
*** 502,512 ****
    p = oentries;
    do
      {
!       Element *x = *p;
  
        if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
          {
!           Element **q = find_empty_slot_for_expand (Hash (x));
  
            *q = x;
          }
--- 468,478 ----
    p = oentries;
    do
      {
!       Element_t *x = *p;
  
        if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
          {
!           Element_t **q = find_empty_slot_for_expand (Element::hash (x));
  
            *q = x;
          }
*************** hash_table <Element, Hash, Equal, Remove
*** 515,521 ****
      }
    while (p < olimit);
  
!   Allocator <Element *> ::data_free (oentries);
  }
  
  
--- 481,487 ----
      }
    while (p < olimit);
  
!   Allocator <Element_t *> ::data_free (oentries);
  }
  
  
*************** hash_table <Element, Hash, Equal, Remove
*** 524,540 ****
     be used to insert or delete an element. */
  
  template <typename Element,
!         hashval_t (*Hash) (const Element *candidate),
!         int (*Equal) (const Element *existing, const Element * candidate),
!         void (*Remove) (Element *retired),
!         template <typename Type> class Allocator>
! Element *
! hash_table <Element, Hash, Equal, Remove, Allocator>
! ::find_with_hash (Element *comparable, hashval_t hash)
  {
    hashval_t index, hash2;
    size_t size;
!   Element *entry;
  
    htab->searches++;
    size = htab->size;
--- 490,503 ----
     be used to insert or delete an element. */
  
  template <typename Element,
!         template <typename Type> class Allocator>
! typename Element::Element_t *
! hash_table <Element, Allocator>
! ::find_with_hash (Element_t *comparable, hashval_t hash)
  {
    hashval_t index, hash2;
    size_t size;
!   Element_t *entry;
  
    htab->searches++;
    size = htab->size;
*************** hash_table <Element, Hash, Equal, Remove
*** 542,548 ****
  
    entry = htab->entries[index];
    if (entry == HTAB_EMPTY_ENTRY
!       || (entry != HTAB_DELETED_ENTRY && Equal (entry, comparable)))
      return entry;
  
    hash2 = hash_table_mod2 (hash, htab->size_prime_index);
--- 505,511 ----
  
    entry = htab->entries[index];
    if (entry == HTAB_EMPTY_ENTRY
!       || (entry != HTAB_DELETED_ENTRY && Element::equal (entry, comparable)))
      return entry;
  
    hash2 = hash_table_mod2 (hash, htab->size_prime_index);
*************** hash_table <Element, Hash, Equal, Remove
*** 555,561 ****
  
        entry = htab->entries[index];
        if (entry == HTAB_EMPTY_ENTRY
!           || (entry != HTAB_DELETED_ENTRY && Equal (entry, comparable)))
          return entry;
      }
  }
--- 518,524 ----
  
        entry = htab->entries[index];
        if (entry == HTAB_EMPTY_ENTRY
!           || (entry != HTAB_DELETED_ENTRY && Element::equal (entry, 
comparable)))
          return entry;
      }
  }
*************** hash_table <Element, Hash, Equal, Remove
*** 570,588 ****
     entry, NULL may be returned if memory allocation fails. */
  
  template <typename Element,
!         hashval_t (*Hash) (const Element *candidate),
!         int (*Equal) (const Element *existing, const Element * candidate),
!         void (*Remove) (Element *retired),
!         template <typename Type> class Allocator>
! Element **
! hash_table <Element, Hash, Equal, Remove, Allocator>
! ::find_slot_with_hash (Element *comparable, hashval_t hash,
                       enum insert_option insert)
  {
!   Element **first_deleted_slot;
    hashval_t index, hash2;
    size_t size;
!   Element *entry;
  
    size = htab->size;
    if (insert == INSERT && size * 3 <= htab->n_elements * 4)
--- 533,548 ----
     entry, NULL may be returned if memory allocation fails. */
  
  template <typename Element,
!         template <typename Type> class Allocator>
! typename Element::Element_t **
! hash_table <Element, Allocator>
! ::find_slot_with_hash (Element_t *comparable, hashval_t hash,
                       enum insert_option insert)
  {
!   Element_t **first_deleted_slot;
    hashval_t index, hash2;
    size_t size;
!   Element_t *entry;
  
    size = htab->size;
    if (insert == INSERT && size * 3 <= htab->n_elements * 4)
*************** hash_table <Element, Hash, Equal, Remove
*** 601,607 ****
      goto empty_entry;
    else if (entry == HTAB_DELETED_ENTRY)
      first_deleted_slot = &htab->entries[index];
!   else if (Equal (entry, comparable))
      return &htab->entries[index];
        
    hash2 = hash_table_mod2 (hash, htab->size_prime_index);
--- 561,567 ----
      goto empty_entry;
    else if (entry == HTAB_DELETED_ENTRY)
      first_deleted_slot = &htab->entries[index];
!   else if (Element::equal (entry, comparable))
      return &htab->entries[index];
        
    hash2 = hash_table_mod2 (hash, htab->size_prime_index);
*************** hash_table <Element, Hash, Equal, Remove
*** 620,626 ****
          if (!first_deleted_slot)
            first_deleted_slot = &htab->entries[index];
        }
!       else if (Equal (entry, comparable))
        return &htab->entries[index];
      }
  
--- 580,586 ----
          if (!first_deleted_slot)
            first_deleted_slot = &htab->entries[index];
        }
!       else if (Element::equal (entry, comparable))
        return &htab->entries[index];
      }
  
*************** hash_table <Element, Hash, Equal, Remove
*** 631,637 ****
    if (first_deleted_slot)
      {
        htab->n_deleted--;
!       *first_deleted_slot = static_cast <Element *> (HTAB_EMPTY_ENTRY);
        return first_deleted_slot;
      }
  
--- 591,597 ----
    if (first_deleted_slot)
      {
        htab->n_deleted--;
!       *first_deleted_slot = static_cast <Element_t *> (HTAB_EMPTY_ENTRY);
        return first_deleted_slot;
      }
  
*************** hash_table <Element, Hash, Equal, Remove
*** 643,662 ****
  /* This function clears all entries in the given hash table.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>::empty ()
  {
    size_t size = htab_size (htab);
!   Element **entries = htab->entries;
    int i;
  
    for (i = size - 1; i >= 0; i--)
      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
!       Remove (entries[i]);
  
    /* Instead of clearing megabyte, downsize the table.  */
    if (size > 1024*1024 / sizeof (PTR))
--- 603,619 ----
  /* This function clears all entries in the given hash table.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  void
! hash_table <Element, Allocator>::empty ()
  {
    size_t size = htab_size (htab);
!   Element_t **entries = htab->entries;
    int i;
  
    for (i = size - 1; i >= 0; i--)
      if (entries[i] != HTAB_EMPTY_ENTRY && entries[i] != HTAB_DELETED_ENTRY)
!       Element::remove (entries[i]);
  
    /* Instead of clearing megabyte, downsize the table.  */
    if (size > 1024*1024 / sizeof (PTR))
*************** hash_table <Element, Hash, Equal, Remove
*** 664,676 ****
        int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
        int nsize = prime_tab[nindex].prime;
  
!       Allocator <Element *> ::data_free (htab->entries);
!       htab->entries = Allocator <Element *> ::data_alloc (nsize);
        htab->size = nsize;
        htab->size_prime_index = nindex;
      }
    else
!     memset (entries, 0, size * sizeof (Element *));
    htab->n_deleted = 0;
    htab->n_elements = 0;
  }
--- 621,633 ----
        int nindex = hash_table_higher_prime_index (1024 / sizeof (PTR));
        int nsize = prime_tab[nindex].prime;
  
!       Allocator <Element_t *> ::data_free (htab->entries);
!       htab->entries = Allocator <Element_t *> ::data_alloc (nsize);
        htab->size = nsize;
        htab->size_prime_index = nindex;
      }
    else
!     memset (entries, 0, size * sizeof (Element_t *));
    htab->n_deleted = 0;
    htab->n_elements = 0;
  }
*************** hash_table <Element, Hash, Equal, Remove
*** 681,699 ****
     again. */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>
! ::clear_slot (Element **slot)
  {
    if (slot < htab->entries || slot >= htab->entries + htab->size
        || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
      abort ();
  
!   Remove (*slot);
  
    *slot = HTAB_DELETED_ENTRY;
    htab->n_deleted++;
--- 638,653 ----
     again. */
  
  template <typename Element,
          template <typename Type> class Allocator>
  void
! hash_table <Element, Allocator>
! ::clear_slot (Element_t **slot)
  {
    if (slot < htab->entries || slot >= htab->entries + htab->size
        || *slot == HTAB_EMPTY_ENTRY || *slot == HTAB_DELETED_ENTRY)
      abort ();
  
!   Element::remove (*slot);
  
    *slot = HTAB_DELETED_ENTRY;
    htab->n_deleted++;
*************** hash_table <Element, Hash, Equal, Remove
*** 705,727 ****
     matching element in the hash table, this function does nothing. */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>
! ::remove_elt_with_hash (Element *comparable, hashval_t hash)
  {
!   Element **slot;
  
    slot = find_slot_with_hash (comparable, hash, NO_INSERT);
    if (*slot == HTAB_EMPTY_ENTRY)
      return;
  
!   Remove (*slot);
  
!   *slot = static_cast <Element *> (HTAB_DELETED_ENTRY);
    htab->n_deleted++;
  }
  
--- 659,678 ----
     matching element in the hash table, this function does nothing. */
  
  template <typename Element,
          template <typename Type> class Allocator>
  void
! hash_table <Element, Allocator>
! ::remove_elt_with_hash (Element_t *comparable, hashval_t hash)
  {
!   Element_t **slot;
  
    slot = find_slot_with_hash (comparable, hash, NO_INSERT);
    if (*slot == HTAB_EMPTY_ENTRY)
      return;
  
!   Element::remove (*slot);
  
!   *slot = static_cast <Element_t *> (HTAB_DELETED_ENTRY);
    htab->n_deleted++;
  }
  
*************** hash_table <Element, Hash, Equal, Remove
*** 731,755 ****
     ARGUMENT is passed as CALLBACK's second argument. */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  template <typename Argument,
!         int (*Callback) (Element **slot, Argument argument)>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>
  ::traverse_noresize (Argument argument)
  {
!   Element **slot;
!   Element **limit;
  
    slot = htab->entries;
    limit = slot + htab->size;
  
    do
      {
!       Element *x = *slot;
  
        if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
          if (! Callback (slot, argument))
--- 682,703 ----
     ARGUMENT is passed as CALLBACK's second argument. */
  
  template <typename Element,
          template <typename Type> class Allocator>
  template <typename Argument,
!         int (*Callback) (typename Element::Element_t **slot, Argument 
argument)>
  void
! hash_table <Element, Allocator>
  ::traverse_noresize (Argument argument)
  {
!   Element_t **slot;
!   Element_t **limit;
  
    slot = htab->entries;
    limit = slot + htab->size;
  
    do
      {
!       Element_t *x = *slot;
  
        if (x != HTAB_EMPTY_ENTRY && x != HTAB_DELETED_ENTRY)
          if (! Callback (slot, argument))
*************** hash_table <Element, Hash, Equal, Remove
*** 763,776 ****
     to improve effectivity of subsequent calls.  */
  
  template <typename Element,
-         hashval_t (*Hash) (const Element *candidate),
-         int (*Equal) (const Element *existing, const Element * candidate),
-         void (*Remove) (Element *retired),
          template <typename Type> class Allocator>
  template <typename Argument,
!         int (*Callback) (Element **slot, Argument argument)>
  void
! hash_table <Element, Hash, Equal, Remove, Allocator>
  ::traverse (Argument argument)
  {
    size_t size = htab->size;
--- 711,721 ----
     to improve effectivity of subsequent calls.  */
  
  template <typename Element,
          template <typename Type> class Allocator>
  template <typename Argument,
!         int (*Callback) (typename Element::Element_t **slot, Argument 
argument)>
  void
! hash_table <Element, Allocator>
  ::traverse (Argument argument)
  {
    size_t size = htab->size;
Index: gcc/coverage.c
===================================================================
*** gcc/coverage.c.orig 2012-08-15 15:39:34.000000000 +0200
--- gcc/coverage.c      2012-08-15 16:12:58.471636654 +0200
*************** get_gcov_unsigned_t (void)
*** 143,172 ****
    return lang_hooks.types.type_for_mode (mode, true);
  }
  
! inline hashval_t
! coverage_counts_entry_hash (const counts_entry_t *entry)
! {
!   return entry->ident * GCOV_COUNTERS + entry->ctr;
! }
! 
! inline int
! coverage_counts_entry_eq (const counts_entry_t *entry1,
!                           const counts_entry_t *entry2)
! {
!   return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
! }
! 
! inline void
! coverage_counts_entry_del (counts_entry_t *entry)
! {
!   free (entry->counts);
!   free (entry);
! }
  
  /* Hash table of count data.  */
! static hash_table <counts_entry_t, coverage_counts_entry_hash,
!                  coverage_counts_entry_eq, coverage_counts_entry_del>
!                 counts_hash;
  
  /* Read in the counts file, if available.  */
  
--- 143,172 ----
    return lang_hooks.types.type_for_mode (mode, true);
  }
  
! /* Hash functions for counts_entry.  */
! class counts_entry_hash {
! public:
!   typedef counts_entry_t Element_t;
!   static inline int equal (const counts_entry_t *entry1,
!                          const counts_entry_t *entry2)
!   {
!     return entry1->ident == entry2->ident && entry1->ctr == entry2->ctr;
!   }
!   static inline hashval_t
!   hash (const counts_entry_t *entry)
!   {
!     return entry->ident * GCOV_COUNTERS + entry->ctr;
!   }
!   static inline void
!   remove (counts_entry_t *entry)
!   {
!     free (entry->counts);
!     free (entry);
!   }
! };
  
  /* Hash table of count data.  */
! static hash_table <counts_entry_hash> counts_hash;
  
  /* Read in the counts file, if available.  */
  
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c.orig     2012-08-15 10:20:31.000000000 +0200
--- gcc/tree-ssa-ccp.c  2012-08-15 15:45:45.896693215 +0200
*************** evaluate_stmt (gimple stmt)
*** 1688,1697 ****
    return val;
  }
  
! typedef hash_table <gimple_statement_d, 
typed_pointer_hash<gimple_statement_d>,
!                   typed_pointer_equal<gimple_statement_d>,
!                   typed_null_remove<gimple_statement_d> >
!                  gimple_htab;
  
  /* Given a BUILT_IN_STACK_SAVE value SAVED_VAL, insert a clobber of VAR before
     each matching BUILT_IN_STACK_RESTORE.  Mark visited phis in VISITED.  */
--- 1688,1694 ----
    return val;
  }
  
! typedef hash_table <pointer_hash <gimple_statement_d> > gimple_htab;
  
  /* Given a BUILT_IN_STACK_SAVE value SAVED_VAL, insert a clobber of VAR before
     each matching BUILT_IN_STACK_RESTORE.  Mark visited phis in VISITED.  */
Index: gcc/tree-ssa-coalesce.c
===================================================================
*** gcc/tree-ssa-coalesce.c.orig        2012-08-15 10:20:33.000000000 +0200
--- gcc/tree-ssa-coalesce.c     2012-08-15 16:14:56.051632549 +0200
*************** coalesce_partitions (var_map map, ssa_co
*** 1258,1278 ****
      }
  }
  
! /* Returns a hash code for N.  */
! 
! inline hashval_t
! hash_ssa_name_by_var (const_tree n)
! {
!   return (hashval_t) htab_hash_pointer (SSA_NAME_VAR (n));
! }
! 
! /* Returns nonzero if N1 and N2 are equal.  */
! 
! inline int
! eq_ssa_name_by_var (const_tree n1, const_tree n2)
! {
!   return SSA_NAME_VAR (n1) == SSA_NAME_VAR (n2);
! }
  
  /* Reduce the number of copies by coalescing variables in the function.  
Return
     a partition map with the resulting coalesces.  */
--- 1258,1276 ----
      }
  }
  
! /* SSA_NAME_VAR hash.  */
! class ssa_name_var_hash : public typed_noop_remove <union tree_node> {
! public:
!   typedef union tree_node Element_t;
!   static inline hashval_t hash (const_tree n)
!   {
!     return DECL_UID (SSA_NAME_VAR (n));
!   }
!   static inline int equal (const_tree n1, const_tree n2)
!   {
!     return SSA_NAME_VAR (n1) == SSA_NAME_VAR (n2);
!   }
! };
  
  /* Reduce the number of copies by coalescing variables in the function.  
Return
     a partition map with the resulting coalesces.  */
*************** coalesce_ssa_name (void)
*** 1286,1294 ****
    bitmap used_in_copies = BITMAP_ALLOC (NULL);
    var_map map;
    unsigned int i;
!   static hash_table <tree_node, hash_ssa_name_by_var, eq_ssa_name_by_var,
!                    typed_null_remove<tree_node> >
!                   ssa_name_hash;
  
    cl = create_coalesce_list ();
    map = create_outofssa_var_map (cl, used_in_copies);
--- 1284,1290 ----
    bitmap used_in_copies = BITMAP_ALLOC (NULL);
    var_map map;
    unsigned int i;
!   static hash_table <ssa_name_var_hash> ssa_name_hash;
  
    cl = create_coalesce_list ();
    map = create_outofssa_var_map (cl, used_in_copies);
Index: gcc/tree-ssa-pre.c
===================================================================
*** gcc/tree-ssa-pre.c.orig     2012-08-15 10:20:33.000000000 +0200
--- gcc/tree-ssa-pre.c  2012-08-15 16:16:11.339629977 +0200
*************** static unsigned int next_expression_id;
*** 229,237 ****
  DEF_VEC_P (pre_expr);
  DEF_VEC_ALLOC_P (pre_expr, heap);
  static VEC(pre_expr, heap) *expressions;
! static hash_table <pre_expr_d, ssa_pre_expr_hash, ssa_pre_expr_eq,
!                  typed_null_remove <pre_expr_d> >
!                 expression_to_id;
  static VEC(unsigned, heap) *name_to_id;
  
  /* Allocate an expression id for EXPR.  */
--- 229,247 ----
  DEF_VEC_P (pre_expr);
  DEF_VEC_ALLOC_P (pre_expr, heap);
  static VEC(pre_expr, heap) *expressions;
! struct pre_expr_hash : public typed_noop_remove <pre_expr_d> {
!   typedef pre_expr_d Element_t;
!   static inline hashval_t hash (const struct pre_expr_d *e)
!   {
!     return ssa_pre_expr_hash (e);
!   }
!   static inline int equal (const struct pre_expr_d *e1,
!                          const struct pre_expr_d *e2)
!   {
!     return ssa_pre_expr_eq (e1, e2);
!   }
! };
! static hash_table <pre_expr_hash> expression_to_id;
  static VEC(unsigned, heap) *name_to_id;
  
  /* Allocate an expression id for EXPR.  */
*************** typedef struct expr_pred_trans_d
*** 500,537 ****
  } *expr_pred_trans_t;
  typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
  
- /* Return the hash value for a phi translation table entry.  */
- 
- inline hashval_t
- ssa_expr_pred_trans_hash (const expr_pred_trans_d *ve)
- {
-   return ve->hashcode;
- }
- 
- /* Return true if two phi translation table entries are the same.
-    P1 and P2 should point to the expr_pred_trans_t's to be compared.*/
- 
- inline int
- ssa_expr_pred_trans_eq (const expr_pred_trans_d *ve1,
-                       const expr_pred_trans_d *ve2)
- {
-   basic_block b1 = ve1->pred;
-   basic_block b2 = ve2->pred;
- 
-   /* If they are not translations for the same basic block, they can't
-      be equal.  */
-   if (b1 != b2)
-     return false;
-   return ssa_pre_expr_eq (ve1->e, ve2->e);
- }
- 
  /* The phi_translate_table caches phi translations for a given
     expression and predecessor.  */
! 
! static hash_table <expr_pred_trans_d, ssa_expr_pred_trans_hash,
!                  ssa_expr_pred_trans_eq,
!                  typed_free_remove <expr_pred_trans_d> >
!                 phi_translate_table;
  
  /* Search in the phi translation table for the translation of
     expression E in basic block PRED.
--- 510,537 ----
  } *expr_pred_trans_t;
  typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
  
  /* The phi_translate_table caches phi translations for a given
     expression and predecessor.  */
! struct expr_pred_trans_hash : public typed_free_remove<expr_pred_trans_d>
! {
!   typedef expr_pred_trans_d Element_t;
!   static inline hashval_t hash (const Element_t *e)
!   {
!     return e->hashcode;
!   }
!   static inline int equal (const Element_t *ve1, const Element_t *ve2)
!   {
!     basic_block b1 = ve1->pred;
!     basic_block b2 = ve2->pred;
! 
!     /* If they are not translations for the same basic block, they can't
!        be equal.  */
!     if (b1 != b2)
!       return false;
!     return ssa_pre_expr_eq (ve1->e, ve2->e);
!   }
! };
! static hash_table <expr_pred_trans_hash> phi_translate_table;
  
  /* Search in the phi translation table for the translation of
     expression E in basic block PRED.
Index: gcc/tree-ssa-tail-merge.c
===================================================================
*** gcc/tree-ssa-tail-merge.c.orig      2012-08-15 10:20:26.000000000 +0200
--- gcc/tree-ssa-tail-merge.c   2012-08-15 16:24:46.219612235 +0200
*************** stmt_update_dep_bb (gimple stmt)
*** 415,422 ****
  
  /* Calculates hash value for same_succ VE.  */
  
! hashval_t
! ssa_same_succ_hash (const_same_succ e)
  {
    hashval_t hashval = bitmap_hash (e->succs);
    int flags;
--- 415,422 ----
  
  /* Calculates hash value for same_succ VE.  */
  
! static hashval_t
! same_succ_hash (const_same_succ e)
  {
    hashval_t hashval = bitmap_hash (e->succs);
    int flags;
*************** inverse_flags (const_same_succ e1, const
*** 511,520 ****
    return (f1a & mask) == (f2a & mask) && (f1b & mask) == (f2b & mask);
  }
  
  /* Compares SAME_SUCCs VE1 and VE2.  */
  
  int
! ssa_same_succ_equal (const_same_succ e1, const_same_succ e2)
  {
    unsigned int i, first1, first2;
    gimple_stmt_iterator gsi1, gsi2;
--- 511,572 ----
    return (f1a & mask) == (f2a & mask) && (f1b & mask) == (f2b & mask);
  }
  
+ /* Alloc and init a new SAME_SUCC.  */
+ 
+ static same_succ
+ same_succ_alloc (void)
+ {
+   same_succ same = XNEW (struct same_succ_def);
+ 
+   same->bbs = BITMAP_ALLOC (NULL);
+   same->succs = BITMAP_ALLOC (NULL);
+   same->inverse = BITMAP_ALLOC (NULL);
+   same->succ_flags = VEC_alloc (int, heap, 10);
+   same->in_worklist = false;
+ 
+   return same;
+ }
+ 
+ /* Delete same_succ VE.  */
+ 
+ static inline void
+ same_succ_delete (same_succ e)
+ {
+   BITMAP_FREE (e->bbs);
+   BITMAP_FREE (e->succs);
+   BITMAP_FREE (e->inverse);
+   VEC_free (int, heap, e->succ_flags);
+ 
+   XDELETE (e);
+ }
+ 
+ /* Reset same_succ SAME.  */
+ 
+ static void
+ same_succ_reset (same_succ same)
+ {
+   bitmap_clear (same->bbs);
+   bitmap_clear (same->succs);
+   bitmap_clear (same->inverse);
+   VEC_truncate (int, same->succ_flags, 0);
+ }
+ 
+ /* Hash table with all same_succ entries.  */
+ 
+ struct same_succ_hashtable {
+   typedef same_succ_def Element_t;
+   static inline hashval_t hash (const same_succ_def *e) { return e->hashval; }
+   static int equal (const_same_succ, const_same_succ);
+   static inline void remove (Element_t *e1)
+   {
+     same_succ_delete (e1);
+   }
+ };
+ 
  /* Compares SAME_SUCCs VE1 and VE2.  */
  
  int
! same_succ_hashtable::equal (const_same_succ e1, const_same_succ e2)
  {
    unsigned int i, first1, first2;
    gimple_stmt_iterator gsi1, gsi2;
*************** ssa_same_succ_equal (const_same_succ e1,
*** 568,618 ****
    return 1;
  }
  
! /* Alloc and init a new SAME_SUCC.  */
! 
! static same_succ
! same_succ_alloc (void)
! {
!   same_succ same = XNEW (struct same_succ_def);
! 
!   same->bbs = BITMAP_ALLOC (NULL);
!   same->succs = BITMAP_ALLOC (NULL);
!   same->inverse = BITMAP_ALLOC (NULL);
!   same->succ_flags = VEC_alloc (int, heap, 10);
!   same->in_worklist = false;
! 
!   return same;
! }
! 
! /* Delete same_succ VE.  */
! 
! inline void
! ssa_same_succ_delete (same_succ e)
! {
!   BITMAP_FREE (e->bbs);
!   BITMAP_FREE (e->succs);
!   BITMAP_FREE (e->inverse);
!   VEC_free (int, heap, e->succ_flags);
! 
!   XDELETE (e);
! }
! 
! /* Reset same_succ SAME.  */
! 
! static void
! same_succ_reset (same_succ same)
! {
!   bitmap_clear (same->bbs);
!   bitmap_clear (same->succs);
!   bitmap_clear (same->inverse);
!   VEC_truncate (int, same->succ_flags, 0);
! }
! 
! /* Hash table with all same_succ entries.  */
! 
! static hash_table <struct same_succ_def, ssa_same_succ_hash,
!                  ssa_same_succ_equal, ssa_same_succ_delete>
!                 same_succ_htab;
  
  /* Array that is used to store the edge flags for a successor.  */
  
--- 620,626 ----
    return 1;
  }
  
! static hash_table <same_succ_hashtable> same_succ_htab;
  
  /* Array that is used to store the edge flags for a successor.  */
  
*************** find_same_succ_bb (basic_block bb, same_
*** 692,698 ****
    EXECUTE_IF_SET_IN_BITMAP (same->succs, 0, j, bj)
      VEC_safe_push (int, heap, same->succ_flags, same_succ_edge_flags[j]);
  
!   same->hashval = ssa_same_succ_hash (same);
  
    slot = same_succ_htab.find_slot_with_hash (same, same->hashval, INSERT);
    if (*slot == NULL)
--- 700,706 ----
    EXECUTE_IF_SET_IN_BITMAP (same->succs, 0, j, bj)
      VEC_safe_push (int, heap, same->succ_flags, same_succ_edge_flags[j]);
  
!   same->hashval = same_succ_hash (same);
  
    slot = same_succ_htab.find_slot_with_hash (same, same->hashval, INSERT);
    if (*slot == NULL)
*************** find_same_succ (void)
*** 728,734 ****
        same = same_succ_alloc ();
      }
  
!   ssa_same_succ_delete (same);
  }
  
  /* Initializes worklist administration.  */
--- 736,742 ----
        same = same_succ_alloc ();
      }
  
!   same_succ_delete (same);
  }
  
  /* Initializes worklist administration.  */
*************** update_worklist (void)
*** 860,866 ****
        if (same == NULL)
        same = same_succ_alloc ();
      }
!   ssa_same_succ_delete (same);
    bitmap_clear (deleted_bb_preds);
  }
  
--- 868,874 ----
        if (same == NULL)
        same = same_succ_alloc ();
      }
!   same_succ_delete (same);
    bitmap_clear (deleted_bb_preds);
  }
  
Index: gcc/tree-ssa-threadupdate.c
===================================================================
*** gcc/tree-ssa-threadupdate.c.orig    2012-08-15 10:20:26.000000000 +0200
--- gcc/tree-ssa-threadupdate.c 2012-08-15 16:27:19.144606857 +0200
*************** create_block_for_threading (basic_block
*** 218,248 ****
  }
  
  /* Hashing and equality routines for our hash table.  */
- inline hashval_t
- ssa_redirection_data_hash (const struct redirection_data *p)
- {
-   edge e = p->outgoing_edge;
-   return e->dest->index;
- }
  
! inline int
! ssa_redirection_data_eq (const struct redirection_data *p1,
!                        const struct redirection_data *p2)
  {
!   edge e1 = p1->outgoing_edge;
!   edge e2 = p2->outgoing_edge;
!   edge e3 = p1->intermediate_edge;
!   edge e4 = p2->intermediate_edge;
! 
!   return e1 == e2 && e3 == e4;
! }
  
  /* Main data structure to hold information for duplicates of BB.  */
  
! static hash_table <struct redirection_data, ssa_redirection_data_hash,
!                  ssa_redirection_data_eq,
!                  typed_free_remove<struct redirection_data> >
!                 redirection_data;
  
  /* Given an outgoing edge E lookup and return its entry in our hash table.
  
--- 218,251 ----
  }
  
  /* Hashing and equality routines for our hash table.  */
  
! struct ssa_redirection_data_hash
!   : public typed_free_remove<struct redirection_data>
  {
!   typedef redirection_data Element_t;
!   static inline hashval_t
!   hash (const struct redirection_data *p)
!   {
!     edge e = p->outgoing_edge;
!     return e->dest->index;
!   }
! 
!   static inline int
!   equal (const struct redirection_data *p1,
!          const struct redirection_data *p2)
!   {
!     edge e1 = p1->outgoing_edge;
!     edge e2 = p2->outgoing_edge;
!     edge e3 = p1->intermediate_edge;
!     edge e4 = p2->intermediate_edge;
! 
!     return e1 == e2 && e3 == e4;
!   }
! };
  
  /* Main data structure to hold information for duplicates of BB.  */
  
! static hash_table <ssa_redirection_data_hash> redirection_data;
  
  /* Given an outgoing edge E lookup and return its entry in our hash table.
  

Reply via email to