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.