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


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

Re: [PATCH 3/3] add hash_map class



On 06/24/2014 02:40 PM, Trevor Saunders wrote:
On Tue, Jun 24, 2014 at 02:29:53PM +0200, Martin LiÅka wrote:
On 06/20/2014 12:52 PM, tsaunders@mozilla.com wrote:
From: Trevor Saunders <tsaunders@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.
Hello Trev,
    I like your changes! One small question about pointer_set, which is unable of deletion of items. Do you plan to migrate and simplify hash_map to be a replacement for pointer_set?
I'm not sure I follow the question.  I imagine that hash_map will
largely stay as it is, other than perhaps some const correctness stuff,
and supporting element removal at some point.  Supporting element
removal should be trivial since I'm just wrapping hash_table which
already supports it, but I didn't want to add it until there was code
testing it.  As you see in the patch I removed pointer_map so its
already a replacement for that functionality.  As for pointer_set since
its a set not a map hash_table would seem closer to me.
Understand, yeah, I was asking if we plan to add element removal also for (pointer_)set? I consider such functionality useful, but it looks  not related to your patch. If I understand correctly, you are not planning to use hash_* as wrapping data structure for set.

Martin


Trev


Thanks,
Martin

bootstrapped + regtested without regression on x86_64-unknown-linux-gnu, ok?

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;


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