On Fri, Jun 20, 2014 at 12:52 PM, <tsaund...@mozilla.com> wrote: > From: Trevor Saunders <tsaund...@mozilla.com> > > Hi, > > This patch adds a hash_map class so we can consolidate the boiler plate around > using hash_table as a map, it also allows us to get rid of pointer_map which I > do in this patch by converting its users to hash_map. > > bootstrapped + regtested without regression on x86_64-unknown-linux-gnu, ok?
Ok. Thanks, Richard. > Trev > > gcc/ > > * alloc-pool.c (alloc_pool_hash): Use hash_map instead of hash_table. > * dominance.c (iterate_fix_dominators): Use hash_map instead of > pointer_map. > * hash-map.h: New file. > * ipa-comdats.c: Use hash_map instead of pointer_map. > * lto-section-out.c: Adjust. > * lto-streamer.h: Replace pointer_map with hash_map. > * symtab.c (verify_symtab): Likewise. > * tree-ssa-strlen.c (decl_to_stridxlist_htab): Likewise. > * tree-ssa-uncprop.c (val_ssa_equiv): Likewise. > * tree-streamer.h: Likewise. > * tree-streamer.c: Adjust. > * pointer-set.h: Remove pointer_map. > > lto/ > > * lto.c (canonical_type_hash_cache): Use hash_map instead of > pointer_map. > > diff --git a/gcc/alloc-pool.c b/gcc/alloc-pool.c > index 49209ee..0d31835 100644 > --- a/gcc/alloc-pool.c > +++ b/gcc/alloc-pool.c > @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see > #include "system.h" > #include "alloc-pool.h" > #include "hash-table.h" > +#include "hash-map.h" > > #define align_eight(x) (((x+7) >> 3) << 3) > > @@ -69,7 +70,6 @@ static ALLOC_POOL_ID_TYPE last_id; > size for that pool. */ > struct alloc_pool_descriptor > { > - const char *name; > /* Number of pools allocated. */ > unsigned long created; > /* Gross allocated storage. */ > @@ -82,48 +82,17 @@ struct alloc_pool_descriptor > int elt_size; > }; > > -/* Hashtable helpers. */ > -struct alloc_pool_hasher : typed_noop_remove <alloc_pool_descriptor> > -{ > - typedef alloc_pool_descriptor value_type; > - typedef char compare_type; > - static inline hashval_t hash (const alloc_pool_descriptor *); > - static inline bool equal (const value_type *, const compare_type *); > -}; > - > -inline hashval_t > -alloc_pool_hasher::hash (const value_type *d) > -{ > - return htab_hash_pointer (d->name); > -} > - > -inline bool > -alloc_pool_hasher::equal (const value_type *d, > - const compare_type *p2) > -{ > - return d->name == p2; > -} > - > /* Hashtable mapping alloc_pool names to descriptors. */ > -static hash_table<alloc_pool_hasher> *alloc_pool_hash; > +static hash_map<const char *, alloc_pool_descriptor> *alloc_pool_hash; > > /* For given name, return descriptor, create new if needed. */ > static struct alloc_pool_descriptor * > allocate_pool_descriptor (const char *name) > { > - struct alloc_pool_descriptor **slot; > - > if (!alloc_pool_hash) > - alloc_pool_hash = new hash_table<alloc_pool_hasher> (10); > - > - slot = alloc_pool_hash->find_slot_with_hash (name, > - htab_hash_pointer (name), > - INSERT); > - if (*slot) > - return *slot; > - *slot = XCNEW (struct alloc_pool_descriptor); > - (*slot)->name = name; > - return *slot; > + alloc_pool_hash = new hash_map<const char *, alloc_pool_descriptor> (10); > + > + return &alloc_pool_hash->get_or_insert (name); > } > > /* Create a pool of things of size SIZE, with NUM in each block we > @@ -375,23 +344,22 @@ struct output_info > unsigned long total_allocated; > }; > > -/* Called via hash_table.traverse. Output alloc_pool descriptor pointed out > by > +/* Called via hash_map.traverse. Output alloc_pool descriptor pointed out by > SLOT and update statistics. */ > -int > -print_alloc_pool_statistics (alloc_pool_descriptor **slot, > +bool > +print_alloc_pool_statistics (const char *const &name, > + const alloc_pool_descriptor &d, > struct output_info *i) > { > - struct alloc_pool_descriptor *d = *slot; > - > - if (d->allocated) > + if (d.allocated) > { > fprintf (stderr, > "%-22s %6d %10lu %10lu(%10lu) %10lu(%10lu) %10lu(%10lu)\n", > - d->name, d->elt_size, d->created, d->allocated, > - d->allocated / d->elt_size, d->peak, d->peak / d->elt_size, > - d->current, d->current / d->elt_size); > - i->total_allocated += d->allocated; > - i->total_created += d->created; > + name, d.elt_size, d.created, d.allocated, > + d.allocated / d.elt_size, d.peak, d.peak / d.elt_size, > + d.current, d.current / d.elt_size); > + i->total_allocated += d.allocated; > + i->total_created += d.created; > } > return 1; > } > diff --git a/gcc/dominance.c b/gcc/dominance.c > index 7adec4f..be0a439 100644 > --- a/gcc/dominance.c > +++ b/gcc/dominance.c > @@ -43,6 +43,7 @@ > #include "diagnostic-core.h" > #include "et-forest.h" > #include "timevar.h" > +#include "hash-map.h" > #include "pointer-set.h" > #include "graphds.h" > #include "bitmap.h" > @@ -1258,7 +1259,6 @@ iterate_fix_dominators (enum cdi_direction dir, > vec<basic_block> bbs, > size_t dom_i; > edge e; > edge_iterator ei; > - pointer_map<int> *map; > int *parent, *son, *brother; > unsigned int dir_index = dom_convert_dir_to_idx (dir); > > @@ -1346,15 +1346,15 @@ iterate_fix_dominators (enum cdi_direction dir, > vec<basic_block> bbs, > } > > /* Construct the graph G. */ > - map = new pointer_map<int>; > + hash_map<basic_block, int> map (251); > FOR_EACH_VEC_ELT (bbs, i, bb) > { > /* If the dominance tree is conservatively correct, split it now. */ > if (conservative) > set_immediate_dominator (CDI_DOMINATORS, bb, NULL); > - *map->insert (bb) = i; > + map.put (bb, i); > } > - *map->insert (ENTRY_BLOCK_PTR_FOR_FN (cfun)) = n; > + map.put (ENTRY_BLOCK_PTR_FOR_FN (cfun), n); > > g = new_graph (n + 1); > for (y = 0; y < g->n_vertices; y++) > @@ -1367,7 +1367,7 @@ iterate_fix_dominators (enum cdi_direction dir, > vec<basic_block> bbs, > if (dom == bb) > continue; > > - dom_i = *map->contains (dom); > + dom_i = *map.get (dom); > > /* Do not include parallel edges to G. */ > if (!bitmap_set_bit ((bitmap) g->vertices[dom_i].data, i)) > @@ -1378,7 +1378,6 @@ iterate_fix_dominators (enum cdi_direction dir, > vec<basic_block> bbs, > } > for (y = 0; y < g->n_vertices; y++) > BITMAP_FREE (g->vertices[y].data); > - delete map; > > /* Find the dominator tree of G. */ > son = XNEWVEC (int, n + 1); > diff --git a/gcc/hash-map.h b/gcc/hash-map.h > new file mode 100644 > index 0000000..0b50f72 > --- /dev/null > +++ b/gcc/hash-map.h > @@ -0,0 +1,203 @@ > +/* A type-safe hash map. > + Copyright (C) 2014 Free Software Foundation, Inc. > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +<http://www.gnu.org/licenses/>. */ > + > + > +#ifndef hash_map_h > +#define hash_map_h > + > +#include "hash-table.h" > + > +/* implement default behavior for traits when types allow it. */ > + > +struct default_hashmap_traits > +{ > + /* Hashes the passed in key. */ > + > + template<typename T> > + static hashval_t > + hash (T *p) > + { > + return uintptr_t(p) >> 3; > + } > + > + /* The right thing to do here would be using is_integral to only allow > + template arguments of integer type, but reimplementing that is a pain, > so > + we'll just promote everything to [u]int64_t and truncate to hashval_t. > */ > + > + static hashval_t hash (uint64_t v) { return v; } > + static hashval_t hash (int64_t v) { return v; } > + > + /* Return true if the two keys passed as arguments are equal. */ > + > + template<typename T> > + static bool > + equal_keys (const T &a, const T &b) > + { > + return a == b; > + } > + > + /* Called to dispose of the key and value before marking the entry as > + deleted. */ > + > + template<typename T> static void remove (T &v) { v.~T (); } > + > + /* Mark the passed in entry as being deleted. */ > + > + template<typename T> > + static void > + mark_deleted (T &e) > + { > + mark_key_deleted (e.m_key); > + } > + > + /* Mark the passed in entry as being empty. */ > + > + template<typename T> > + static void > + mark_empty (T &e) > + { > + mark_key_empty (e.m_key); > + } > + > + /* Return true if the passed in entry is marked as deleted. */ > + > + template<typename T> > + static bool > + is_deleted (T &e) > + { > + return e.m_key == (void *)1; > + } > + > + /* Return true if the passed in entry is marked as empty. */ > + > + template<typename T> static bool is_empty (T &e) { return e.m_key == NULL; > } > + > +private: > + template<typename T> > + static void > + mark_key_deleted (T *&k) > + { > + k = static_cast<T *> (1); > + } > + > + template<typename T> > + static void > + mark_key_empty (T *&k) > + { > + k = static_cast<T *> (0); > + } > +}; > + > +template<typename Key, typename Value, > + typename Traits = default_hashmap_traits> > +class hash_map > +{ > + struct hash_entry > + { > + Key m_key; > + Value m_value; > + > + typedef hash_entry value_type; > + typedef Key compare_type; > + typedef int store_values_directly; > + > + static hashval_t hash (const hash_entry &e) > + { > + return Traits::hash (e.m_key); > + } > + > + static bool equal (const hash_entry &a, const Key &b) > + { > + return Traits::equal_keys (a.m_key, b); > + } > + > + static void remove (hash_entry &e) { Traits::remove (e); } > + > + static void mark_deleted (hash_entry &e) { Traits::mark_deleted (e); } > + > + static bool is_deleted (const hash_entry &e) > + { > + return Traits::is_deleted (e); > + } > + > + static void mark_empty (hash_entry &e) { Traits::mark_empty (e); } > + static bool is_empty (const hash_entry &e) { return Traits::is_empty > (e); } > + }; > + > +public: > + explicit hash_map (size_t n = 13) : m_table (n) {} > + > + /* If key k isn't already in the map add key k with value v to the map, and > + return false. Otherwise set the value of the entry for key k to be v > and > + return true. */ > + > + bool put (const Key &k, const Value &v) > + { > + hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k), > + INSERT); > + bool existed = !hash_entry::is_empty (*e); > + if (!existed) > + e->m_key = k; > + > + e->m_value = v; > + return existed; > + } > + > + /* if the passed in key is in the map return its value otherwise NULL. */ > + > + Value *get (const Key &k) > + { > + hash_entry &e = m_table.find_with_hash (k, Traits::hash (k)); > + return Traits::is_empty (e) ? NULL : &e.m_value; > + } > + > + /* Return a reference to the value for the passed in key, creating the > entry > + if it doesn't already exist. If existed is not NULL then it is set to > false > + if the key was not previously in the map, and true otherwise. */ > + > + Value &get_or_insert (const Key &k, bool *existed = NULL) > + { > + hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k), > + INSERT); > + bool ins = Traits::is_empty (*e); > + if (ins) > + e->m_key = k; > + > + if (existed != NULL) > + *existed = !ins; > + > + return e->m_value; > + } > + > + /* Call the call back on each pair of key and value with the passed in > + arg. */ > + > + template<typename Arg, bool (*f)(const Key &, const Value &, Arg)> > + void traverse (Arg a) const > + { > + for (typename hash_table<hash_entry>::iterator iter = m_table.begin (); > + iter != m_table.end (); ++iter) > + f ((*iter).m_key, (*iter).m_value, a); > + } > + > +private: > + hash_table<hash_entry> m_table; > +}; > + > +#endif > diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c > index 6926900..b1bc35e 100644 > --- a/gcc/ipa-comdats.c > +++ b/gcc/ipa-comdats.c > @@ -55,7 +55,7 @@ along with GCC; see the file COPYING3. If not see > #include "tree.h" > #include "cgraph.h" > #include "tree-pass.h" > -#include "pointer-set.h" > +#include "hash-map.h" > > /* Main dataflow loop propagating comdat groups across > the symbol table. All references to SYMBOL are examined > @@ -64,7 +64,7 @@ along with GCC; see the file COPYING3. If not see > > tree > propagate_comdat_group (struct symtab_node *symbol, > - tree newgroup, pointer_map <tree> &map) > + tree newgroup, hash_map<symtab_node *, tree> &map) > { > int i; > struct ipa_ref *ref; > @@ -105,7 +105,7 @@ propagate_comdat_group (struct symtab_node *symbol, > > /* The actual merge operation. */ > > - tree *val2 = map.contains (symbol2); > + tree *val2 = map.get (symbol2); > > if (val2 && *val2 != newgroup) > { > @@ -138,7 +138,7 @@ propagate_comdat_group (struct symtab_node *symbol, > > /* The actual merge operation. */ > > - tree *val2 = map.contains (symbol2); > + tree *val2 = map.get (symbol2); > > if (val2 && *val2 != newgroup) > { > @@ -213,8 +213,8 @@ set_comdat_group (symtab_node *symbol, > static unsigned int > ipa_comdats (void) > { > - pointer_map<tree> map; > - pointer_map<symtab_node *> comdat_head_map; > + hash_map<symtab_node *, tree> map (251); > + hash_map<tree, symtab_node *> comdat_head_map (251); > symtab_node *symbol; > bool comdat_group_seen = false; > symtab_node *first = (symtab_node *) (void *) 1; > @@ -229,8 +229,8 @@ ipa_comdats (void) > ; > else if ((group = symbol->get_comdat_group ()) != NULL) > { > - *map.insert (symbol) = group; > - *comdat_head_map.insert (group) = symbol; > + map.put (symbol, group); > + comdat_head_map.put (group, symbol); > comdat_group_seen = true; > > /* Mark the symbol so we won't waste time visiting it for dataflow. > */ > @@ -248,7 +248,7 @@ ipa_comdats (void) > && (DECL_STATIC_CONSTRUCTOR (symbol->decl) > || DECL_STATIC_DESTRUCTOR (symbol->decl)))) > { > - *map.insert (symtab_alias_ultimate_target (symbol, NULL)) = > error_mark_node; > + map.put (symtab_alias_ultimate_target (symbol, NULL), > error_mark_node); > > /* Mark the symbol so we won't waste time visiting it for dataflow. > */ > symbol->aux = (symtab_node *) (void *) 1; > @@ -278,7 +278,7 @@ ipa_comdats (void) > first = (symtab_node *)first->aux; > > /* Get current lattice value of SYMBOL. */ > - val = map.contains (symbol); > + val = map.get (symbol); > if (val) > group = *val; > > @@ -301,7 +301,7 @@ ipa_comdats (void) > if (val) > *val = newgroup; > else > - *map.insert (symbol) = newgroup; > + map.put (symbol, newgroup); > enqueue_references (&first, symbol); > > /* We may need to revisit the symbol unless it is BOTTOM. */ > @@ -318,7 +318,7 @@ ipa_comdats (void) > && !symbol->alias > && symtab_real_symbol_p (symbol)) > { > - tree group = *map.contains (symbol); > + tree group = *map.get (symbol); > > if (group == error_mark_node) > continue; > @@ -329,7 +329,7 @@ ipa_comdats (void) > fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER > (group)); > } > symtab_for_node_and_aliases (symbol, set_comdat_group, > - *comdat_head_map.contains (group), > true); > + *comdat_head_map.get (group), true); > } > } > return 0; > diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c > index 9d6926c..00b1801 100644 > --- a/gcc/lto-section-out.c > +++ b/gcc/lto-section-out.c > @@ -224,21 +224,17 @@ lto_output_decl_index (struct lto_output_stream *obs, > struct lto_tree_ref_encoder *encoder, > tree name, unsigned int *this_index) > { > - unsigned *slot; > - unsigned int index; > bool new_entry_p = FALSE; > bool existed_p; > > - slot = encoder->tree_hash_table->insert (name, &existed_p); > + unsigned int &index > + = encoder->tree_hash_table->get_or_insert (name, &existed_p); > if (!existed_p) > { > index = encoder->trees.length (); > - *slot = index; > encoder->trees.safe_push (name); > new_entry_p = TRUE; > } > - else > - index = *slot; > > if (obs) > streamer_write_uhwi_stream (obs, index); > diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h > index 889e91d..566a0e0 100644 > --- a/gcc/lto-streamer.h > +++ b/gcc/lto-streamer.h > @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see > > #include "plugin-api.h" > #include "hash-table.h" > +#include "hash-map.h" > #include "target.h" > #include "cgraph.h" > #include "vec.h" > @@ -472,7 +473,7 @@ struct GTY(()) lto_tree_ref_table > > struct lto_tree_ref_encoder > { > - pointer_map<unsigned> *tree_hash_table; /* Maps pointers to indices. > */ > + hash_map<tree, unsigned> *tree_hash_table; /* Maps pointers to indices. > */ > vec<tree> trees; /* Maps indices to pointers. */ > }; > > @@ -994,7 +995,7 @@ lto_tag_check_range (enum LTO_tags actual, enum LTO_tags > tag1, > static inline void > lto_init_tree_ref_encoder (struct lto_tree_ref_encoder *encoder) > { > - encoder->tree_hash_table = new pointer_map<unsigned>; > + encoder->tree_hash_table = new hash_map<tree, unsigned> (251); > encoder->trees.create (0); > } > > @@ -1005,8 +1006,8 @@ static inline void > lto_destroy_tree_ref_encoder (struct lto_tree_ref_encoder *encoder) > { > /* Hash table may be delete already. */ > - if (encoder->tree_hash_table) > - delete encoder->tree_hash_table; > + delete encoder->tree_hash_table; > + encoder->tree_hash_table = NULL; > encoder->trees.release (); > } > > diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c > index 7c60981..78997b5 100644 > --- a/gcc/lto/lto.c > +++ b/gcc/lto/lto.c > @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see > #include "tree-pass.h" > #include "langhooks.h" > #include "bitmap.h" > +#include "hash-map.h" > #include "ipa-prop.h" > #include "common.h" > #include "debug.h" > @@ -261,7 +262,7 @@ lto_read_in_decl_state (struct data_in *data_in, const > uint32_t *data, > > /* Global canonical type table. */ > static htab_t gimple_canonical_types; > -static pointer_map <hashval_t> *canonical_type_hash_cache; > +static hash_map<const_tree, hashval_t> *canonical_type_hash_cache; > static unsigned long num_canonical_type_hash_entries; > static unsigned long num_canonical_type_hash_queries; > > @@ -405,8 +406,7 @@ static hashval_t > gimple_canonical_type_hash (const void *p) > { > num_canonical_type_hash_queries++; > - hashval_t *slot > - = canonical_type_hash_cache->contains (CONST_CAST_TREE ((const_tree) p)); > + hashval_t *slot = canonical_type_hash_cache->get ((const_tree) p); > gcc_assert (slot != NULL); > return *slot; > } > @@ -648,10 +648,8 @@ gimple_register_canonical_type_1 (tree t, hashval_t hash) > *slot = (void *) t; > /* Cache the just computed hash value. */ > num_canonical_type_hash_entries++; > - bool existed_p; > - hashval_t *hslot = canonical_type_hash_cache->insert (t, &existed_p); > + bool existed_p = canonical_type_hash_cache->put (t, hash); > gcc_assert (!existed_p); > - *hslot = hash; > } > } > > @@ -2921,7 +2919,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char > **fnames) > } > cgraph_state = CGRAPH_LTO_STREAMING; > > - canonical_type_hash_cache = new pointer_map <hashval_t>; > + canonical_type_hash_cache = new hash_map<const_tree, hashval_t> (251); > gimple_canonical_types = htab_create_ggc (16381, > gimple_canonical_type_hash, > gimple_canonical_type_eq, 0); > gcc_obstack_init (&tree_scc_hash_obstack); > diff --git a/gcc/pointer-set.h b/gcc/pointer-set.h > index a426534..fc59212 100644 > --- a/gcc/pointer-set.h > +++ b/gcc/pointer-set.h > @@ -45,117 +45,6 @@ void pointer_set_traverse (const struct pointer_set_t *, > void *); > bool pointer_set_lookup (const pointer_set_t *, const void *, size_t *); > > -/* A pointer map is represented the same way as a pointer_set, so > - the hash code is based on the address of the key, rather than > - its contents. Null keys are a reserved value. Deletion is not > - supported (yet). There is no mechanism for user control of hash > - function, equality comparison, initial size, or resizing policy. */ > - > -template <typename T> > -class pointer_map : protected pointer_set_t > -{ > - T *values; > - > -public: > - pointer_map (); > - ~pointer_map (); > - T *contains (const void *p); > - T *insert (const void *p, bool *existed_p = NULL); > - void traverse (bool (*fn) (const void *, T *, void *), void *data); > -}; > - > -/* Allocate an empty pointer map. */ > -template <typename T> > -pointer_map<T>::pointer_map (void) > -{ > - n_elements = 0; > - log_slots = 8; > - n_slots = (size_t) 1 << log_slots; > - > - slots = XCNEWVEC (const void *, n_slots); > - values = XNEWVEC (T, n_slots); > -} > - > -/* Reclaims all memory associated with PMAP. */ > -template <typename T> > -pointer_map<T>::~pointer_map (void) > -{ > - XDELETEVEC (slots); > - XDELETEVEC (values); > -} > - > -/* Returns a pointer to the value to which P maps, if PMAP contains P. P > - must be nonnull. Return NULL if PMAP does not contain P. > - > - Collisions are resolved by linear probing. */ > -template <typename T> > -T * > -pointer_map<T>::contains (const void *p) > -{ > - size_t n; > - if (!pointer_set_lookup (this, p, &n)) > - return NULL; > - return &values[n]; > -} > - > -/* Inserts P into PMAP if it wasn't already there. Returns a pointer > - to the value. P must be nonnull. */ > -template <typename T> > -T * > -pointer_map<T>::insert (const void *p, bool *existed_p) > -{ > - size_t n; > - > - /* For simplicity, expand the map even if P is already there. This can be > - superfluous but can happen at most once. */ > - /* ??? Fugly that we have to inline that here. */ > - if (n_elements > n_slots / 4) > - { > - size_t old_n_slots = n_slots; > - const void **old_keys = slots; > - T *old_values = values; > - log_slots = log_slots + 1; > - n_slots = n_slots * 2; > - slots = XCNEWVEC (const void *, n_slots); > - values = XNEWVEC (T, n_slots); > - for (size_t i = 0; i < old_n_slots; ++i) > - if (old_keys[i]) > - { > - const void *key = old_keys[i]; > - pointer_set_lookup (this, key, &n); > - slots[n] = key; > - values[n] = old_values[i]; > - } > - XDELETEVEC (old_keys); > - XDELETEVEC (old_values); > - } > - > - if (!pointer_set_lookup (this, p, &n)) > - { > - ++n_elements; > - slots[n] = p; > - if (existed_p) > - *existed_p = false; > - } > - else if (existed_p) > - *existed_p = true; > - > - return &values[n]; > -} > - > -/* Pass each pointer in PMAP to the function in FN, together with the pointer > - to the value and the fixed parameter DATA. If FN returns false, the > - iteration stops. */ > - > -template <class T> > -void > -pointer_map<T>::traverse (bool (*fn) (const void *, T *, void *), void *data) > -{ > - for (size_t i = 0; i < n_slots; ++i) > - if (slots[i] && !fn (slots[i], &values[i], data)) > - break; > -} > - > > struct pointer_map_t; > pointer_map_t *pointer_map_create (void); > diff --git a/gcc/symtab.c b/gcc/symtab.c > index 8158acc..40877ab 100644 > --- a/gcc/symtab.c > +++ b/gcc/symtab.c > @@ -874,7 +874,7 @@ DEBUG_FUNCTION void > verify_symtab (void) > { > symtab_node *node; > - pointer_map<symtab_node *> comdat_head_map; > + hash_map<tree, symtab_node *> comdat_head_map (251); > > FOR_EACH_SYMBOL (node) > { > @@ -884,7 +884,8 @@ verify_symtab (void) > symtab_node **entry, *s; > bool existed; > > - entry = comdat_head_map.insert (node->get_comdat_group (), > &existed); > + entry = &comdat_head_map.get_or_insert (node->get_comdat_group (), > + &existed); > if (!existed) > *entry = node; > else > diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c > index b452d9d..dc659c9 100644 > --- a/gcc/tree-ssa-strlen.c > +++ b/gcc/tree-ssa-strlen.c > @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see > #include "tree.h" > #include "stor-layout.h" > #include "hash-table.h" > +#include "hash-map.h" > #include "bitmap.h" > #include "basic-block.h" > #include "tree-ssa-alias.h" > @@ -134,31 +135,23 @@ struct decl_stridxlist_map > > /* stridxlist hashtable helpers. */ > > -struct stridxlist_hasher : typed_noop_remove <decl_stridxlist_map> > +struct stridxlist_hash_traits : default_hashmap_traits > { > - typedef decl_stridxlist_map value_type; > - typedef decl_stridxlist_map compare_type; > - static inline hashval_t hash (const value_type *); > - static inline bool equal (const value_type *, const compare_type *); > + static inline hashval_t hash (tree); > }; > > /* Hash a from tree in a decl_stridxlist_map. */ > > inline hashval_t > -stridxlist_hasher::hash (const value_type *item) > +stridxlist_hash_traits::hash (tree item) > { > - return DECL_UID (item->base.from); > -} > - > -inline bool > -stridxlist_hasher::equal (const value_type *v, const compare_type *c) > -{ > - return tree_map_base_eq (&v->base, &c->base); > + return DECL_UID (item); > } > > /* Hash table for mapping decls to a chained list of offset -> idx > mappings. */ > -static hash_table<stridxlist_hasher> *decl_to_stridxlist_htab; > +static hash_map<tree, stridxlist, stridxlist_hash_traits> > + *decl_to_stridxlist_htab; > > /* Obstack for struct stridxlist and struct decl_stridxlist_map. */ > static struct obstack stridx_obstack; > @@ -179,7 +172,6 @@ static int > get_addr_stridx (tree exp) > { > HOST_WIDE_INT off; > - struct decl_stridxlist_map ent, *e; > struct stridxlist *list; > tree base; > > @@ -190,12 +182,10 @@ get_addr_stridx (tree exp) > if (base == NULL || !DECL_P (base)) > return 0; > > - ent.base.from = base; > - e = decl_to_stridxlist_htab->find_with_hash (&ent, DECL_UID (base)); > - if (e == NULL) > + list = decl_to_stridxlist_htab->get (base); > + if (list == NULL) > return 0; > > - list = &e->list; > do > { > if (list->offset == off) > @@ -270,9 +260,6 @@ unshare_strinfo_vec (void) > static int * > addr_stridxptr (tree exp) > { > - decl_stridxlist_map **slot; > - struct decl_stridxlist_map ent; > - struct stridxlist *list; > HOST_WIDE_INT off; > > tree base = get_addr_base_and_unit_offset (exp, &off); > @@ -281,16 +268,16 @@ addr_stridxptr (tree exp) > > if (!decl_to_stridxlist_htab) > { > - decl_to_stridxlist_htab = new hash_table<stridxlist_hasher> (64); > + decl_to_stridxlist_htab > + = new hash_map<tree, stridxlist, stridxlist_hash_traits> (64); > gcc_obstack_init (&stridx_obstack); > } > - ent.base.from = base; > - slot = decl_to_stridxlist_htab->find_slot_with_hash (&ent, DECL_UID (base), > - INSERT); > - if (*slot) > + > + bool existed; > + stridxlist *list = &decl_to_stridxlist_htab->get_or_insert (base, > &existed); > + if (existed) > { > int i; > - list = &(*slot)->list; > for (i = 0; i < 16; i++) > { > if (list->offset == off) > @@ -303,14 +290,7 @@ addr_stridxptr (tree exp) > list->next = XOBNEW (&stridx_obstack, struct stridxlist); > list = list->next; > } > - else > - { > - struct decl_stridxlist_map *e > - = XOBNEW (&stridx_obstack, struct decl_stridxlist_map); > - e->base.from = base; > - *slot = e; > - list = &e->list; > - } > + > list->next = NULL; > list->offset = off; > list->idx = 0; > diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c > index 81d3085..5c928b4 100644 > --- a/gcc/tree-ssa-uncprop.c > +++ b/gcc/tree-ssa-uncprop.c > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see > #include "basic-block.h" > #include "function.h" > #include "hash-table.h" > +#include "hash-map.h" > #include "tree-ssa-alias.h" > #include "internal-fn.h" > #include "gimple-expr.h" > @@ -284,44 +285,38 @@ struct equiv_hash_elt > > /* Value to ssa name equivalence hashtable helpers. */ > > -struct val_ssa_equiv_hasher > +struct val_ssa_equiv_hash_traits : default_hashmap_traits > { > - typedef equiv_hash_elt value_type; > - typedef equiv_hash_elt compare_type; > - static inline hashval_t hash (const value_type *); > - static inline bool equal (const value_type *, const compare_type *); > - static inline void remove (value_type *); > + static inline hashval_t hash (tree); > + static inline bool equal_keys (tree, tree); > + template<typename T> static inline void remove (T &); > }; > > inline hashval_t > -val_ssa_equiv_hasher::hash (const value_type *p) > +val_ssa_equiv_hash_traits::hash (tree value) > { > - tree const value = p->value; > return iterative_hash_expr (value, 0); > } > > inline bool > -val_ssa_equiv_hasher::equal (const value_type *p1, const compare_type *p2) > +val_ssa_equiv_hash_traits::equal_keys (tree value1, tree value2) > { > - tree value1 = p1->value; > - tree value2 = p2->value; > - > return operand_equal_p (value1, value2, 0); > } > > /* Free an instance of equiv_hash_elt. */ > > +template<typename T> > inline void > -val_ssa_equiv_hasher::remove (value_type *elt) > +val_ssa_equiv_hash_traits::remove (T &elt) > { > - elt->equivalences.release (); > - free (elt); > + elt.m_value.release (); > } > > /* Global hash table implementing a mapping from invariant values > to a list of SSA_NAMEs which have the same value. We might be > able to reuse tree-vn for this code. */ > -static hash_table<val_ssa_equiv_hasher> *val_ssa_equiv; > +static hash_map<tree, vec<tree>, val_ssa_equiv_hash_traits> *val_ssa_equiv; > > static void uncprop_into_successor_phis (basic_block); > > @@ -330,16 +325,7 @@ static void uncprop_into_successor_phis (basic_block); > static void > remove_equivalence (tree value) > { > - struct equiv_hash_elt an_equiv_elt, *an_equiv_elt_p; > - equiv_hash_elt **slot; > - > - an_equiv_elt.value = value; > - an_equiv_elt.equivalences.create (0); > - > - slot = val_ssa_equiv->find_slot (&an_equiv_elt, NO_INSERT); > - > - an_equiv_elt_p = *slot; > - an_equiv_elt_p->equivalences.pop (); > + val_ssa_equiv->get (value)->pop (); > } > > /* Record EQUIVALENCE = VALUE into our hash table. */ > @@ -347,23 +333,7 @@ remove_equivalence (tree value) > static void > record_equiv (tree value, tree equivalence) > { > - equiv_hash_elt *an_equiv_elt_p; > - equiv_hash_elt **slot; > - > - an_equiv_elt_p = XNEW (struct equiv_hash_elt); > - an_equiv_elt_p->value = value; > - an_equiv_elt_p->equivalences.create (0); > - > - slot = val_ssa_equiv->find_slot (an_equiv_elt_p, INSERT); > - > - if (*slot == NULL) > - *slot = an_equiv_elt_p; > - else > - free (an_equiv_elt_p); > - > - an_equiv_elt_p = *slot; > - > - an_equiv_elt_p->equivalences.safe_push (equivalence); > + val_ssa_equiv->get_or_insert (value).safe_push (equivalence); > } > > class uncprop_dom_walker : public dom_walker > @@ -433,8 +403,6 @@ uncprop_into_successor_phis (basic_block bb) > gimple phi = gsi_stmt (gsi); > tree arg = PHI_ARG_DEF (phi, e->dest_idx); > tree res = PHI_RESULT (phi); > - equiv_hash_elt an_equiv_elt; > - equiv_hash_elt **slot; > > /* If the argument is not an invariant and can be potentially > coalesced with the result, then there's no point in > @@ -444,23 +412,17 @@ uncprop_into_successor_phis (basic_block bb) > continue; > > /* Lookup this argument's value in the hash table. */ > - an_equiv_elt.value = arg; > - an_equiv_elt.equivalences.create (0); > - slot = val_ssa_equiv->find_slot (&an_equiv_elt, NO_INSERT); > - > - if (slot) > + vec<tree> *equivalences = val_ssa_equiv->get (arg); > + if (equivalences) > { > - struct equiv_hash_elt *elt = *slot; > - int j; > - > /* Walk every equivalence with the same value. If we find > one that can potentially coalesce with the PHI rsult, > then replace the value in the argument with its equivalent > SSA_NAME. Use the most recent equivalence as hopefully > that results in shortest lifetimes. */ > - for (j = elt->equivalences.length () - 1; j >= 0; j--) > + for (int j = equivalences->length () - 1; j >= 0; j--) > { > - tree equiv = elt->equivalences[j]; > + tree equiv = (*equivalences)[j]; > > if (gimple_can_coalesce_p (equiv, res)) > { > @@ -578,7 +540,8 @@ pass_uncprop::execute (function *fun) > associate_equivalences_with_edges (); > > /* Create our global data structures. */ > - val_ssa_equiv = new hash_table<val_ssa_equiv_hasher> (1024); > + val_ssa_equiv > + = new hash_map<tree, vec<tree>, val_ssa_equiv_hash_traits> (1024); > > /* We're going to do a dominator walk, so ensure that we have > dominance information. */ > diff --git a/gcc/tree-streamer.c b/gcc/tree-streamer.c > index 517bf77..17f3045 100644 > --- a/gcc/tree-streamer.c > +++ b/gcc/tree-streamer.c > @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see > #include "tree-ssa-alias.h" > #include "internal-fn.h" > #include "gimple-expr.h" > +#include "hash-map.h" > #include "is-a.h" > #include "gimple.h" > #include "streamer-hooks.h" > @@ -134,13 +135,11 @@ streamer_tree_cache_insert_1 (struct > streamer_tree_cache_d *cache, > tree t, hashval_t hash, unsigned *ix_p, > bool insert_at_next_slot_p) > { > - unsigned *slot; > - unsigned ix; > bool existed_p; > > gcc_assert (t); > > - slot = cache->node_map->insert (t, &existed_p); > + unsigned int &ix = cache->node_map->get_or_insert (t, &existed_p); > if (!existed_p) > { > /* Determine the next slot to use in the cache. */ > @@ -148,14 +147,11 @@ streamer_tree_cache_insert_1 (struct > streamer_tree_cache_d *cache, > ix = cache->next_idx++; > else > ix = *ix_p; > - *slot = ix; > > streamer_tree_cache_add_to_node_array (cache, ix, t, hash); > } > else > { > - ix = *slot; > - > if (!insert_at_next_slot_p && ix != *ix_p) > { > /* If the caller wants to insert T at a specific slot > @@ -163,7 +159,6 @@ streamer_tree_cache_insert_1 (struct > streamer_tree_cache_d *cache, > the requested location slot. */ > ix = *ix_p; > streamer_tree_cache_add_to_node_array (cache, ix, t, hash); > - *slot = ix; > } > } > > @@ -231,7 +226,7 @@ streamer_tree_cache_lookup (struct streamer_tree_cache_d > *cache, tree t, > > gcc_assert (t); > > - slot = cache->node_map->contains (t); > + slot = cache->node_map->get (t); > if (slot == NULL) > { > retval = false; > @@ -332,7 +327,7 @@ streamer_tree_cache_create (bool with_hashes, bool > with_map, bool with_vec) > cache = XCNEW (struct streamer_tree_cache_d); > > if (with_map) > - cache->node_map = new pointer_map<unsigned>; > + cache->node_map = new hash_map<tree, unsigned> (251); > cache->next_idx = 0; > if (with_vec) > cache->nodes.create (165); > @@ -356,8 +351,8 @@ streamer_tree_cache_delete (struct streamer_tree_cache_d > *c) > if (c == NULL) > return; > > - if (c->node_map) > - delete c->node_map; > + delete c->node_map; > + c->node_map = NULL; > c->nodes.release (); > c->hashes.release (); > free (c); > diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h > index 20dbba0..ddd366a 100644 > --- a/gcc/tree-streamer.h > +++ b/gcc/tree-streamer.h > @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see > > #include "streamer-hooks.h" > #include "lto-streamer.h" > +#include "hash-map.h" > > /* Cache of pickled nodes. Used to avoid writing the same node more > than once. The first time a tree node is streamed out, it is > @@ -46,7 +47,7 @@ along with GCC; see the file COPYING3. If not see > struct streamer_tree_cache_d > { > /* The mapping between tree nodes and slots into the nodes array. */ > - pointer_map<unsigned> *node_map; > + hash_map<tree, unsigned> *node_map; > > /* The nodes pickled so far. */ > vec<tree> nodes; > -- > 2.0.0 >