public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 2/5] remove the remaining uses of if_marked
  2014-11-13  5:57 [PATCH 1/5] add an alternative to if_marked using hash_table tsaunders
  2014-11-13  5:57 ` [PATCH 5/5] use vec in lto_tree_ref_table tsaunders
  2014-11-13  5:57 ` [PATCH 3/5] fix hash_table when empty elements are not 0 tsaunders
@ 2014-11-13  5:57 ` tsaunders
  2014-11-13  6:52   ` Marek Polacek
  2014-11-14  0:49   ` Jeff Law
  2014-11-13  6:14 ` [PATCH 4/5] remove param$N_is usage tsaunders
  2014-11-14  0:37 ` [PATCH 1/5] add an alternative to if_marked using hash_table Jeff Law
  4 siblings, 2 replies; 16+ messages in thread
From: tsaunders @ 2014-11-13  5:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

$subject.

bootstrapped + regtested x86_64-unknown-linux-gnu, ok?

Trev


ada/

	* gcc-interface/decl.c, gcc-interface/utils.c: replace htab with
	hash_table.

cp/

	* cp-objcp-common.c: Use hash_table instead of htab.

gcc/

	* config/i386/i386.c, function.c, trans-mem.c, tree-core.h,
	tree.c, tree.h, ubsan.c, varasm.c: Use hash_table instead of htab.



diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 2ed68d4..c133a22 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -128,8 +128,35 @@ typedef struct variant_desc_d {
 
 
 /* A hash table used to cache the result of annotate_value.  */
-static GTY ((if_marked ("tree_int_map_marked_p"),
-	     param_is (struct tree_int_map))) htab_t annotate_value_cache;
+
+struct value_annotation_hasher : ggc_cache_hasher<tree_int_map *>
+{
+  static inline hashval_t
+  hash (tree_int_map *m)
+  {
+    return htab_hash_pointer (m->base.from);
+  }
+
+  static inline bool
+  equal (tree_int_map *a, tree_int_map *b)
+  {
+    return a->base.from == b->base.from;
+  }
+
+  static void
+  handle_cache_entry (tree_int_map *&m)
+  {
+    extern void gt_ggc_mx (tree_int_map *&);
+    if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
+      return;
+    else if (ggc_marked_p (m->base.from))
+      gt_ggc_mx (m);
+    else
+      m = static_cast<tree_int_map *> (HTAB_DELETED_ENTRY);
+  }
+};
+
+static GTY ((cache)) hash_table<value_annotation_hasher> *annotate_value_cache;
 
 static bool allocatable_size_p (tree, bool);
 static void prepend_one_attribute (struct attrib **,
@@ -7362,7 +7389,7 @@ annotate_value (tree gnu_size)
       struct tree_int_map *e;
 
       in.base.from = gnu_size;
-      e = (struct tree_int_map *) htab_find (annotate_value_cache, &in);
+      e = annotate_value_cache->find (&in);
 
       if (e)
 	return (Node_Ref_Or_Val) e->to;
@@ -7491,8 +7518,7 @@ annotate_value (tree gnu_size)
 	 look up, so we have to search again.  Allocating and inserting an
 	 entry at that point would be an alternative, but then we'd better
 	 discard the entry if we decided not to cache it.  */
-      h = (struct tree_int_map **)
-	    htab_find_slot (annotate_value_cache, &in, INSERT);
+      h = annotate_value_cache->find_slot (&in, INSERT);
       gcc_assert (!*h);
       *h = ggc_alloc<tree_int_map> ();
       (*h)->base.from = gnu_size;
@@ -8840,8 +8866,7 @@ void
 init_gnat_decl (void)
 {
   /* Initialize the cache of annotated values.  */
-  annotate_value_cache
-    = htab_create_ggc (512, tree_int_map_hash, tree_int_map_eq, 0);
+  annotate_value_cache = hash_table<value_annotation_hasher>::create_ggc (512);
 }
 
 /* Destroy data structures of the decl.c module.  */
@@ -8850,7 +8875,7 @@ void
 destroy_gnat_decl (void)
 {
   /* Destroy the cache of annotated values.  */
-  htab_delete (annotate_value_cache);
+  annotate_value_cache->empty ();
   annotate_value_cache = NULL;
 }
 
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 4d35060..32f0012 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -233,20 +233,23 @@ static GTY(()) vec<tree, va_gc> *global_renaming_pointers;
 /* A chain of unused BLOCK nodes. */
 static GTY((deletable)) tree free_block_chain;
 
-static int pad_type_hash_marked_p (const void *p);
-static hashval_t pad_type_hash_hash (const void *p);
-static int pad_type_hash_eq (const void *p1, const void *p2);
-
 /* A hash table of padded types.  It is modelled on the generic type
    hash table in tree.c, which must thus be used as a reference.  */
-struct GTY(()) pad_type_hash {
+
+struct GTY((for_user)) pad_type_hash {
   unsigned long hash;
   tree type;
 };
 
-static GTY ((if_marked ("pad_type_hash_marked_p"),
-	     param_is (struct pad_type_hash)))
-  htab_t pad_type_hash_table;
+struct pad_type_hasher : ggc_cache_hasher<pad_type_hash *>
+{
+  static inline hashval_t hash (pad_type_hash *t) { return t->hash; }
+  static bool equal (pad_type_hash *a, pad_type_hash *b);
+  static void handle_cache_entry (pad_type_hash *&);
+};
+
+static GTY ((cache))
+  hash_table<pad_type_hasher> *pad_type_hash_table;
 
 static tree merge_sizes (tree, tree, tree, bool, bool);
 static tree compute_related_constant (tree, tree);
@@ -294,8 +297,7 @@ init_gnat_utils (void)
   dummy_node_table = ggc_cleared_vec_alloc<tree> (max_gnat_nodes);
 
   /* Initialize the hash table of padded types.  */
-  pad_type_hash_table
-    = htab_create_ggc (512, pad_type_hash_hash, pad_type_hash_eq, 0);
+  pad_type_hash_table = hash_table<pad_type_hasher>::create_ggc (512);
 }
 
 /* Destroy data structures of the utils.c module.  */
@@ -312,7 +314,7 @@ destroy_gnat_utils (void)
   dummy_node_table = NULL;
 
   /* Destroy the hash table of padded types.  */
-  htab_delete (pad_type_hash_table);
+  pad_type_hash_table->empty ();
   pad_type_hash_table = NULL;
 
   /* Invalidate the global renaming pointers.   */
@@ -1155,29 +1157,23 @@ make_type_from_size (tree type, tree size_tree, bool for_biased)
 
 /* See if the data pointed to by the hash table slot is marked.  */
 
-static int
-pad_type_hash_marked_p (const void *p)
-{
-  const_tree const type = ((const struct pad_type_hash *) p)->type;
-
-  return ggc_marked_p (type);
-}
-
-/* Return the cached hash value.  */
-
-static hashval_t
-pad_type_hash_hash (const void *p)
+void
+pad_type_hasher::handle_cache_entry (pad_type_hash *&t)
 {
-  return ((const struct pad_type_hash *) p)->hash;
+  extern void gt_ggc_mx (pad_type_hash *&);
+  if (t == HTAB_EMPTY_ENTRY || t == HTAB_DELETED_ENTRY)
+    return;
+  else if (ggc_marked_p (t->type))
+    gt_ggc_mx (t);
+  else
+    t = static_cast<pad_type_hash *> (HTAB_DELETED_ENTRY);
 }
 
-/* Return 1 iff the padded types are equivalent.  */
+/* Return true iff the padded types are equivalent.  */
 
-static int
-pad_type_hash_eq (const void *p1, const void *p2)
+bool
+pad_type_hasher::equal (pad_type_hash *t1, pad_type_hash *t2)
 {
-  const struct pad_type_hash *const t1 = (const struct pad_type_hash *) p1;
-  const struct pad_type_hash *const t2 = (const struct pad_type_hash *) p2;
   tree type1, type2;
 
   if (t1->hash != t2->hash)
@@ -1204,7 +1200,6 @@ lookup_and_insert_pad_type (tree type)
 {
   hashval_t hashcode;
   struct pad_type_hash in, *h;
-  void **loc;
 
   hashcode
     = iterative_hash_object (TYPE_HASH (TREE_TYPE (TYPE_FIELDS (type))), 0);
@@ -1214,16 +1209,14 @@ lookup_and_insert_pad_type (tree type)
 
   in.hash = hashcode;
   in.type = type;
-  h = (struct pad_type_hash *)
-	htab_find_with_hash (pad_type_hash_table, &in, hashcode);
+  h = pad_type_hash_table->find_with_hash (&in, hashcode);
   if (h)
     return h->type;
 
   h = ggc_alloc<pad_type_hash> ();
   h->hash = hashcode;
   h->type = type;
-  loc = htab_find_slot_with_hash (pad_type_hash_table, h, hashcode, INSERT);
-  *loc = (void *)h;
+  *pad_type_hash_table->find_slot_with_hash (h, hashcode, INSERT) = h;
   return NULL_TREE;
 }
 
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b70c56c..227509a 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14032,14 +14032,34 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
    to symbol DECL if BEIMPORT is true.  Otherwise create or return the
    unique refptr-DECL symbol corresponding to symbol DECL.  */
 
-static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
-  htab_t dllimport_map;
+struct dllimport_hasher : ggc_cache_hasher<tree_map *>
+{
+  static inline hashval_t hash (tree_map *m) { return m->hash; }
+  static inline bool
+  equal (tree_map *a, tree_map *b)
+  {
+    return a->base.from == b->base.from;
+  }
+
+  static void
+    handle_cache_entry (tree_map *&m)
+      {
+	extern void gt_ggc_mx (tree_map *&);
+	if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
+	  return;
+	else if (ggc_marked_p (m->base.from))
+	  gt_ggc_mx (m);
+	else
+	  m = static_cast<tree_map *> (HTAB_DELETED_ENTRY);
+      }
+};
+
+static GTY((cache)) hash_table<dllimport_hasher> *dllimport_map;
 
 static tree
 get_dllimport_decl (tree decl, bool beimport)
 {
   struct tree_map *h, in;
-  void **loc;
   const char *name;
   const char *prefix;
   size_t namelen, prefixlen;
@@ -14048,12 +14068,12 @@ get_dllimport_decl (tree decl, bool beimport)
   rtx rtl;
 
   if (!dllimport_map)
-    dllimport_map = htab_create_ggc (512, tree_map_hash, tree_map_eq, 0);
+    dllimport_map = hash_table<dllimport_hasher>::create_ggc (512);
 
   in.hash = htab_hash_pointer (decl);
   in.base.from = decl;
-  loc = htab_find_slot_with_hash (dllimport_map, &in, in.hash, INSERT);
-  h = (struct tree_map *) *loc;
+  tree_map **loc = dllimport_map->find_slot_with_hash (&in, in.hash, INSERT);
+  h = *loc;
   if (h)
     return h->to;
 
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 12df4c2..9457af2 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -178,8 +178,8 @@ has_c_linkage (const_tree decl)
   return DECL_EXTERN_C_P (decl);
 }
 
-static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_map)))
-     htab_t shadowed_var_for_decl;
+static GTY ((cache))
+     hash_table<tree_decl_map_cache_hasher> *shadowed_var_for_decl;
 
 /* Lookup a shadowed var for FROM, and return it if we find one.  */
 
@@ -189,8 +189,7 @@ decl_shadowed_for_var_lookup (tree from)
   struct tree_decl_map *h, in;
   in.base.from = from;
 
-  h = (struct tree_decl_map *)
-      htab_find_with_hash (shadowed_var_for_decl, &in, DECL_UID (from));
+  h = shadowed_var_for_decl->find_with_hash (&in, DECL_UID (from));
   if (h)
     return h->to;
   return NULL_TREE;
@@ -202,21 +201,18 @@ void
 decl_shadowed_for_var_insert (tree from, tree to)
 {
   struct tree_decl_map *h;
-  void **loc;
 
   h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
-  loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, DECL_UID (from),
-				  INSERT);
-  *(struct tree_decl_map **) loc = h;
+  *shadowed_var_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
 }
 
 void
 init_shadowed_var_for_decl (void)
 {
-  shadowed_var_for_decl = htab_create_ggc (512, tree_decl_map_hash,
-					   tree_decl_map_eq, 0);
+  shadowed_var_for_decl
+    = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
 }
 
 /* Return true if stmt can fall through.  Used by block_may_fallthru
diff --git a/gcc/function.c b/gcc/function.c
index ef98091..f597b9e 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -116,10 +116,17 @@ struct machine_function * (*init_machine_status) (void);
 struct function *cfun = 0;
 
 /* These hashes record the prologue and epilogue insns.  */
-static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
-  htab_t prologue_insn_hash;
-static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
-  htab_t epilogue_insn_hash;
+
+struct insn_cache_hasher : ggc_cache_hasher<rtx>
+{
+  static hashval_t hash (rtx x) { return htab_hash_pointer (x); }
+  static bool equal (rtx a, rtx b) { return a == b; }
+};
+
+static GTY((cache))
+  hash_table<insn_cache_hasher> *prologue_insn_hash;
+static GTY((cache))
+  hash_table<insn_cache_hasher> *epilogue_insn_hash;
 \f
 
 hash_table<used_type_hasher> *types_used_by_vars_hash = NULL;
@@ -136,8 +143,9 @@ static tree *get_block_vector (tree, int *);
 extern tree debug_find_var_in_block_tree (tree, tree);
 /* We always define `record_insns' even if it's not used so that we
    can always export `prologue_epilogue_contains'.  */
-static void record_insns (rtx_insn *, rtx, htab_t *) ATTRIBUTE_UNUSED;
-static bool contains (const_rtx, htab_t);
+static void record_insns (rtx_insn *, rtx, hash_table<insn_cache_hasher> **)
+     ATTRIBUTE_UNUSED;
+static bool contains (const_rtx, hash_table<insn_cache_hasher> *);
 static void prepare_function_start (void);
 static void do_clobber_return_reg (rtx, void *);
 static void do_use_return_reg (rtx, void *);
@@ -5532,18 +5540,17 @@ get_arg_pointer_save_area (void)
    for the first time.  */
 
 static void
-record_insns (rtx_insn *insns, rtx end, htab_t *hashp)
+record_insns (rtx_insn *insns, rtx end, hash_table<insn_cache_hasher> **hashp)
 {
   rtx_insn *tmp;
-  htab_t hash = *hashp;
+  hash_table<insn_cache_hasher> *hash = *hashp;
 
   if (hash == NULL)
-    *hashp = hash
-      = htab_create_ggc (17, htab_hash_pointer, htab_eq_pointer, NULL);
+    *hashp = hash = hash_table<insn_cache_hasher>::create_ggc (17);
 
   for (tmp = insns; tmp != end; tmp = NEXT_INSN (tmp))
     {
-      void **slot = htab_find_slot (hash, tmp, INSERT);
+      rtx *slot = hash->find_slot (tmp, INSERT);
       gcc_assert (*slot == NULL);
       *slot = tmp;
     }
@@ -5556,18 +5563,18 @@ record_insns (rtx_insn *insns, rtx end, htab_t *hashp)
 void
 maybe_copy_prologue_epilogue_insn (rtx insn, rtx copy)
 {
-  htab_t hash;
-  void **slot;
+  hash_table<insn_cache_hasher> *hash;
+  rtx *slot;
 
   hash = epilogue_insn_hash;
-  if (!hash || !htab_find (hash, insn))
+  if (!hash || !hash->find (insn))
     {
       hash = prologue_insn_hash;
-      if (!hash || !htab_find (hash, insn))
+      if (!hash || !hash->find (insn))
 	return;
     }
 
-  slot = htab_find_slot (hash, copy, INSERT);
+  slot = hash->find_slot (copy, INSERT);
   gcc_assert (*slot == NULL);
   *slot = copy;
 }
@@ -5576,7 +5583,7 @@ maybe_copy_prologue_epilogue_insn (rtx insn, rtx copy)
    we can be running after reorg, SEQUENCE rtl is possible.  */
 
 static bool
-contains (const_rtx insn, htab_t hash)
+contains (const_rtx insn, hash_table<insn_cache_hasher> *hash)
 {
   if (hash == NULL)
     return false;
@@ -5586,12 +5593,12 @@ contains (const_rtx insn, htab_t hash)
       rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
       int i;
       for (i = seq->len () - 1; i >= 0; i--)
-	if (htab_find (hash, seq->element (i)))
+	if (hash->find (seq->element (i)))
 	  return true;
       return false;
     }
 
-  return htab_find (hash, insn) != NULL;
+  return hash->find (const_cast<rtx> (insn)) != NULL;
 }
 
 int
@@ -6203,7 +6210,7 @@ reposition_prologue_and_epilogue_notes (void)
      non-null is a signal that it is non-empty.  */
   if (prologue_insn_hash != NULL)
     {
-      size_t len = htab_elements (prologue_insn_hash);
+      size_t len = prologue_insn_hash->elements ();
       rtx_insn *insn, *last = NULL, *note = NULL;
 
       /* Scan from the beginning until we reach the last prologue insn.  */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 9899e7b..766b14e 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -472,8 +472,29 @@ build_tm_abort_call (location_t loc, bool is_outer)
 /* Map for aribtrary function replacement under TM, as created
    by the tm_wrap attribute.  */
 
-static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
-     htab_t tm_wrap_map;
+struct tm_wrapper_hasher : ggc_cache_hasher<tree_map *>
+{
+  static inline hashval_t hash (tree_map *m) { return m->hash; }
+  static inline bool
+  equal (tree_map *a, tree_map *b)
+  {
+    return a->base.from == b->base.from;
+  }
+
+  static void
+  handle_cache_entry (tree_map *&m)
+    {
+      extern void gt_ggc_mx (tree_map *&);
+      if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
+	return;
+      else if (ggc_marked_p (m->base.from))
+	gt_ggc_mx (m);
+      else
+	m = static_cast<tree_map *> (HTAB_DELETED_ENTRY);
+    }
+};
+
+static GTY((cache)) hash_table<tm_wrapper_hasher> *tm_wrap_map;
 
 void
 record_tm_replacement (tree from, tree to)
@@ -489,15 +510,14 @@ record_tm_replacement (tree from, tree to)
   DECL_UNINLINABLE (from) = 1;
 
   if (tm_wrap_map == NULL)
-    tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
+    tm_wrap_map = hash_table<tm_wrapper_hasher>::create_ggc (32);
 
   h = ggc_alloc<tree_map> ();
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
 
-  slot = (struct tree_map **)
-    htab_find_slot_with_hash (tm_wrap_map, h, h->hash, INSERT);
+  slot = tm_wrap_map->find_slot_with_hash (h, h->hash, INSERT);
   *slot = h;
 }
 
@@ -512,7 +532,7 @@ find_tm_replacement_function (tree fndecl)
 
       in.base.from = fndecl;
       in.hash = htab_hash_pointer (fndecl);
-      h = (struct tree_map *) htab_find_with_hash (tm_wrap_map, &in, in.hash);
+      h = tm_wrap_map->find_with_hash (&in, in.hash);
       if (h)
 	return h->to;
     }
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 58bdfff..3cc5470 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1770,26 +1770,26 @@ struct GTY(()) tree_map_base {
 
 /* Map from a tree to another tree.  */
 
-struct GTY(()) tree_map {
+struct GTY((for_user)) tree_map {
   struct tree_map_base base;
   unsigned int hash;
   tree to;
 };
 
 /* Map from a decl tree to another tree.  */
-struct GTY(()) tree_decl_map {
+struct GTY((for_user)) tree_decl_map {
   struct tree_map_base base;
   tree to;
 };
 
 /* Map from a tree to an int.  */
-struct GTY(()) tree_int_map {
+struct GTY((for_user)) tree_int_map {
   struct tree_map_base base;
   unsigned int to;
 };
 
 /* Map from a decl tree to a tree vector.  */
-struct GTY(()) tree_vec_map {
+struct GTY((for_user)) tree_vec_map {
   struct tree_map_base base;
   vec<tree, va_gc> *to;
 };
diff --git a/gcc/tree.c b/gcc/tree.c
index 5fb44bc..2038e8c 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -185,7 +185,7 @@ static GTY(()) int next_debug_decl_uid;
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
 
-struct GTY(()) type_hash {
+struct GTY((for_user)) type_hash {
   unsigned long hash;
   tree type;
 };
@@ -193,6 +193,24 @@ struct GTY(()) type_hash {
 /* Initial size of the hash table (rounded to next prime).  */
 #define TYPE_HASH_INITIAL_SIZE 1000
 
+struct type_cache_hasher : ggc_cache_hasher<type_hash *>
+{
+  static hashval_t hash (type_hash *t) { return t->hash; }
+  static bool equal (type_hash *a, type_hash *b);
+
+  static void
+  handle_cache_entry (type_hash *&t)
+  {
+    extern void gt_ggc_mx (type_hash *&);
+    if (t == HTAB_DELETED_ENTRY || t == HTAB_EMPTY_ENTRY)
+      return;
+    else if (ggc_marked_p (t->type))
+      gt_ggc_mx (t);
+    else
+      t = static_cast<type_hash *> (HTAB_DELETED_ENTRY);
+  }
+};
+
 /* Now here is the hash table.  When recording a type, it is added to
    the slot whose index is the hash code.  Note that the hash table is
    used for several kinds of types (function types, array types and
@@ -200,8 +218,7 @@ struct GTY(()) type_hash {
    same table, they are completely independent, and the hash code is
    computed differently for each of these.  */
 
-static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
-     htab_t type_hash_table;
+static GTY ((cache)) hash_table<type_cache_hasher> *type_hash_table;
 
 /* Hash table and temporary node for larger integer const values.  */
 static GTY (()) tree int_cst_node;
@@ -233,22 +250,42 @@ static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
 /* General tree->tree mapping  structure for use in hash tables.  */
 
 
-static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_map)))
-     htab_t debug_expr_for_decl;
+static GTY ((cache))
+     hash_table<tree_decl_map_cache_hasher> *debug_expr_for_decl;
 
-static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_map)))
-     htab_t value_expr_for_decl;
+static GTY ((cache))
+     hash_table<tree_decl_map_cache_hasher> *value_expr_for_decl;
+
+     struct tree_vec_map_cache_hasher : ggc_cache_hasher<tree_vec_map *>
+{
+  static hashval_t hash (tree_vec_map *m) { return DECL_UID (m->base.from); }
+
+  static bool
+  equal (tree_vec_map *a, tree_vec_map *b)
+  {
+    return a->base.from == b->base.from;
+  }
+
+  static void
+  handle_cache_entry (tree_vec_map *&m)
+  {
+    extern void gt_ggc_mx (tree_vec_map *&);
+    if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
+      return;
+    else if (ggc_marked_p (m->base.from))
+      gt_ggc_mx (m);
+    else
+      m = static_cast<tree_vec_map *> (HTAB_DELETED_ENTRY);
+  }
+};
 
-static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)))
-     htab_t debug_args_for_decl;
+static GTY ((cache))
+     hash_table<tree_vec_map_cache_hasher> *debug_args_for_decl;
 
 static void set_type_quals (tree, int);
-static int type_hash_eq (const void *, const void *);
-static hashval_t type_hash_hash (const void *);
 static void print_type_hash_statistics (void);
 static void print_debug_expr_statistics (void);
 static void print_value_expr_statistics (void);
-static int type_hash_marked_p (const void *);
 static void type_hash_list (const_tree, inchash::hash &);
 static void attribute_hash_list (const_tree, inchash::hash &);
 
@@ -584,14 +621,14 @@ void
 init_ttree (void)
 {
   /* Initialize the hash table of types.  */
-  type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
-				     type_hash_eq, 0);
+  type_hash_table
+    = hash_table<type_cache_hasher>::create_ggc (TYPE_HASH_INITIAL_SIZE);
 
-  debug_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
-					 tree_decl_map_eq, 0);
+  debug_expr_for_decl
+    = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
 
-  value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
-					 tree_decl_map_eq, 0);
+  value_expr_for_decl
+    = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
 
   int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
 
@@ -6545,9 +6582,9 @@ static void
 print_debug_expr_statistics (void)
 {
   fprintf (stderr, "DECL_DEBUG_EXPR  hash: size %ld, %ld elements, %f collisions\n",
-	   (long) htab_size (debug_expr_for_decl),
-	   (long) htab_elements (debug_expr_for_decl),
-	   htab_collisions (debug_expr_for_decl));
+	   (long) debug_expr_for_decl->size (),
+	   (long) debug_expr_for_decl->elements (),
+	   debug_expr_for_decl->collisions ());
 }
 
 /* Print out the statistics for the DECL_VALUE_EXPR hash table.  */
@@ -6556,9 +6593,9 @@ static void
 print_value_expr_statistics (void)
 {
   fprintf (stderr, "DECL_VALUE_EXPR  hash: size %ld, %ld elements, %f collisions\n",
-	   (long) htab_size (value_expr_for_decl),
-	   (long) htab_elements (value_expr_for_decl),
-	   htab_collisions (value_expr_for_decl));
+	   (long) value_expr_for_decl->size (),
+	   (long) value_expr_for_decl->elements (),
+	   value_expr_for_decl->collisions ());
 }
 
 /* Lookup a debug expression for FROM, and return it if we find one.  */
@@ -6569,8 +6606,7 @@ decl_debug_expr_lookup (tree from)
   struct tree_decl_map *h, in;
   in.base.from = from;
 
-  h = (struct tree_decl_map *)
-      htab_find_with_hash (debug_expr_for_decl, &in, DECL_UID (from));
+  h = debug_expr_for_decl->find_with_hash (&in, DECL_UID (from));
   if (h)
     return h->to;
   return NULL_TREE;
@@ -6582,14 +6618,11 @@ void
 decl_debug_expr_insert (tree from, tree to)
 {
   struct tree_decl_map *h;
-  void **loc;
 
   h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
-  loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
-				  INSERT);
-  *(struct tree_decl_map **) loc = h;
+  *debug_expr_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
 }
 
 /* Lookup a value expression for FROM, and return it if we find one.  */
@@ -6600,8 +6633,7 @@ decl_value_expr_lookup (tree from)
   struct tree_decl_map *h, in;
   in.base.from = from;
 
-  h = (struct tree_decl_map *)
-      htab_find_with_hash (value_expr_for_decl, &in, DECL_UID (from));
+  h = value_expr_for_decl->find_with_hash (&in, DECL_UID (from));
   if (h)
     return h->to;
   return NULL_TREE;
@@ -6613,14 +6645,11 @@ void
 decl_value_expr_insert (tree from, tree to)
 {
   struct tree_decl_map *h;
-  void **loc;
 
   h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
-  loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
-				  INSERT);
-  *(struct tree_decl_map **) loc = h;
+  *value_expr_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
 }
 
 /* Lookup a vector of debug arguments for FROM, and return it if we
@@ -6635,8 +6664,7 @@ decl_debug_args_lookup (tree from)
     return NULL;
   gcc_checking_assert (debug_args_for_decl != NULL);
   in.base.from = from;
-  h = (struct tree_vec_map *)
-      htab_find_with_hash (debug_args_for_decl, &in, DECL_UID (from));
+  h = debug_args_for_decl->find_with_hash (&in, DECL_UID (from));
   if (h)
     return &h->to;
   return NULL;
@@ -6649,19 +6677,17 @@ vec<tree, va_gc> **
 decl_debug_args_insert (tree from)
 {
   struct tree_vec_map *h;
-  void **loc;
+  tree_vec_map **loc;
 
   if (DECL_HAS_DEBUG_ARGS_P (from))
     return decl_debug_args_lookup (from);
   if (debug_args_for_decl == NULL)
-    debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
-					   tree_vec_map_eq, 0);
+    debug_args_for_decl = hash_table<tree_vec_map_cache_hasher>::create_ggc (64);
   h = ggc_alloc<tree_vec_map> ();
   h->base.from = from;
   h->to = NULL;
-  loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
-				  INSERT);
-  *(struct tree_vec_map **) loc = h;
+  loc = debug_args_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT);
+  *loc = h;
   DECL_HAS_DEBUG_ARGS_P (from) = 1;
   return &h->to;
 }
@@ -6687,12 +6713,9 @@ type_hash_list (const_tree list, inchash::hash &hstate)
 
 /* Returns true iff the types are equivalent.  */
 
-static int
-type_hash_eq (const void *va, const void *vb)
+bool
+type_cache_hasher::equal (type_hash *a, type_hash *b)
 {
-  const struct type_hash *const a = (const struct type_hash *) va,
-    *const b = (const struct type_hash *) vb;
-
   /* First test the things that are the same for all types.  */
   if (a->hash != b->hash
       || TREE_CODE (a->type) != TREE_CODE (b->type)
@@ -6799,14 +6822,6 @@ type_hash_eq (const void *va, const void *vb)
   return 1;
 }
 
-/* Return the cached hash value.  */
-
-static hashval_t
-type_hash_hash (const void *item)
-{
-  return ((const struct type_hash *) item)->hash;
-}
-
 /* Given TYPE, and HASHCODE its hash code, return the canonical
    object for an identical type if one already exists.
    Otherwise, return TYPE, and record it as the canonical object.
@@ -6820,7 +6835,7 @@ tree
 type_hash_canon (unsigned int hashcode, tree type)
 {
   type_hash in;
-  void **loc;
+  type_hash **loc;
 
   /* The hash table only contains main variants, so ensure that's what we're
      being passed.  */
@@ -6833,7 +6848,7 @@ type_hash_canon (unsigned int hashcode, tree type)
   in.hash = hashcode;
   in.type = type;
 
-  loc = htab_find_slot_with_hash (type_hash_table, &in, hashcode, INSERT);
+  loc = type_hash_table->find_slot_with_hash (&in, hashcode, INSERT);
   if (*loc)
     {
       tree t1 = ((type_hash *) *loc)->type;
@@ -6853,31 +6868,19 @@ type_hash_canon (unsigned int hashcode, tree type)
       h = ggc_alloc<type_hash> ();
       h->hash = hashcode;
       h->type = type;
-      *loc = (void *)h;
+      *loc = h;
 
       return type;
     }
 }
 
-/* See if the data pointed to by the type hash table is marked.  We consider
-   it marked if the type is marked or if a debug type number or symbol
-   table entry has been made for the type.  */
-
-static int
-type_hash_marked_p (const void *p)
-{
-  const_tree const type = ((const struct type_hash *) p)->type;
-
-  return ggc_marked_p (type);
-}
-
 static void
 print_type_hash_statistics (void)
 {
   fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n",
-	   (long) htab_size (type_hash_table),
-	   (long) htab_elements (type_hash_table),
-	   htab_collisions (type_hash_table));
+	   (long) type_hash_table->size (),
+	   (long) type_hash_table->elements (),
+	   type_hash_table->collisions ());
 }
 
 /* Compute a hash code for a list of attributes (chain of TREE_LIST nodes
diff --git a/gcc/tree.h b/gcc/tree.h
index 0577d51..9875a50 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4389,6 +4389,28 @@ extern unsigned int tree_map_hash (const void *);
 extern unsigned int tree_decl_map_hash (const void *);
 #define tree_decl_map_marked_p tree_map_base_marked_p
 
+struct tree_decl_map_cache_hasher : ggc_cache_hasher<tree_decl_map *>
+{
+  static hashval_t hash (tree_decl_map *m) { return tree_decl_map_hash (m); }
+  static bool
+  equal (tree_decl_map *a, tree_decl_map *b)
+  {
+    return tree_decl_map_eq (a, b);
+  }
+
+  static void
+  handle_cache_entry (tree_decl_map *&m)
+  {
+    extern void gt_ggc_mx (tree_decl_map *&);
+    if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
+      return;
+    else if (ggc_marked_p (m->base.from))
+      gt_ggc_mx (m);
+    else
+      m = static_cast<tree_decl_map *> (HTAB_DELETED_ENTRY);
+  }
+};
+
 #define tree_int_map_eq tree_map_base_eq
 #define tree_int_map_hash tree_map_base_hash
 #define tree_int_map_marked_p tree_map_base_marked_p
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index 41cf546..98f49ef 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -70,24 +70,40 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Map from a tree to a VAR_DECL tree.  */
 
-struct GTY(()) tree_type_map {
+struct GTY((for_user)) tree_type_map {
   struct tree_map_base type;
   tree decl;
 };
 
-#define tree_type_map_eq tree_map_base_eq
-#define tree_type_map_marked_p tree_map_base_marked_p
-
-/* Hash from a tree in a tree_type_map.  */
-
-unsigned int
-tree_type_map_hash (const void *item)
+struct tree_type_map_cache_hasher : ggc_cache_hasher<tree_type_map *>
 {
-  return TYPE_UID (((const struct tree_type_map *)item)->type.from);
-}
+  static inline hashval_t
+  hash (tree_type_map *t)
+  {
+    return TYPE_UID (t->type.from);
+  }
+
+  static inline bool
+  equal (tree_type_map *a, tree_type_map *b)
+  {
+    return a->type.from == b->type.from;
+  }
+
+  static void
+    handle_cache_entry (tree_type_map *&m)
+      {
+	extern void gt_ggc_mx (tree_type_map *&);
+	if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
+	  return;
+	else if (ggc_marked_p (m->type.from))
+	  gt_ggc_mx (m);
+	else
+	  m = static_cast<tree_type_map *> (HTAB_DELETED_ENTRY);
+      }
+};
 
-static GTY ((if_marked ("tree_type_map_marked_p"), param_is (struct tree_type_map)))
-     htab_t decl_tree_for_type;
+static GTY ((cache))
+     hash_table<tree_type_map_cache_hasher> *decl_tree_for_type;
 
 /* Lookup a VAR_DECL for TYPE, and return it if we find one.  */
 
@@ -97,8 +113,8 @@ decl_for_type_lookup (tree type)
   /* If the hash table is not initialized yet, create it now.  */
   if (decl_tree_for_type == NULL)
     {
-      decl_tree_for_type = htab_create_ggc (10, tree_type_map_hash,
-					    tree_type_map_eq, 0);
+      decl_tree_for_type
+	= hash_table<tree_type_map_cache_hasher>::create_ggc (10);
       /* That also means we don't have to bother with the lookup.  */
       return NULL_TREE;
     }
@@ -106,8 +122,7 @@ decl_for_type_lookup (tree type)
   struct tree_type_map *h, in;
   in.type.from = type;
 
-  h = (struct tree_type_map *)
-      htab_find_with_hash (decl_tree_for_type, &in, TYPE_UID (type));
+  h = decl_tree_for_type->find_with_hash (&in, TYPE_UID (type));
   return h ? h->decl : NULL_TREE;
 }
 
@@ -117,14 +132,11 @@ static void
 decl_for_type_insert (tree type, tree decl)
 {
   struct tree_type_map *h;
-  void **slot;
 
   h = ggc_alloc<tree_type_map> ();
   h->type.from = type;
   h->decl = decl;
-  slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
-                                  INSERT);
-  *(struct tree_type_map **) slot = h;
+  *decl_tree_for_type->find_slot_with_hash (h, TYPE_UID (type), INSERT) = h;
 }
 
 /* Helper routine, which encodes a value in the pointer_sized_int_node.
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 54611f8..07eb72a 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5727,8 +5727,26 @@ assemble_alias (tree decl, tree target)
    to its transaction aware clone.  Note that tm_pure functions are
    considered to be their own clone.  */
 
-static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
-     htab_t tm_clone_hash;
+struct tm_clone_hasher : ggc_cache_hasher<tree_map *>
+{
+  static hashval_t hash (tree_map *m) { return tree_map_hash (m); }
+  static bool equal (tree_map *a, tree_map *b) { return tree_map_eq (a, b); }
+
+  static void handle_cache_entry (tree_map *&e)
+  {
+    if (e != HTAB_EMPTY_ENTRY || e != HTAB_DELETED_ENTRY)
+      {
+	extern void gt_ggc_mx (tree_map *&);
+	if (ggc_marked_p (e->base.from))
+	  gt_ggc_mx (e);
+	else
+	  e = static_cast<tree_map *> (HTAB_DELETED_ENTRY);
+      }
+  }
+};
+
+static GTY((cache))
+     hash_table<tm_clone_hasher> *tm_clone_hash;
 
 void
 record_tm_clone_pair (tree o, tree n)
@@ -5736,15 +5754,14 @@ record_tm_clone_pair (tree o, tree n)
   struct tree_map **slot, *h;
 
   if (tm_clone_hash == NULL)
-    tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
+    tm_clone_hash = hash_table<tm_clone_hasher>::create_ggc (32);
 
   h = ggc_alloc<tree_map> ();
   h->hash = htab_hash_pointer (o);
   h->base.from = o;
   h->to = n;
 
-  slot = (struct tree_map **)
-    htab_find_slot_with_hash (tm_clone_hash, h, h->hash, INSERT);
+  slot = tm_clone_hash->find_slot_with_hash (h, h->hash, INSERT);
   *slot = h;
 }
 
@@ -5757,8 +5774,7 @@ get_tm_clone_pair (tree o)
 
       in.base.from = o;
       in.hash = htab_hash_pointer (o);
-      h = (struct tree_map *) htab_find_with_hash (tm_clone_hash,
-						   &in, in.hash);
+      h = tm_clone_hash->find_with_hash (&in, in.hash);
       if (h)
 	return h->to;
     }
@@ -5773,19 +5789,6 @@ typedef struct tm_alias_pair
 } tm_alias_pair;
 
 
-/* Helper function for finish_tm_clone_pairs.  Dump a hash table entry
-   into a VEC in INFO.  */
-
-static int
-dump_tm_clone_to_vec (void **slot, void *info)
-{
-  struct tree_map *map = (struct tree_map *) *slot;
-  vec<tm_alias_pair> *tm_alias_pairs = (vec<tm_alias_pair> *) info;
-  tm_alias_pair p = {DECL_UID (map->base.from), map->base.from, map->to};
-  tm_alias_pairs->safe_push (p);
-  return 1;
-}
-
 /* Dump the actual pairs to the .tm_clone_table section.  */
 
 static void
@@ -5866,15 +5869,20 @@ finish_tm_clone_pairs (void)
      to a vector, sort it, and dump the vector.  */
 
   /* Dump the hashtable to a vector.  */
-  htab_traverse_noresize (tm_clone_hash, dump_tm_clone_to_vec,
-			  (void *) &tm_alias_pairs);
+  tree_map *map;
+  hash_table<tm_clone_hasher>::iterator iter;
+  FOR_EACH_HASH_TABLE_ELEMENT (*tm_clone_hash, map, tree_map *, iter)
+    {
+      tm_alias_pair p = {DECL_UID (map->base.from), map->base.from, map->to};
+      tm_alias_pairs.safe_push (p);
+    }
   /* Sort it.  */
   tm_alias_pairs.qsort (tm_alias_pair_cmp);
 
   /* Dump it.  */
   dump_tm_clone_pairs (tm_alias_pairs);
 
-  htab_delete (tm_clone_hash);
+  tm_clone_hash->empty ();
   tm_clone_hash = NULL;
   tm_alias_pairs.release ();
 }
-- 
2.1.3

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 5/5] use vec in lto_tree_ref_table
  2014-11-13  5:57 [PATCH 1/5] add an alternative to if_marked using hash_table tsaunders
@ 2014-11-13  5:57 ` tsaunders
  2014-11-14  0:56   ` Jeff Law
  2014-11-14 10:44   ` Richard Biener
  2014-11-13  5:57 ` [PATCH 3/5] fix hash_table when empty elements are not 0 tsaunders
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 16+ messages in thread
From: tsaunders @ 2014-11-13  5:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

gengtype fails to create valid user marking functions for this type, which is
fixed by using vec here (which seems cleaner anyway).

bootstrapped + regtested powerpc64-linux (gcc 110 since gcc20 died) ok?

Trev


gcc/ChangeLog:

2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>

	* lto-section-in.c (lto_delete_in_decl_state): Adjust.
	(lto_free_function_in_decl_state): Likewise.
	* lto-streamer-out.c (copy_function_or_variable): Likewise.
	* lto-streamer.h (lto_file_decl_data_get_ ## name): Likewise.
	(lto_file_decl_data_num_ ## name ## s): Likewise.
	(struct lto_tree_ref_table): Remove.
	(struct lto_in_decl_state): Replace lto_tree_ref_table with vec<tree>.

gcc/lto/ChangeLog:

2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>

	* lto.c (lto_read_in_decl_state): Adjust.
	(lto_fixup_state): Likewise.


diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index 042dd99..75f394d 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -379,8 +379,7 @@ lto_delete_in_decl_state (struct lto_in_decl_state *state)
   int i;
 
   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
-    if (state->streams[i].trees)
-      ggc_free (state->streams[i].trees);
+    vec_free (state->streams[i]);
   ggc_free (state);
 }
 
@@ -429,7 +428,7 @@ lto_free_function_in_decl_state (struct lto_in_decl_state *state)
 {
   int i;
   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
-    ggc_free (state->streams[i].trees);
+    vec_free (state->streams[i]);
   ggc_free (state);
 }
 
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index dc406da..bc18a9c 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2186,8 +2186,8 @@ copy_function_or_variable (struct symtab_node *node)
 
   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
     {
-      size_t n = in_state->streams[i].size;
-      tree *trees = in_state->streams[i].trees;
+      size_t n = vec_safe_length (in_state->streams[i]);
+      vec<tree, va_gc> *trees = in_state->streams[i];
       struct lto_tree_ref_encoder *encoder = &(out_state->streams[i]);
 
       /* The out state must have the same indices and the in state.
@@ -2196,7 +2196,7 @@ copy_function_or_variable (struct symtab_node *node)
       gcc_assert (lto_tree_ref_encoder_size (encoder) == 0);
       encoder->trees.reserve_exact (n);
       for (j = 0; j < n; j++)
-	encoder->trees.safe_push (trees[j]);
+	encoder->trees.safe_push ((*trees)[j]);
     }
 
   lto_free_section_data (file_data, LTO_section_function_body, name,
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 4b875a2..9d6d7a0 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -274,15 +274,14 @@ lto_file_decl_data_get_ ## name (struct lto_file_decl_data *data, \
 				 unsigned int idx) \
 { \
   struct lto_in_decl_state *state = data->current_decl_state; \
-  gcc_assert (idx < state->streams[LTO_DECL_STREAM_## UPPER_NAME].size); \
-  return state->streams[LTO_DECL_STREAM_## UPPER_NAME].trees[idx]; \
+   return (*state->streams[LTO_DECL_STREAM_## UPPER_NAME])[idx]; \
 } \
 \
 static inline unsigned int \
 lto_file_decl_data_num_ ## name ## s (struct lto_file_decl_data *data) \
 { \
   struct lto_in_decl_state *state = data->current_decl_state; \
-  return state->streams[LTO_DECL_STREAM_## UPPER_NAME].size; \
+  return vec_safe_length (state->streams[LTO_DECL_STREAM_## UPPER_NAME]); \
 }
 
 
@@ -420,18 +419,6 @@ struct lto_symtab_encoder_iterator
 
 
 
-
-/* Mapping from indices to trees.  */
-struct GTY(()) lto_tree_ref_table
-{
-  /* Array of referenced trees . */
-  tree * GTY((length ("%h.size"))) trees;
-
-  /* Size of array. */
-  unsigned int size;
-};
-
-
 /* The lto_tree_ref_encoder struct is used to encode trees into indices. */
 
 struct lto_tree_ref_encoder
@@ -445,7 +432,7 @@ struct lto_tree_ref_encoder
 struct GTY(()) lto_in_decl_state
 {
   /* Array of lto_in_decl_buffers to store type and decls streams. */
-  struct lto_tree_ref_table streams[LTO_N_DECL_STREAMS];
+  vec<tree, va_gc> *streams[LTO_N_DECL_STREAMS];
 
   /* If this in-decl state is associated with a function. FN_DECL
      point to the FUNCTION_DECL. */
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index d8519d9..cdd2331 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -260,13 +260,15 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
     {
       uint32_t size = *data++;
-      tree *decls = ggc_vec_alloc<tree> (size);
+      vec<tree, va_gc> *decls = NULL;
+      vec_alloc (decls, size);
 
       for (j = 0; j < size; j++)
-	decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
+	vec_safe_push (decls,
+		       streamer_tree_cache_get_tree (data_in->reader_cache,
+						     data[j]));
 
-      state->streams[i].size = size;
-      state->streams[i].trees = decls;
+      state->streams[i] = decls;
       data += size;
     }
 
@@ -2806,20 +2808,19 @@ static void
 lto_fixup_state (struct lto_in_decl_state *state)
 {
   unsigned i, si;
-  struct lto_tree_ref_table *table;
 
   /* Although we only want to replace FUNCTION_DECLs and VAR_DECLs,
      we still need to walk from all DECLs to find the reachable
      FUNCTION_DECLs and VAR_DECLs.  */
   for (si = 0; si < LTO_N_DECL_STREAMS; si++)
     {
-      table = &state->streams[si];
-      for (i = 0; i < table->size; i++)
+      vec<tree, va_gc> *trees = state->streams[si];
+      for (i = 0; i < vec_safe_length (trees); i++)
 	{
-	  tree *tp = table->trees + i;
-	  if (VAR_OR_FUNCTION_DECL_P (*tp)
-	      && (TREE_PUBLIC (*tp) || DECL_EXTERNAL (*tp)))
-	    *tp = lto_symtab_prevailing_decl (*tp);
+	  tree t = (*trees)[i];
+	  if (VAR_OR_FUNCTION_DECL_P (t)
+	      && (TREE_PUBLIC (t) || DECL_EXTERNAL (t)))
+	    (*trees)[i] = lto_symtab_prevailing_decl (t);
 	}
     }
 }
-- 
2.1.3

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 3/5] fix hash_table when empty elements are not 0
  2014-11-13  5:57 [PATCH 1/5] add an alternative to if_marked using hash_table tsaunders
  2014-11-13  5:57 ` [PATCH 5/5] use vec in lto_tree_ref_table tsaunders
@ 2014-11-13  5:57 ` tsaunders
  2014-11-14  0:52   ` Jeff Law
  2014-11-13  5:57 ` [PATCH 2/5] remove the remaining uses of if_marked tsaunders
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: tsaunders @ 2014-11-13  5:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

hi,

The problem here is that hash_table used to zero element storage, but if the
empty element is not 0 then all elements appear to be in use.

bootstrapped + regtested x86_64-unknown-linux-gnu, ok?

Trev


gcc/ChangeLog:

2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>

	* hash-table.h (hash_table::hash_table): Call alloc_entries.
	(hash_table::alloc_entries): new method.
	(hash_table::expand): Call alloc_entries.
	(hash_table::empty): Likewise.


diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 2802e0a..7a4d609 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -1201,6 +1201,7 @@ private:
   template<typename T> friend void gt_pch_nx (hash_table<T> *,
 					      gt_pointer_operator, void *);
 
+  value_type *alloc_entries (size_t n) const;
   value_type *find_empty_slot_for_expand (hashval_t);
   void expand ();
   static bool is_deleted (value_type &v)
@@ -1259,12 +1260,7 @@ hash_table<Descriptor, Allocator, true>::hash_table (size_t size, bool ggc) :
   size_prime_index = hash_table_higher_prime_index (size);
   size = prime_tab[size_prime_index].prime;
 
-  if (!m_ggc)
-    m_entries = Allocator <value_type> ::data_alloc (size);
-  else
-    m_entries = ggc_cleared_vec_alloc<value_type> (size);
-
-  gcc_assert (m_entries != NULL);
+  m_entries = alloc_entries (size);
   m_size = size;
   m_size_prime_index = size_prime_index;
 }
@@ -1282,6 +1278,26 @@ hash_table<Descriptor, Allocator, true>::~hash_table ()
     ggc_free (m_entries);
 }
 
+/* This function returns an array of empty hash table elements.  */
+
+template<typename Descriptor, template<typename Type> class Allocator>
+inline typename hash_table<Descriptor, Allocator, true>::value_type *
+hash_table<Descriptor, Allocator, true>::alloc_entries (size_t n) const
+{
+  value_type *nentries;
+
+  if (!m_ggc)
+    nentries = Allocator <value_type> ::data_alloc (n);
+  else
+    nentries = ::ggc_cleared_vec_alloc<value_type> (n);
+
+  gcc_assert (nentries != NULL);
+  for (size_t i = 0; i < n; i++)
+    mark_empty (nentries[i]);
+
+  return nentries;
+}
+
 /* 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
@@ -1351,13 +1367,7 @@ hash_table<Descriptor, Allocator, true>::expand ()
       nsize = osize;
     }
 
-  value_type *nentries;
-  if (!m_ggc)
-    nentries = Allocator <value_type> ::data_alloc (nsize);
-  else
-    nentries = ggc_cleared_vec_alloc<value_type> (nsize);
-
-  gcc_assert (nentries != NULL);
+  value_type *nentries = alloc_entries (nsize);
   m_entries = nentries;
   m_size = nsize;
   m_size_prime_index = nindex;
@@ -1405,16 +1415,11 @@ hash_table<Descriptor, Allocator, true>::empty ()
       int nsize = prime_tab[nindex].prime;
 
       if (!m_ggc)
-	{
-	  Allocator <value_type> ::data_free (m_entries);
-	  m_entries = Allocator <value_type> ::data_alloc (nsize);
-	}
+	Allocator <value_type> ::data_free (m_entries);
       else
-	{
-	  ggc_free (m_entries);
-	  m_entries = ggc_cleared_vec_alloc<value_type> (nsize);
-	}
+	ggc_free (m_entries);
 
+      m_entries = alloc_entries (nsize);
       m_size = nsize;
       m_size_prime_index = nindex;
     }
-- 
2.1.3

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/5] add an alternative to if_marked using hash_table
@ 2014-11-13  5:57 tsaunders
  2014-11-13  5:57 ` [PATCH 5/5] use vec in lto_tree_ref_table tsaunders
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: tsaunders @ 2014-11-13  5:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

 This adds a gty cache attribute that calls user code after marking and before
sweeping allowing user code to mark more objects or clear caches as
appropriate.  User code for hash_table is set up to work similarly to if_marked
for htab.

bootstrapped + regtested x86_64-unknown-linux-gnu, ok?

Trev


gcc/ChangeLog:

2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>

	* doc/gty.texi: Document the new cache gty attribute.
	* gengtype.c (finish_cache_funcs): New function.
	(write_roots): Call gt_clear_cache on global variables with the cache
	gty attribute.
	* ggc-common.c (ggc_mark_roots): Call gt_clear_caches.
	* ggc.h (gt_clear_caches): New declaration.
	* hash-table.h (struct ggc_cache_hasher): New hasher for caches in gc
	memory.
	(gt_cleare_cache): New function.
	* emit-rtl.c, rtl.h, tree.c: Use hash_table instead of htab.


diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index 609cfce..e4d2b60 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -293,6 +293,14 @@ the pointed-to structure should use the same parameters as the outer
 structure.  This is done by marking the pointer with the
 @code{use_params} option.
 
+@findex cache
+@item cache
+
+When the @code{cache} option is applied to a global variable gt_clear_cache is
+called on that variable between the mark and sweep phases of garbage
+collection.  The gt_clear_cache function is free to mark blocks as used, or to
+clear pointers in the variable.
+
 @findex deletable
 @item deletable
 
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 04f677e..1226aad 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -131,23 +131,50 @@ rtx cc0_rtx;
 /* A hash table storing CONST_INTs whose absolute value is greater
    than MAX_SAVED_CONST_INT.  */
 
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
-     htab_t const_int_htab;
+struct const_int_hasher : ggc_cache_hasher<rtx>
+{
+  typedef HOST_WIDE_INT compare_type;
+
+  static hashval_t hash (rtx i);
+  static bool equal (rtx i, HOST_WIDE_INT h);
+};
 
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
-     htab_t const_wide_int_htab;
+static GTY ((cache)) hash_table<const_int_hasher> *const_int_htab;
+
+struct const_wide_int_hasher : ggc_cache_hasher<rtx>
+{
+  static hashval_t hash (rtx x);
+  static bool equal (rtx x, rtx y);
+};
+
+static GTY ((cache)) hash_table<const_wide_int_hasher> *const_wide_int_htab;
 
 /* A hash table storing register attribute structures.  */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct reg_attrs)))
-     htab_t reg_attrs_htab;
+struct reg_attr_hasher : ggc_cache_hasher<reg_attrs *>
+{
+  static hashval_t hash (reg_attrs *x);
+  static bool equal (reg_attrs *a, reg_attrs *b);
+};
+
+static GTY ((cache)) hash_table<reg_attr_hasher> *reg_attrs_htab;
 
 /* A hash table storing all CONST_DOUBLEs.  */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
-     htab_t const_double_htab;
+struct const_double_hasher : ggc_cache_hasher<rtx>
+{
+  static hashval_t hash (rtx x);
+  static bool equal (rtx x, rtx y);
+};
+
+static GTY ((cache)) hash_table<const_double_hasher> *const_double_htab;
 
 /* A hash table storing all CONST_FIXEDs.  */
-static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
-     htab_t const_fixed_htab;
+struct const_fixed_hasher : ggc_cache_hasher<rtx>
+{
+  static hashval_t hash (rtx x);
+  static bool equal (rtx x, rtx y);
+};
+
+static GTY ((cache)) hash_table<const_fixed_hasher> *const_fixed_htab;
 
 #define cur_insn_uid (crtl->emit.x_cur_insn_uid)
 #define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid)
@@ -155,21 +182,11 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
 
 static void set_used_decls (tree);
 static void mark_label_nuses (rtx);
-static hashval_t const_int_htab_hash (const void *);
-static int const_int_htab_eq (const void *, const void *);
 #if TARGET_SUPPORTS_WIDE_INT
-static hashval_t const_wide_int_htab_hash (const void *);
-static int const_wide_int_htab_eq (const void *, const void *);
 static rtx lookup_const_wide_int (rtx);
 #endif
-static hashval_t const_double_htab_hash (const void *);
-static int const_double_htab_eq (const void *, const void *);
 static rtx lookup_const_double (rtx);
-static hashval_t const_fixed_htab_hash (const void *);
-static int const_fixed_htab_eq (const void *, const void *);
 static rtx lookup_const_fixed (rtx);
-static hashval_t reg_attrs_htab_hash (const void *);
-static int reg_attrs_htab_eq (const void *, const void *);
 static reg_attrs *get_reg_attrs (tree, int);
 static rtx gen_const_vector (machine_mode, int);
 static void copy_rtx_if_shared_1 (rtx *orig);
@@ -180,31 +197,31 @@ int split_branch_probability = -1;
 \f
 /* Returns a hash code for X (which is a really a CONST_INT).  */
 
-static hashval_t
-const_int_htab_hash (const void *x)
+hashval_t
+const_int_hasher::hash (rtx x)
 {
-  return (hashval_t) INTVAL ((const_rtx) x);
+  return (hashval_t) INTVAL (x);
 }
 
 /* Returns nonzero if the value represented by X (which is really a
    CONST_INT) is the same as that given by Y (which is really a
    HOST_WIDE_INT *).  */
 
-static int
-const_int_htab_eq (const void *x, const void *y)
+bool
+const_int_hasher::equal (rtx x, HOST_WIDE_INT y)
 {
-  return (INTVAL ((const_rtx) x) == *((const HOST_WIDE_INT *) y));
+  return (INTVAL (x) == y);
 }
 
 #if TARGET_SUPPORTS_WIDE_INT
 /* Returns a hash code for X (which is a really a CONST_WIDE_INT).  */
 
-static hashval_t
-const_wide_int_htab_hash (const void *x)
+hashval_t
+const_wide_int_hasher::hash (rtx x)
 {
   int i;
   HOST_WIDE_INT hash = 0;
-  const_rtx xr = (const_rtx) x;
+  const_rtx xr = x;
 
   for (i = 0; i < CONST_WIDE_INT_NUNITS (xr); i++)
     hash += CONST_WIDE_INT_ELT (xr, i);
@@ -216,28 +233,28 @@ const_wide_int_htab_hash (const void *x)
    CONST_WIDE_INT) is the same as that given by Y (which is really a
    CONST_WIDE_INT).  */
 
-static int
-const_wide_int_htab_eq (const void *x, const void *y)
+bool
+const_wide_int_hasher::equal (rtx x, rtx y)
 {
   int i;
-  const_rtx xr = (const_rtx) x;
-  const_rtx yr = (const_rtx) y;
+  const_rtx xr = x;
+  const_rtx yr = y;
   if (CONST_WIDE_INT_NUNITS (xr) != CONST_WIDE_INT_NUNITS (yr))
-    return 0;
+    return false;
 
   for (i = 0; i < CONST_WIDE_INT_NUNITS (xr); i++)
     if (CONST_WIDE_INT_ELT (xr, i) != CONST_WIDE_INT_ELT (yr, i))
-      return 0;
+      return false;
 
-  return 1;
+  return true;
 }
 #endif
 
 /* Returns a hash code for X (which is really a CONST_DOUBLE).  */
-static hashval_t
-const_double_htab_hash (const void *x)
+hashval_t
+const_double_hasher::hash (rtx x)
 {
-  const_rtx const value = (const_rtx) x;
+  const_rtx const value = x;
   hashval_t h;
 
   if (TARGET_SUPPORTS_WIDE_INT == 0 && GET_MODE (value) == VOIDmode)
@@ -253,10 +270,10 @@ const_double_htab_hash (const void *x)
 
 /* Returns nonzero if the value represented by X (really a ...)
    is the same as that represented by Y (really a ...) */
-static int
-const_double_htab_eq (const void *x, const void *y)
+bool
+const_double_hasher::equal (rtx x, rtx y)
 {
-  const_rtx const a = (const_rtx)x, b = (const_rtx)y;
+  const_rtx const a = x, b = y;
 
   if (GET_MODE (a) != GET_MODE (b))
     return 0;
@@ -270,10 +287,10 @@ const_double_htab_eq (const void *x, const void *y)
 
 /* Returns a hash code for X (which is really a CONST_FIXED).  */
 
-static hashval_t
-const_fixed_htab_hash (const void *x)
+hashval_t
+const_fixed_hasher::hash (rtx x)
 {
-  const_rtx const value = (const_rtx) x;
+  const_rtx const value = x;
   hashval_t h;
 
   h = fixed_hash (CONST_FIXED_VALUE (value));
@@ -282,13 +299,13 @@ const_fixed_htab_hash (const void *x)
   return h;
 }
 
-/* Returns nonzero if the value represented by X (really a ...)
-   is the same as that represented by Y (really a ...).  */
+/* Returns nonzero if the value represented by X is the same as that
+   represented by Y.  */
 
-static int
-const_fixed_htab_eq (const void *x, const void *y)
+bool
+const_fixed_hasher::equal (rtx x, rtx y)
 {
-  const_rtx const a = (const_rtx) x, b = (const_rtx) y;
+  const_rtx const a = x, b = y;
 
   if (GET_MODE (a) != GET_MODE (b))
     return 0;
@@ -338,23 +355,22 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
 
 /* Returns a hash code for X (which is a really a reg_attrs *).  */
 
-static hashval_t
-reg_attrs_htab_hash (const void *x)
+hashval_t
+reg_attr_hasher::hash (reg_attrs *x)
 {
-  const reg_attrs *const p = (const reg_attrs *) x;
+  const reg_attrs *const p = x;
 
   return ((p->offset * 1000) ^ (intptr_t) p->decl);
 }
 
-/* Returns nonzero if the value represented by X (which is really a
-   reg_attrs *) is the same as that given by Y (which is also really a
-   reg_attrs *).  */
+/* Returns nonzero if the value represented by X  is the same as that given by
+   Y.  */
 
-static int
-reg_attrs_htab_eq (const void *x, const void *y)
+bool
+reg_attr_hasher::equal (reg_attrs *x, reg_attrs *y)
 {
-  const reg_attrs *const p = (const reg_attrs *) x;
-  const reg_attrs *const q = (const reg_attrs *) y;
+  const reg_attrs *const p = x;
+  const reg_attrs *const q = y;
 
   return (p->decl == q->decl && p->offset == q->offset);
 }
@@ -366,7 +382,6 @@ static reg_attrs *
 get_reg_attrs (tree decl, int offset)
 {
   reg_attrs attrs;
-  void **slot;
 
   /* If everything is the default, we can just return zero.  */
   if (decl == 0 && offset == 0)
@@ -375,14 +390,14 @@ get_reg_attrs (tree decl, int offset)
   attrs.decl = decl;
   attrs.offset = offset;
 
-  slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
+  reg_attrs **slot = reg_attrs_htab->find_slot (&attrs, INSERT);
   if (*slot == 0)
     {
       *slot = ggc_alloc<reg_attrs> ();
       memcpy (*slot, &attrs, sizeof (reg_attrs));
     }
 
-  return (reg_attrs *) *slot;
+  return *slot;
 }
 
 
@@ -444,8 +459,6 @@ gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
 rtx
 gen_rtx_CONST_INT (machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
 {
-  void **slot;
-
   if (arg >= - MAX_SAVED_CONST_INT && arg <= MAX_SAVED_CONST_INT)
     return const_int_rtx[arg + MAX_SAVED_CONST_INT];
 
@@ -455,12 +468,12 @@ gen_rtx_CONST_INT (machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
 #endif
 
   /* Look up the CONST_INT in the hash table.  */
-  slot = htab_find_slot_with_hash (const_int_htab, &arg,
-				   (hashval_t) arg, INSERT);
+  rtx *slot = const_int_htab->find_slot_with_hash (arg, (hashval_t) arg,
+						   INSERT);
   if (*slot == 0)
     *slot = gen_rtx_raw_CONST_INT (VOIDmode, arg);
 
-  return (rtx) *slot;
+  return *slot;
 }
 
 rtx
@@ -479,11 +492,11 @@ gen_int_mode (HOST_WIDE_INT c, machine_mode mode)
 static rtx
 lookup_const_double (rtx real)
 {
-  void **slot = htab_find_slot (const_double_htab, real, INSERT);
+  rtx *slot = const_double_htab->find_slot (real, INSERT);
   if (*slot == 0)
     *slot = real;
 
-  return (rtx) *slot;
+  return *slot;
 }
 
 /* Return a CONST_DOUBLE rtx for a floating-point value specified by
@@ -506,11 +519,11 @@ const_double_from_real_value (REAL_VALUE_TYPE value, machine_mode mode)
 static rtx
 lookup_const_fixed (rtx fixed)
 {
-  void **slot = htab_find_slot (const_fixed_htab, fixed, INSERT);
+  rtx *slot = const_fixed_htab->find_slot (fixed, INSERT);
   if (*slot == 0)
     *slot = fixed;
 
-  return (rtx) *slot;
+  return *slot;
 }
 
 /* Return a CONST_FIXED rtx for a fixed-point value specified by
@@ -557,11 +570,11 @@ rtx_to_double_int (const_rtx cst)
 static rtx
 lookup_const_wide_int (rtx wint)
 {
-  void **slot = htab_find_slot (const_wide_int_htab, wint, INSERT);
+  rtx *slot = const_wide_int_htab->find_slot (wint, INSERT);
   if (*slot == 0)
     *slot = wint;
 
-  return (rtx) *slot;
+  return *slot;
 }
 #endif
 
@@ -5812,7 +5825,7 @@ init_emit_regs (void)
   mem_attrs *attrs;
 
   /* Reset register attributes */
-  htab_empty (reg_attrs_htab);
+  reg_attrs_htab->empty ();
 
   /* We need reg_raw_mode, so initialize the modes now.  */
   init_reg_modes_target ();
@@ -5901,21 +5914,16 @@ init_emit_once (void)
 
   /* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
      CONST_FIXED, and memory attribute hash tables.  */
-  const_int_htab = htab_create_ggc (37, const_int_htab_hash,
-				    const_int_htab_eq, NULL);
+  const_int_htab = hash_table<const_int_hasher>::create_ggc (37);
 
 #if TARGET_SUPPORTS_WIDE_INT
-  const_wide_int_htab = htab_create_ggc (37, const_wide_int_htab_hash,
-					 const_wide_int_htab_eq, NULL);
+  const_wide_int_htab = hash_table<const_wide_int_hasher>::create_ggc (37);
 #endif
-  const_double_htab = htab_create_ggc (37, const_double_htab_hash,
-				       const_double_htab_eq, NULL);
+  const_double_htab = hash_table<const_double_hasher>::create_ggc (37);
 
-  const_fixed_htab = htab_create_ggc (37, const_fixed_htab_hash,
-				      const_fixed_htab_eq, NULL);
+  const_fixed_htab = hash_table<const_fixed_hasher>::create_ggc (37);
 
-  reg_attrs_htab = htab_create_ggc (37, reg_attrs_htab_hash,
-				    reg_attrs_htab_eq, NULL);
+  reg_attrs_htab = hash_table<reg_attr_hasher>::create_ggc (37);
 
 #ifdef INIT_EXPANDERS
   /* This is to initialize {init|mark|free}_machine_status before the first
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index fac83ee..38c173f 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -4482,6 +4482,58 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
   }
 }
 
+static void
+finish_cache_funcs (flist *flp)
+{
+  struct flist *fli2;
+
+  for (fli2 = flp; fli2; fli2 = fli2->next)
+    if (fli2->started_p)
+      {
+	oprintf (fli2->f, "}\n\n");
+      }
+
+  for (fli2 = flp; fli2 && base_files; fli2 = fli2->next)
+    if (fli2->started_p)
+      {
+	lang_bitmap bitmap = get_lang_bitmap (fli2->file);
+	int fnum;
+
+	for (fnum = 0; bitmap != 0; fnum++, bitmap >>= 1)
+	  if (bitmap & 1)
+	    {
+	      oprintf (base_files[fnum], "extern void gt_clear_caches_");
+	      put_mangled_filename (base_files[fnum], fli2->file);
+	      oprintf (base_files[fnum], " ();\n");
+	    }
+      }
+
+  for (size_t fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
+    oprintf (base_files[fnum], "void\ngt_clear_caches ()\n{\n");
+
+  for (fli2 = flp; fli2; fli2 = fli2->next)
+    if (fli2->started_p)
+      {
+	lang_bitmap bitmap = get_lang_bitmap (fli2->file);
+	int fnum;
+
+	fli2->started_p = 0;
+
+	for (fnum = 0; base_files && bitmap != 0; fnum++, bitmap >>= 1)
+	  if (bitmap & 1)
+	    {
+	      oprintf (base_files[fnum], "  gt_clear_caches_");
+	      put_mangled_filename (base_files[fnum], fli2->file);
+	      oprintf (base_files[fnum], " ();\n");
+	    }
+      }
+
+  for (size_t fnum = 0; base_files && fnum < num_lang_dirs; fnum++)
+    {
+      oprintf (base_files[fnum], "}\n");
+    }
+}
+
 /* Write the first three fields (pointer, count and stride) for
    root NAME to F.  V and LINE are as for write_root.
 
@@ -4801,6 +4853,8 @@ write_roots (pair_p variables, bool emit_pch)
 	  ;
 	else if (strcmp (o->name, "if_marked") == 0)
 	  ;
+	else if (strcmp (o->name, "cache") == 0)
+	  ;
 	else
 	  error_at_line (&v->line,
 			 "global `%s' has unknown option `%s'",
@@ -4952,6 +5006,37 @@ write_roots (pair_p variables, bool emit_pch)
   finish_root_table (flp, "ggc_rc", "LAST_GGC_CACHE_TAB", "ggc_cache_tab",
 		     "gt_ggc_cache_rtab");
 
+  for (v = variables; v; v = v->next)
+    {
+      outf_p f = get_output_file_with_visibility (CONST_CAST (input_file*,
+							      v->line.file));
+      struct flist *fli;
+      bool cache = false;
+      options_p o;
+
+      for (o = v->opt; o; o = o->next)
+	if (strcmp (o->name, "cache") == 0)
+	  cache = true;
+       if (!cache)
+	continue;
+
+      for (fli = flp; fli; fli = fli->next)
+	if (fli->f == f)
+	  break;
+      if (!fli->started_p)
+	{
+	  fli->started_p = 1;
+
+	  oprintf (f, "void\ngt_clear_caches_");
+	  put_mangled_filename (f, v->line.file);
+	  oprintf (f, " ()\n{\n");
+	}
+
+      oprintf (f, "  gt_cleare_cache (%s);\n", v->name);
+    }
+
+  finish_cache_funcs (flp);
+
   if (!emit_pch)
     return;
 
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 32440b4..06f70c2 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -162,6 +162,8 @@ ggc_mark_roots (void)
   for (ct = gt_ggc_cache_rtab; *ct; ct++)
     ggc_scan_cache_tab (*ct);
 
+  gt_clear_caches ();
+
   FOR_EACH_VEC_ELT (extra_cache_vec, i, ctp)
     ggc_scan_cache_tab (ctp);
 
diff --git a/gcc/ggc.h b/gcc/ggc.h
index dc21520..fb8ce73 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -54,6 +54,9 @@ extern int gt_pch_note_object (void *, void *, gt_note_pointers);
    function.  */
 extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder);
 
+/* generated function to clear caches in gc memory.  */
+extern void gt_clear_caches ();
+
 /* Mark the object in the first parameter and anything it points to.  */
 typedef void (*gt_pointer_walker) (void *);
 
diff --git a/gcc/hash-table.h b/gcc/hash-table.h
index 2493f2e..2802e0a 100644
--- a/gcc/hash-table.h
+++ b/gcc/hash-table.h
@@ -334,6 +334,44 @@ struct ggc_hasher
   }
 };
 
+/* Hasher for cache entry in gc memory.  */
+
+template<typename T>
+struct ggc_cache_hasher
+{
+  typedef T value_type;
+  typedef T compare_type;
+  typedef int store_values_directly;
+
+  static void remove (T &) {}
+
+  /* Entries are weakly held because this is for caches.  */
+
+  static void ggc_mx (T &) {}
+
+  static void
+  pch_nx (T &p)
+  {
+  extern void gt_pch_nx (T &);
+  gt_pch_nx (p);
+  }
+
+  static void
+  pch_nx (T &p, gt_pointer_operator op, void *cookie)
+  {
+    op (&p, cookie);
+  }
+
+  /* clear out entries if there about to be gc'd.  */
+
+  static void
+  handle_cache_entry (T &e)
+  {
+    if (e != HTAB_EMPTY_ENTRY && e != HTAB_DELETED_ENTRY && !ggc_marked_p (e))
+      e = static_cast<T> (HTAB_DELETED_ENTRY);
+  }
+};
+
 
 /* Table of primes and their inversion information.  */
 
@@ -1667,4 +1705,16 @@ gt_pch_nx (hash_table<D> *h, gt_pointer_operator op, void *cookie)
   op (&h->m_entries, cookie);
 }
 
+template<typename H>
+inline void
+gt_cleare_cache (hash_table<H> *h)
+{
+  if (!h)
+    return;
+
+  for (typename hash_table<H>::iterator iter = h->begin (); iter != h->end ();
+       ++iter)
+    H::handle_cache_entry (*iter);
+}
+
 #endif /* TYPED_HASHTAB_H */
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 3bfb6bf..b9d62ae 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -181,7 +181,7 @@ struct GTY(()) mem_attrs
    object in the low part of a 4-byte register, the OFFSET field
    will be -3 rather than 0.  */
 
-struct GTY(()) reg_attrs {
+struct GTY((for_user)) reg_attrs {
   tree decl;			/* decl corresponding to REG.  */
   HOST_WIDE_INT offset;		/* Offset from start of DECL.  */
 };
diff --git a/gcc/tree.c b/gcc/tree.c
index 221f0dd..5fb44bc 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -205,8 +205,14 @@ static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
 
 /* Hash table and temporary node for larger integer const values.  */
 static GTY (()) tree int_cst_node;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-     htab_t int_cst_hash_table;
+
+struct int_cst_hasher : ggc_cache_hasher<tree>
+{
+  static hashval_t hash (tree t);
+  static bool equal (tree x, tree y);
+};
+
+static GTY ((cache)) hash_table<int_cst_hasher> *int_cst_hash_table;
 
 /* Hash table for optimization flags and target option flags.  Use the same
    hash table for both sets of options.  Nodes for building the current
@@ -215,8 +221,14 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
    allocating and freeing up a node repeatably.  */
 static GTY (()) tree cl_optimization_node;
 static GTY (()) tree cl_target_option_node;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-     htab_t cl_option_hash_table;
+
+struct cl_option_hasher : ggc_cache_hasher<tree>
+{
+  static hashval_t hash (tree t);
+  static bool equal (tree x, tree y);
+};
+
+static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
 
 /* General tree->tree mapping  structure for use in hash tables.  */
 
@@ -233,10 +245,6 @@ static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)
 static void set_type_quals (tree, int);
 static int type_hash_eq (const void *, const void *);
 static hashval_t type_hash_hash (const void *);
-static hashval_t int_cst_hash_hash (const void *);
-static int int_cst_hash_eq (const void *, const void *);
-static hashval_t cl_option_hash_hash (const void *);
-static int cl_option_hash_eq (const void *, const void *);
 static void print_type_hash_statistics (void);
 static void print_debug_expr_statistics (void);
 static void print_value_expr_statistics (void);
@@ -585,13 +593,11 @@ init_ttree (void)
   value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
 					 tree_decl_map_eq, 0);
 
-  int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
-					int_cst_hash_eq, NULL);
+  int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
 
   int_cst_node = make_int_cst (1, 1);
 
-  cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
-					  cl_option_hash_eq, NULL);
+  cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64);
 
   cl_optimization_node = make_node (OPTIMIZATION_NODE);
   cl_target_option_node = make_node (TARGET_OPTION_NODE);
@@ -1256,10 +1262,10 @@ force_fit_type (tree type, const wide_int_ref &cst,
 
 /* Return the hash code code X, an INTEGER_CST.  */
 
-static hashval_t
-int_cst_hash_hash (const void *x)
+hashval_t
+int_cst_hasher::hash (tree x)
 {
-  const_tree const t = (const_tree) x;
+  const_tree const t = x;
   hashval_t code = htab_hash_pointer (TREE_TYPE (t));
   int i;
 
@@ -1272,11 +1278,11 @@ int_cst_hash_hash (const void *x)
 /* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
    is the same as that given by *Y, which is the same.  */
 
-static int
-int_cst_hash_eq (const void *x, const void *y)
+bool
+int_cst_hasher::equal (tree x, tree y)
 {
-  const_tree const xt = (const_tree) x;
-  const_tree const yt = (const_tree) y;
+  const_tree const xt = x;
+  const_tree const yt = y;
 
   if (TREE_TYPE (xt) != TREE_TYPE (yt)
       || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
@@ -1408,13 +1414,12 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst)
 	{
 	  /* Use the cache of larger shared ints, using int_cst_node as
 	     a temporary.  */
-	  void **slot;
 
 	  TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
 	  TREE_TYPE (int_cst_node) = type;
 
-	  slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
-	  t = (tree) *slot;
+	  tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT);
+	  t = *slot;
 	  if (!t)
 	    {
 	      /* Insert this one into the hash table.  */
@@ -1430,11 +1435,10 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst)
       /* The value either hashes properly or we drop it on the floor
 	 for the gc to take care of.  There will not be enough of them
 	 to worry about.  */
-      void **slot;
 
       tree nt = build_new_int_cst (type, cst);
-      slot = htab_find_slot (int_cst_hash_table, nt, INSERT);
-      t = (tree) *slot;
+      tree *slot = int_cst_hash_table->find_slot (nt, INSERT);
+      t = *slot;
       if (!t)
 	{
 	  /* Insert this one into the hash table.  */
@@ -1539,9 +1543,7 @@ cache_integer_cst (tree t)
   else
     {
       /* Use the cache of larger shared ints.  */
-      void **slot;
-
-      slot = htab_find_slot (int_cst_hash_table, t, INSERT);
+      tree *slot = int_cst_hash_table->find_slot (t, INSERT);
       /* If there is already an entry for the number verify it's the
          same.  */
       if (*slot)
@@ -11468,10 +11470,10 @@ tree_nonartificial_location (tree exp)
 
 /* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code.  */
 
-static hashval_t
-cl_option_hash_hash (const void *x)
+hashval_t
+cl_option_hasher::hash (tree x)
 {
-  const_tree const t = (const_tree) x;
+  const_tree const t = x;
   const char *p;
   size_t i;
   size_t len = 0;
@@ -11505,11 +11507,11 @@ cl_option_hash_hash (const void *x)
    TARGET_OPTION tree node) is the same as that given by *Y, which is the
    same.  */
 
-static int
-cl_option_hash_eq (const void *x, const void *y)
+bool
+cl_option_hasher::equal (tree x, tree y)
 {
-  const_tree const xt = (const_tree) x;
-  const_tree const yt = (const_tree) y;
+  const_tree const xt = x;
+  const_tree const yt = y;
   const char *xp;
   const char *yp;
   size_t len;
@@ -11543,15 +11545,14 @@ tree
 build_optimization_node (struct gcc_options *opts)
 {
   tree t;
-  void **slot;
 
   /* Use the cache of optimization nodes.  */
 
   cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
 			opts);
 
-  slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
-  t = (tree) *slot;
+  tree *slot = cl_option_hash_table->find_slot (cl_optimization_node, INSERT);
+  t = *slot;
   if (!t)
     {
       /* Insert this one into the hash table.  */
@@ -11571,15 +11572,14 @@ tree
 build_target_option_node (struct gcc_options *opts)
 {
   tree t;
-  void **slot;
 
   /* Use the cache of optimization nodes.  */
 
   cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
 			 opts);
 
-  slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
-  t = (tree) *slot;
+  tree *slot = cl_option_hash_table->find_slot (cl_target_option_node, INSERT);
+  t = *slot;
   if (!t)
     {
       /* Insert this one into the hash table.  */
@@ -11593,26 +11593,16 @@ build_target_option_node (struct gcc_options *opts)
   return t;
 }
 
-/* Reset TREE_TARGET_GLOBALS cache for TARGET_OPTION_NODE.
-   Called through htab_traverse.  */
-
-static int
-prepare_target_option_node_for_pch (void **slot, void *)
-{
-  tree node = (tree) *slot;
-  if (TREE_CODE (node) == TARGET_OPTION_NODE)
-    TREE_TARGET_GLOBALS (node) = NULL;
-  return 1;
-}
-
 /* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees,
    so that they aren't saved during PCH writing.  */
 
 void
 prepare_target_option_nodes_for_pch (void)
 {
-  htab_traverse (cl_option_hash_table, prepare_target_option_node_for_pch,
-		 NULL);
+  hash_table<cl_option_hasher>::iterator iter = cl_option_hash_table->begin ();
+  for (; iter != cl_option_hash_table->end (); ++iter)
+    if (TREE_CODE (*iter) == TARGET_OPTION_NODE)
+      TREE_TARGET_GLOBALS (*iter) = NULL;
 }
 
 /* Determine the "ultimate origin" of a block.  The block may be an inlined
-- 
2.1.3

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 4/5] remove param$N_is usage
  2014-11-13  5:57 [PATCH 1/5] add an alternative to if_marked using hash_table tsaunders
                   ` (2 preceding siblings ...)
  2014-11-13  5:57 ` [PATCH 2/5] remove the remaining uses of if_marked tsaunders
@ 2014-11-13  6:14 ` tsaunders
  2014-11-14  0:56   ` Jeff Law
  2014-11-14  0:37 ` [PATCH 1/5] add an alternative to if_marked using hash_table Jeff Law
  4 siblings, 1 reply; 16+ messages in thread
From: tsaunders @ 2014-11-13  6:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

The only user of this is splay_tree.  We only have a couple splay trees in ggc
memory, and it wasn't clear to me any of them were tree based instead of hash
based for performance reasons, so I chose to just convert them to hash_map
rather than writing a templated splay tree.

bootstrapped + regtested x86_64-unknown-linux-gnu, ok?

trev

gcc/

	* hash-map.h (hash_map::iterator): New class.
	(hash_map::begin): New method.
	(hash_map::end): Likewise.
	* alias.c, config/alpha/alpha.c, dwarf2asm.c, omp-low.c, tree.h:
	replace splay_tree with hash_map.


diff --git a/gcc/alias.c b/gcc/alias.c
index aa6ae41..fe27ce8 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h"
 #include "cselib.h"
 #include "splay-tree.h"
+#include "hash-map.h"
 #include "langhooks.h"
 #include "timevar.h"
 #include "dumpfile.h"
@@ -139,6 +140,32 @@ along with GCC; see the file COPYING3.  If not see
    However, this is no actual entry for alias set zero.  It is an
    error to attempt to explicitly construct a subset of zero.  */
 
+struct alias_set_traits : default_hashmap_traits
+{
+  template<typename T>
+  static bool
+  is_empty (T &e)
+  {
+    return e.m_key == INT_MIN;
+  }
+
+  template<typename  T>
+  static bool
+  is_deleted (T &e)
+  {
+    return e.m_key == (INT_MIN + 1);
+  }
+
+  template<typename T> static void mark_empty (T &e) { e.m_key = INT_MIN; }
+
+  template<typename T>
+  static void
+  mark_deleted (T &e)
+  {
+    e.m_key = INT_MIN + 1;
+  }
+};
+
 struct GTY(()) alias_set_entry_d {
   /* The alias set number, as stored in MEM_ALIAS_SET.  */
   alias_set_type alias_set;
@@ -154,7 +181,7 @@ struct GTY(()) alias_set_entry_d {
 
      continuing our example above, the children here will be all of
      `int', `double', `float', and `struct S'.  */
-  splay_tree GTY((param1_is (int), param2_is (int))) children;
+  hash_map<int, int, alias_set_traits> *children;
 };
 typedef struct alias_set_entry_d *alias_set_entry;
 
@@ -165,7 +192,6 @@ static int base_alias_check (rtx, rtx, rtx, rtx, machine_mode,
 			     machine_mode);
 static rtx find_base_value (rtx);
 static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
-static int insert_subset_children (splay_tree_node, void*);
 static alias_set_entry get_alias_set_entry (alias_set_type);
 static tree decl_for_component_ref (tree);
 static int write_dependence_p (const_rtx,
@@ -405,17 +431,6 @@ mems_in_disjoint_alias_sets_p (const_rtx mem1, const_rtx mem2)
   return ! alias_sets_conflict_p (MEM_ALIAS_SET (mem1), MEM_ALIAS_SET (mem2));
 }
 
-/* Insert the NODE into the splay tree given by DATA.  Used by
-   record_alias_subset via splay_tree_foreach.  */
-
-static int
-insert_subset_children (splay_tree_node node, void *data)
-{
-  splay_tree_insert ((splay_tree) data, node->key, node->value);
-
-  return 0;
-}
-
 /* Return true if the first alias set is a subset of the second.  */
 
 bool
@@ -431,8 +446,7 @@ alias_set_subset_of (alias_set_type set1, alias_set_type set2)
   ase = get_alias_set_entry (set2);
   if (ase != 0
       && (ase->has_zero_child
-	  || splay_tree_lookup (ase->children,
-			        (splay_tree_key) set1)))
+	  || ase->children->get (set1)))
     return true;
   return false;
 }
@@ -452,16 +466,14 @@ alias_sets_conflict_p (alias_set_type set1, alias_set_type set2)
   ase = get_alias_set_entry (set1);
   if (ase != 0
       && (ase->has_zero_child
-	  || splay_tree_lookup (ase->children,
-				(splay_tree_key) set2)))
+	  || ase->children->get (set2)))
     return 1;
 
   /* Now do the same, but with the alias sets reversed.  */
   ase = get_alias_set_entry (set2);
   if (ase != 0
       && (ase->has_zero_child
-	  || splay_tree_lookup (ase->children,
-				(splay_tree_key) set1)))
+	  || ase->children->get (set1)))
     return 1;
 
   /* The two alias sets are distinct and neither one is the
@@ -956,9 +968,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
       superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
       superset_entry->alias_set = superset;
       superset_entry->children
-	= splay_tree_new_ggc (splay_tree_compare_ints,
-			      ggc_alloc_splay_tree_scalar_scalar_splay_tree_s,
-			      ggc_alloc_splay_tree_scalar_scalar_splay_tree_node_s);
+	= hash_map<int, int, alias_set_traits>::create_ggc (64);
       superset_entry->has_zero_child = 0;
       (*alias_sets)[superset] = superset_entry;
     }
@@ -975,13 +985,14 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
 	  if (subset_entry->has_zero_child)
 	    superset_entry->has_zero_child = 1;
 
-	  splay_tree_foreach (subset_entry->children, insert_subset_children,
-			      superset_entry->children);
+	  hash_map<int, int, alias_set_traits>::iterator iter
+	    = subset_entry->children->begin ();
+	  for (; iter != subset_entry->children->end (); ++iter)
+	    superset_entry->children->put ((*iter).first, (*iter).second);
 	}
 
       /* Enter the SUBSET itself as a child of the SUPERSET.  */
-      splay_tree_insert (superset_entry->children,
-			 (splay_tree_key) subset, 0);
+      superset_entry->children->put (subset, 0);
     }
 }
 
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 05db3dc..33ff717 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -57,6 +57,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "debug.h"
 #include "langhooks.h"
 #include "splay-tree.h"
+#include "hash-map.h"
 #include "hash-table.h"
 #include "predict.h"
 #include "dominance.h"
@@ -4860,6 +4861,14 @@ alpha_multipass_dfa_lookahead (void)
 
 struct GTY(()) alpha_links;
 
+struct string_traits : default_hashmap_traits
+{
+  static bool equal_keys (const char *const &a, const char *const &b)
+  {
+    return strcmp (a, b) == 0;
+  }
+};
+
 struct GTY(()) machine_function
 {
   /* For flag_reorder_blocks_and_partition.  */
@@ -4869,8 +4878,7 @@ struct GTY(()) machine_function
   bool uses_condition_handler;
 
   /* Linkage entries.  */
-  splay_tree GTY ((param1_is (char *), param2_is (struct alpha_links *)))
-    links;
+  hash_map<const char *, alpha_links *, string_traits> *links;
 };
 
 /* How to allocate a 'struct machine_function'.  */
@@ -9642,18 +9650,14 @@ alpha_use_linkage (rtx func, bool lflag, bool rflag)
 
   if (cfun->machine->links)
     {
-      splay_tree_node lnode;
-
       /* Is this name already defined?  */
-      lnode = splay_tree_lookup (cfun->machine->links, (splay_tree_key) name);
-      if (lnode)
-	al = (struct alpha_links *) lnode->value;
+      alpha_links *slot = cfun->machine->links->get (name);
+      if (slot)
+	al = *slot;
     }
   else
-    cfun->machine->links = splay_tree_new_ggc
-      ((splay_tree_compare_fn) strcmp,
-       ggc_alloc_splay_tree_str_alpha_links_splay_tree_s,
-       ggc_alloc_splay_tree_str_alpha_links_splay_tree_node_s);
+    cfun->machine->links
+      = hash_map<const char *, alpha_links *, string_traits>::create_ggc (64);
 
   if (al == NULL)
     {
@@ -9681,9 +9685,7 @@ alpha_use_linkage (rtx func, bool lflag, bool rflag)
       al->func = func;
       al->linkage = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (linksym));
 
-      splay_tree_insert (cfun->machine->links,
-                         (splay_tree_key) ggc_strdup (name),
-			 (splay_tree_value) al);
+      cfun->machine->links->put (ggc_strdup (name), al);
     }
 
   al->rkind = rflag ? KIND_CODEADDR : KIND_LINKAGE;
@@ -9695,12 +9697,8 @@ alpha_use_linkage (rtx func, bool lflag, bool rflag)
 }
 
 static int
-alpha_write_one_linkage (splay_tree_node node, void *data)
+alpha_write_one_linkage (const char *name, alpha_links *link, FILE *steam)
 {
-  const char *const name = (const char *) node->key;
-  struct alpha_links *link = (struct alpha_links *) node->value;
-  FILE *stream = (FILE *) data;
-
   ASM_OUTPUT_INTERNAL_LABEL (stream, XSTR (link->linkage, 0));
   if (link->rkind == KIND_CODEADDR)
     {
@@ -9750,8 +9748,10 @@ alpha_write_linkage (FILE *stream, const char *funname)
 
   if (cfun->machine->links)
     {
-      splay_tree_foreach (cfun->machine->links, alpha_write_one_linkage, stream);
-      /* splay_tree_delete (func->links); */
+      hash_map<const char *, alpha_links *, string_traits>::iterator iter
+	= cfun->machine->links->begin ();
+      for (; iter != cfun->machine->links->end (); ++iter)
+	alpha_write_one_linkage ((*iter).first, (*iter).second, stream);
     }
 }
 
diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index b437005..3eba5ca 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dwarf2asm.h"
 #include "dwarf2.h"
 #include "splay-tree.h"
+#include "hash-map.h"
 #include "ggc.h"
 #include "tm_p.h"
 
@@ -790,9 +791,7 @@ dw2_asm_output_delta_sleb128 (const char *lab1 ATTRIBUTE_UNUSED,
 }
 #endif /* 0 */
 \f
-static int dw2_output_indirect_constant_1 (splay_tree_node, void *);
-
-static GTY((param1_is (char *), param2_is (tree))) splay_tree indirect_pool;
+static GTY(()) hash_map<const char *, tree> *indirect_pool;
 
 static GTY(()) int dw2_const_labelno;
 
@@ -808,10 +807,10 @@ static GTY(()) int dw2_const_labelno;
    K2, respectively.  */
 
 static int
-splay_tree_compare_strings (splay_tree_key k1, splay_tree_key k2)
+compare_strings (const void *a, const void *b)
 {
-  const char *s1 = (const char *)k1;
-  const char *s2 = (const char *)k2;
+  const char *s1 = ((const std::pair<const char *, tree> *) a)->first;
+  const char *s2 = ((const std::pair<const char *, tree> *) b)->first;
   int ret;
 
   if (s1 == s2)
@@ -836,23 +835,18 @@ splay_tree_compare_strings (splay_tree_key k1, splay_tree_key k2)
 rtx
 dw2_force_const_mem (rtx x, bool is_public)
 {
-  splay_tree_node node;
   const char *key;
   tree decl_id;
 
   if (! indirect_pool)
-    /* We use strcmp, rather than just comparing pointers, so that the
-       sort order will not depend on the host system.  */
-    indirect_pool = splay_tree_new_ggc (splay_tree_compare_strings,
-					ggc_alloc_splay_tree_str_tree_node_splay_tree_s,
-					ggc_alloc_splay_tree_str_tree_node_splay_tree_node_s);
+    indirect_pool = hash_map<const char *, tree>::create_ggc (64);
 
   gcc_assert (GET_CODE (x) == SYMBOL_REF);
 
   key = XSTR (x, 0);
-  node = splay_tree_lookup (indirect_pool, (splay_tree_key) key);
-  if (node)
-    decl_id = (tree) node->value;
+  tree *slot = indirect_pool->get (key);
+  if (slot)
+    decl_id = *slot;
   else
     {
       tree id;
@@ -881,8 +875,7 @@ dw2_force_const_mem (rtx x, bool is_public)
       if (id)
 	TREE_SYMBOL_REFERENCED (id) = 1;
 
-      splay_tree_insert (indirect_pool, (splay_tree_key) key,
-			 (splay_tree_value) decl_id);
+      indirect_pool->put (key, decl_id);
     }
 
   return gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (decl_id));
@@ -892,15 +885,10 @@ dw2_force_const_mem (rtx x, bool is_public)
    splay_tree_foreach.  Emit one queued constant to memory.  */
 
 static int
-dw2_output_indirect_constant_1 (splay_tree_node node,
-				void *data ATTRIBUTE_UNUSED)
+dw2_output_indirect_constant_1 (const char *sym, tree id)
 {
-  const char *sym;
   rtx sym_ref;
-  tree id, decl;
-
-  sym = (const char *) node->key;
-  id = (tree) node->value;
+  tree decl;
 
   decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, ptr_type_node);
   SET_DECL_ASSEMBLER_NAME (decl, id);
@@ -930,8 +918,18 @@ dw2_output_indirect_constant_1 (splay_tree_node node,
 void
 dw2_output_indirect_constants (void)
 {
-  if (indirect_pool)
-    splay_tree_foreach (indirect_pool, dw2_output_indirect_constant_1, NULL);
+  if (!indirect_pool)
+    return;
+
+  auto_vec<std::pair<const char *, tree> > temp (indirect_pool->elements ());
+  for (hash_map<const char *, tree>::iterator iter = indirect_pool->begin ();
+       iter != indirect_pool->end (); ++iter)
+    temp.quick_push (*iter);
+
+    temp.qsort (compare_strings);
+
+    for (unsigned int i = 0; i < temp.length (); i++)
+    dw2_output_indirect_constant_1 (temp[i].first, temp[i].second);
 }
 
 /* Like dw2_asm_output_addr_rtx, but encode the pointer as directed.
diff --git a/gcc/hash-map.h b/gcc/hash-map.h
index a5816dc..f6fdc1c 100644
--- a/gcc/hash-map.h
+++ b/gcc/hash-map.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define hash_map_h
 
 #include <new>
+#include <utility>
 #include "hash-table.h"
 
 /* implement default behavior for traits when types allow it.  */
@@ -266,6 +267,39 @@ public:
 
   size_t elements () const { return m_table.elements (); }
 
+  class iterator
+  {
+  public:
+    explicit iterator (const typename hash_table<hash_entry>::iterator &iter) :
+      m_iter (iter) {}
+
+    iterator &operator++ ()
+    {
+      ++m_iter;
+      return *this;
+    }
+
+    std::pair<Key, Value> operator* ()
+    {
+      hash_entry &e = *m_iter;
+      return std::pair<Key, Value> (e.m_key, e.m_value);
+    }
+
+    bool
+    operator != (const iterator &other) const
+    {
+      return m_iter != other.m_iter;
+    }
+
+  private:
+    typename hash_table<hash_entry>::iterator m_iter;
+  };
+
+  /* Standard iterator retrieval methods.  */
+
+  iterator  begin () const { return iterator (m_table.begin ()); }
+  iterator end () const { return iterator (m_table.end ()); }
+
 private:
 
   template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index b59d069..b151430 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -9243,8 +9243,7 @@ lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
    requires that languages coordinate a symbol name.  It is therefore
    best put here in common code.  */
 
-static GTY((param1_is (tree), param2_is (tree)))
-  splay_tree critical_name_mutexes;
+static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
 
 static void
 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
@@ -9259,15 +9258,11 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
   if (name)
     {
       tree decl;
-      splay_tree_node n;
 
       if (!critical_name_mutexes)
-	critical_name_mutexes
-	  = splay_tree_new_ggc (splay_tree_compare_pointers,
-				ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_s,
-				ggc_alloc_splay_tree_tree_node_tree_node_splay_tree_node_s);
+	critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
 
-      n = splay_tree_lookup (critical_name_mutexes, (splay_tree_key) name);
+      tree *n = critical_name_mutexes->get (name);
       if (n == NULL)
 	{
 	  char *new_str;
@@ -9284,11 +9279,10 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
 	  DECL_IGNORED_P (decl) = 1;
 	  varpool_node::finalize_decl (decl);
 
-	  splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
-			     (splay_tree_value) decl);
+	  critical_name_mutexes->put (name, decl);
 	}
       else
-	decl = (tree) n->value;
+	decl = *n;
 
       lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
       lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
diff --git a/gcc/tree.h b/gcc/tree.h
index 9875a50..7bff405 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4862,4 +4862,9 @@ int_bit_position (const_tree field)
   return (wi::lshift (wi::to_offset (DECL_FIELD_OFFSET (field)), BITS_PER_UNIT_LOG)
 	  + wi::to_offset (DECL_FIELD_BIT_OFFSET (field))).to_shwi ();
 }
+
+extern void gt_ggc_mx (tree &);
+extern void gt_pch_nx (tree &);
+extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
+
 #endif  /* GCC_TREE_H  */
-- 
2.1.3

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/5] remove the remaining uses of if_marked
  2014-11-13  5:57 ` [PATCH 2/5] remove the remaining uses of if_marked tsaunders
@ 2014-11-13  6:52   ` Marek Polacek
  2014-11-14  0:49   ` Jeff Law
  1 sibling, 0 replies; 16+ messages in thread
From: Marek Polacek @ 2014-11-13  6:52 UTC (permalink / raw)
  To: tsaunders; +Cc: gcc-patches

On Thu, Nov 13, 2014 at 12:55:40AM -0500, tsaunders@mozilla.com wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index b70c56c..227509a 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -14032,14 +14032,34 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
>     to symbol DECL if BEIMPORT is true.  Otherwise create or return the
>     unique refptr-DECL symbol corresponding to symbol DECL.  */
>  
> -static GTY((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
> -  htab_t dllimport_map;
> +struct dllimport_hasher : ggc_cache_hasher<tree_map *>
> +{
> +  static inline hashval_t hash (tree_map *m) { return m->hash; }
> +  static inline bool
> +  equal (tree_map *a, tree_map *b)
> +  {
> +    return a->base.from == b->base.from;
> +  }
> +
> +  static void
> +    handle_cache_entry (tree_map *&m)
> +      {
> +	extern void gt_ggc_mx (tree_map *&);
> +	if (m == HTAB_EMPTY_ENTRY || m == HTAB_DELETED_ENTRY)
> +	  return;
> +	else if (ggc_marked_p (m->base.from))
> +	  gt_ggc_mx (m);
> +	else
> +	  m = static_cast<tree_map *> (HTAB_DELETED_ENTRY);
> +      }
> +};
> +

Note that the formatting is a bit off here (and in ubsan.c too).

	Marek

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] add an alternative to if_marked using hash_table
  2014-11-13  5:57 [PATCH 1/5] add an alternative to if_marked using hash_table tsaunders
                   ` (3 preceding siblings ...)
  2014-11-13  6:14 ` [PATCH 4/5] remove param$N_is usage tsaunders
@ 2014-11-14  0:37 ` Jeff Law
  2014-11-14  1:33   ` Trevor Saunders
  4 siblings, 1 reply; 16+ messages in thread
From: Jeff Law @ 2014-11-14  0:37 UTC (permalink / raw)
  To: tsaunders, gcc-patches

On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
>   This adds a gty cache attribute that calls user code after marking and before
> sweeping allowing user code to mark more objects or clear caches as
> appropriate.  User code for hash_table is set up to work similarly to if_marked
> for htab.
>
> bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
>
> Trev
>
>
> gcc/ChangeLog:
>
> 2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
>
> 	* doc/gty.texi: Document the new cache gty attribute.
> 	* gengtype.c (finish_cache_funcs): New function.
> 	(write_roots): Call gt_clear_cache on global variables with the cache
> 	gty attribute.
> 	* ggc-common.c (ggc_mark_roots): Call gt_clear_caches.
> 	* ggc.h (gt_clear_caches): New declaration.
> 	* hash-table.h (struct ggc_cache_hasher): New hasher for caches in gc
> 	memory.
> 	(gt_cleare_cache): New function.
> 	* emit-rtl.c, rtl.h, tree.c: Use hash_table instead of htab.
Presumably the goal here is continuing to move to the new style hash 
tables. So you need to support something like if_marked in the new sytle 
hash tables.  There really isn't any significant functional changes 
here, right?


> diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> index fac83ee..38c173f 100644
> --- a/gcc/gengtype.c
> +++ b/gcc/gengtype.c
> @@ -4482,6 +4482,58 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
>     }
>   }
>
> +static void
> +finish_cache_funcs (flist *flp)
Function comment missing.


> +
> +  /* clear out entries if there about to be gc'd.  */
s/there/they are/ ?
s/clear/Clear/


OK with the above nits fixed.

jeff

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/5] remove the remaining uses of if_marked
  2014-11-13  5:57 ` [PATCH 2/5] remove the remaining uses of if_marked tsaunders
  2014-11-13  6:52   ` Marek Polacek
@ 2014-11-14  0:49   ` Jeff Law
  2014-11-14  2:35     ` Trevor Saunders
  1 sibling, 1 reply; 16+ messages in thread
From: Jeff Law @ 2014-11-14  0:49 UTC (permalink / raw)
  To: tsaunders, gcc-patches

On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> $subject.
>
> bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
>
> Trev
>
>
> ada/
>
> 	* gcc-interface/decl.c, gcc-interface/utils.c: replace htab with
> 	hash_table.
>
> cp/
>
> 	* cp-objcp-common.c: Use hash_table instead of htab.
>
> gcc/
>
> 	* config/i386/i386.c, function.c, trans-mem.c, tree-core.h,
> 	tree.c, tree.h, ubsan.c, varasm.c: Use hash_table instead of htab.
OK.

Does it make sense to follow-up with a patch to drop the if_marked tag? 
  Or are we going to keep it for compatibility with plugins that might 
be using it in their hash tables?

jeff

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/5] fix hash_table when empty elements are not 0
  2014-11-13  5:57 ` [PATCH 3/5] fix hash_table when empty elements are not 0 tsaunders
@ 2014-11-14  0:52   ` Jeff Law
  0 siblings, 0 replies; 16+ messages in thread
From: Jeff Law @ 2014-11-14  0:52 UTC (permalink / raw)
  To: tsaunders, gcc-patches

On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> hi,
>
> The problem here is that hash_table used to zero element storage, but if the
> empty element is not 0 then all elements appear to be in use.
>
> bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
>
> Trev
>
>
> gcc/ChangeLog:
>
> 2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
>
> 	* hash-table.h (hash_table::hash_table): Call alloc_entries.
> 	(hash_table::alloc_entries): new method.
> 	(hash_table::expand): Call alloc_entries.
> 	(hash_table::empty): Likewise.
OK.
Jeff


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/5] use vec in lto_tree_ref_table
  2014-11-13  5:57 ` [PATCH 5/5] use vec in lto_tree_ref_table tsaunders
@ 2014-11-14  0:56   ` Jeff Law
  2014-11-14  2:04     ` Trevor Saunders
  2014-11-14 10:44   ` Richard Biener
  1 sibling, 1 reply; 16+ messages in thread
From: Jeff Law @ 2014-11-14  0:56 UTC (permalink / raw)
  To: tsaunders, gcc-patches

On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> gengtype fails to create valid user marking functions for this type, which is
> fixed by using vec here (which seems cleaner anyway).
>
> bootstrapped + regtested powerpc64-linux (gcc 110 since gcc20 died) ok?
>
> Trev
>
>
> gcc/ChangeLog:
>
> 2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
>
> 	* lto-section-in.c (lto_delete_in_decl_state): Adjust.
> 	(lto_free_function_in_decl_state): Likewise.
> 	* lto-streamer-out.c (copy_function_or_variable): Likewise.
> 	* lto-streamer.h (lto_file_decl_data_get_ ## name): Likewise.
> 	(lto_file_decl_data_num_ ## name ## s): Likewise.
> 	(struct lto_tree_ref_table): Remove.
> 	(struct lto_in_decl_state): Replace lto_tree_ref_table with vec<tree>.
>
> gcc/lto/ChangeLog:
>
> 2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
>
> 	* lto.c (lto_read_in_decl_state): Adjust.
> 	(lto_fixup_state): Likewise.
What is it about the data structure that's causing GGC grief?  Are there 
other data structures with similar enough characteristics that we need 
to fix them?  Is there any way to warn/error for this case?

I'm OK with the change, but it feels like there needs to be some 
research into other potential lossage and some preventative work to 
prevent similar problems in the future.

Thanks,
Jeff

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 4/5] remove param$N_is usage
  2014-11-13  6:14 ` [PATCH 4/5] remove param$N_is usage tsaunders
@ 2014-11-14  0:56   ` Jeff Law
  2014-11-14  2:34     ` Trevor Saunders
  0 siblings, 1 reply; 16+ messages in thread
From: Jeff Law @ 2014-11-14  0:56 UTC (permalink / raw)
  To: tsaunders, gcc-patches

On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> The only user of this is splay_tree.  We only have a couple splay trees in ggc
> memory, and it wasn't clear to me any of them were tree based instead of hash
> based for performance reasons, so I chose to just convert them to hash_map
> rather than writing a templated splay tree.
>
> bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
>
> trev
>
> gcc/
>
> 	* hash-map.h (hash_map::iterator): New class.
> 	(hash_map::begin): New method.
> 	(hash_map::end): Likewise.
> 	* alias.c, config/alpha/alpha.c, dwarf2asm.c, omp-low.c, tree.h:
> 	replace splay_tree with hash_map.
Splay trees in the alias code are very very old.  They came in with the 
initial "restrict" support from Mark Mitchell many many years ago.   I 
don't recall the reasoning behind using splay trees instead of hash 
tables or some other data structure.

In cases where you're removing the last remnants of a splay tree in a 
file, please make sure to remove the splay-tree include.

OK with the splay-tree include removal, but if we start to get reports 
that these data structures have become a bottleneck, we'll be looking to 
you to address that problem ;-)

jeff

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/5] add an alternative to if_marked using hash_table
  2014-11-14  0:37 ` [PATCH 1/5] add an alternative to if_marked using hash_table Jeff Law
@ 2014-11-14  1:33   ` Trevor Saunders
  0 siblings, 0 replies; 16+ messages in thread
From: Trevor Saunders @ 2014-11-14  1:33 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

On Thu, Nov 13, 2014 at 05:27:13PM -0700, Jeff Law wrote:
> On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> >From: Trevor Saunders <tsaunders@mozilla.com>
> >
> >Hi,
> >
> >  This adds a gty cache attribute that calls user code after marking and before
> >sweeping allowing user code to mark more objects or clear caches as
> >appropriate.  User code for hash_table is set up to work similarly to if_marked
> >for htab.
> >
> >bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
> >
> >Trev
> >
> >
> >gcc/ChangeLog:
> >
> >2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
> >
> >	* doc/gty.texi: Document the new cache gty attribute.
> >	* gengtype.c (finish_cache_funcs): New function.
> >	(write_roots): Call gt_clear_cache on global variables with the cache
> >	gty attribute.
> >	* ggc-common.c (ggc_mark_roots): Call gt_clear_caches.
> >	* ggc.h (gt_clear_caches): New declaration.
> >	* hash-table.h (struct ggc_cache_hasher): New hasher for caches in gc
> >	memory.
> >	(gt_cleare_cache): New function.
> >	* emit-rtl.c, rtl.h, tree.c: Use hash_table instead of htab.
> Presumably the goal here is continuing to move to the new style hash tables.
> So you need to support something like if_marked in the new sytle hash
> tables.  There really isn't any significant functional changes here, right?

to how the compiler it self work no, and the new mechanism is pretty
similar to if_marked.

> 
> 
> >diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> >index fac83ee..38c173f 100644
> >--- a/gcc/gengtype.c
> >+++ b/gcc/gengtype.c
> >@@ -4482,6 +4482,58 @@ finish_root_table (struct flist *flp, const char *pfx, const char *lastname,
> >    }
> >  }
> >
> >+static void
> >+finish_cache_funcs (flist *flp)
> Function comment missing.

oops

> 
> >+
> >+  /* clear out entries if there about to be gc'd.  */
> s/there/they are/ ?
> s/clear/Clear/

I hope one day I'll write reasonable english ;-)

thanks!

Trev

> 
> 
> OK with the above nits fixed.
> 
> jeff
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/5] use vec in lto_tree_ref_table
  2014-11-14  0:56   ` Jeff Law
@ 2014-11-14  2:04     ` Trevor Saunders
  0 siblings, 0 replies; 16+ messages in thread
From: Trevor Saunders @ 2014-11-14  2:04 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

On Thu, Nov 13, 2014 at 05:52:51PM -0700, Jeff Law wrote:
> On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> >From: Trevor Saunders <tsaunders@mozilla.com>
> >
> >Hi,
> >
> >gengtype fails to create valid user marking functions for this type, which is
> >fixed by using vec here (which seems cleaner anyway).
> >
> >bootstrapped + regtested powerpc64-linux (gcc 110 since gcc20 died) ok?
> >
> >Trev
> >
> >
> >gcc/ChangeLog:
> >
> >2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
> >
> >	* lto-section-in.c (lto_delete_in_decl_state): Adjust.
> >	(lto_free_function_in_decl_state): Likewise.
> >	* lto-streamer-out.c (copy_function_or_variable): Likewise.
> >	* lto-streamer.h (lto_file_decl_data_get_ ## name): Likewise.
> >	(lto_file_decl_data_num_ ## name ## s): Likewise.
> >	(struct lto_tree_ref_table): Remove.
> >	(struct lto_in_decl_state): Replace lto_tree_ref_table with vec<tree>.
> >
> >gcc/lto/ChangeLog:
> >
> >2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
> >
> >	* lto.c (lto_read_in_decl_state): Adjust.
> >	(lto_fixup_state): Likewise.
> What is it about the data structure that's causing GGC grief?  Are there

A couple things come together here

1 user pch routines don't have separate this_obj and x_p arguments, they
  expect they only need to mark one object.
2 gengtype does the marking for the lto_tree_ref_table within the
   routine for lto_in_decl_state.  This means it needs to check if
   this_obj is the same as x_p.

the combination results in a user pch marking routine trying to check if
this_obj == x_p when there is no this_obj argument.

> other data structures with similar enough characteristics that we need to
> fix them?  Is there any way to warn/error for this case?

I think its roughly when an object or a subobject there of has a pointer
to an array of pointers.  I'm not sure how to find all the effected
types other than by adding for_user everywhere and seeing what breaks,
but that could expose other problems and I think will happen soon enough
anyway.

 we could make gengtype handle this better urrently it just emits
 invalid C++.  I 'd like to make gengtype always use user style marking
 routines and remove the custom mangling, which I suspect will require
 either fixing all the types with problems like this or making gengtype
 emit correct code for them.

> I'm OK with the change, but it feels like there needs to be some research
> into other potential lossage and some preventative work to prevent similar
> problems in the future.

 yeah, this is kind of a cheap way of dealing with the problem, on the
 other hand I tend to think its a decent clean up on its own.

 Trev

> 
> Thanks,
> Jeff

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 4/5] remove param$N_is usage
  2014-11-14  0:56   ` Jeff Law
@ 2014-11-14  2:34     ` Trevor Saunders
  0 siblings, 0 replies; 16+ messages in thread
From: Trevor Saunders @ 2014-11-14  2:34 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

On Thu, Nov 13, 2014 at 05:49:47PM -0700, Jeff Law wrote:
> On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> >From: Trevor Saunders <tsaunders@mozilla.com>
> >
> >Hi,
> >
> >The only user of this is splay_tree.  We only have a couple splay trees in ggc
> >memory, and it wasn't clear to me any of them were tree based instead of hash
> >based for performance reasons, so I chose to just convert them to hash_map
> >rather than writing a templated splay tree.
> >
> >bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
> >
> >trev
> >
> >gcc/
> >
> >	* hash-map.h (hash_map::iterator): New class.
> >	(hash_map::begin): New method.
> >	(hash_map::end): Likewise.
> >	* alias.c, config/alpha/alpha.c, dwarf2asm.c, omp-low.c, tree.h:
> >	replace splay_tree with hash_map.
> Splay trees in the alias code are very very old.  They came in with the
> initial "restrict" support from Mark Mitchell many many years ago.   I don't
> recall the reasoning behind using splay trees instead of hash tables or some
> other data structure.

 fair enough, I could believe it was a case of what was handy,
 splay_tree does make a nicer map than htab.

> In cases where you're removing the last remnants of a splay tree in a file,
> please make sure to remove the splay-tree include.

sure

> OK with the splay-tree include removal, but if we start to get reports that
> these data structures have become a bottleneck, we'll be looking to you to
> address that problem ;-)

of course, a C++ splay tree shouldn't be too hard, but the only use for
it I can see is ggc stuff where std::map won't really work.

thanks!

Trev

> 
> jeff
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/5] remove the remaining uses of if_marked
  2014-11-14  0:49   ` Jeff Law
@ 2014-11-14  2:35     ` Trevor Saunders
  0 siblings, 0 replies; 16+ messages in thread
From: Trevor Saunders @ 2014-11-14  2:35 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches

On Thu, Nov 13, 2014 at 05:32:08PM -0700, Jeff Law wrote:
> On 11/12/14 22:55, tsaunders@mozilla.com wrote:
> >From: Trevor Saunders <tsaunders@mozilla.com>
> >
> >Hi,
> >
> >$subject.
> >
> >bootstrapped + regtested x86_64-unknown-linux-gnu, ok?
> >
> >Trev
> >
> >
> >ada/
> >
> >	* gcc-interface/decl.c, gcc-interface/utils.c: replace htab with
> >	hash_table.
> >
> >cp/
> >
> >	* cp-objcp-common.c: Use hash_table instead of htab.
> >
> >gcc/
> >
> >	* config/i386/i386.c, function.c, trans-mem.c, tree-core.h,
> >	tree.c, tree.h, ubsan.c, varasm.c: Use hash_table instead of htab.
> OK.
> 
> Does it make sense to follow-up with a patch to drop the if_marked tag?  Or
> are we going to keep it for compatibility with plugins that might be using
> it in their hash tables?

Its looking tight, but I'm still hopeful I can remove if_marked,
param_is and the splay tree allocator stuff from gengtype this stage 1.

thanks!

Trev

> 
> jeff
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 5/5] use vec in lto_tree_ref_table
  2014-11-13  5:57 ` [PATCH 5/5] use vec in lto_tree_ref_table tsaunders
  2014-11-14  0:56   ` Jeff Law
@ 2014-11-14 10:44   ` Richard Biener
  1 sibling, 0 replies; 16+ messages in thread
From: Richard Biener @ 2014-11-14 10:44 UTC (permalink / raw)
  To: tsaunders; +Cc: GCC Patches

On Thu, Nov 13, 2014 at 6:55 AM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> gengtype fails to create valid user marking functions for this type, which is
> fixed by using vec here (which seems cleaner anyway).
>
> bootstrapped + regtested powerpc64-linux (gcc 110 since gcc20 died) ok?

Ok.

Thanks,
Richard.

> Trev
>
>
> gcc/ChangeLog:
>
> 2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * lto-section-in.c (lto_delete_in_decl_state): Adjust.
>         (lto_free_function_in_decl_state): Likewise.
>         * lto-streamer-out.c (copy_function_or_variable): Likewise.
>         * lto-streamer.h (lto_file_decl_data_get_ ## name): Likewise.
>         (lto_file_decl_data_num_ ## name ## s): Likewise.
>         (struct lto_tree_ref_table): Remove.
>         (struct lto_in_decl_state): Replace lto_tree_ref_table with vec<tree>.
>
> gcc/lto/ChangeLog:
>
> 2014-11-13  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * lto.c (lto_read_in_decl_state): Adjust.
>         (lto_fixup_state): Likewise.
>
>
> diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
> index 042dd99..75f394d 100644
> --- a/gcc/lto-section-in.c
> +++ b/gcc/lto-section-in.c
> @@ -379,8 +379,7 @@ lto_delete_in_decl_state (struct lto_in_decl_state *state)
>    int i;
>
>    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
> -    if (state->streams[i].trees)
> -      ggc_free (state->streams[i].trees);
> +    vec_free (state->streams[i]);
>    ggc_free (state);
>  }
>
> @@ -429,7 +428,7 @@ lto_free_function_in_decl_state (struct lto_in_decl_state *state)
>  {
>    int i;
>    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
> -    ggc_free (state->streams[i].trees);
> +    vec_free (state->streams[i]);
>    ggc_free (state);
>  }
>
> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> index dc406da..bc18a9c 100644
> --- a/gcc/lto-streamer-out.c
> +++ b/gcc/lto-streamer-out.c
> @@ -2186,8 +2186,8 @@ copy_function_or_variable (struct symtab_node *node)
>
>    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
>      {
> -      size_t n = in_state->streams[i].size;
> -      tree *trees = in_state->streams[i].trees;
> +      size_t n = vec_safe_length (in_state->streams[i]);
> +      vec<tree, va_gc> *trees = in_state->streams[i];
>        struct lto_tree_ref_encoder *encoder = &(out_state->streams[i]);
>
>        /* The out state must have the same indices and the in state.
> @@ -2196,7 +2196,7 @@ copy_function_or_variable (struct symtab_node *node)
>        gcc_assert (lto_tree_ref_encoder_size (encoder) == 0);
>        encoder->trees.reserve_exact (n);
>        for (j = 0; j < n; j++)
> -       encoder->trees.safe_push (trees[j]);
> +       encoder->trees.safe_push ((*trees)[j]);
>      }
>
>    lto_free_section_data (file_data, LTO_section_function_body, name,
> diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
> index 4b875a2..9d6d7a0 100644
> --- a/gcc/lto-streamer.h
> +++ b/gcc/lto-streamer.h
> @@ -274,15 +274,14 @@ lto_file_decl_data_get_ ## name (struct lto_file_decl_data *data, \
>                                  unsigned int idx) \
>  { \
>    struct lto_in_decl_state *state = data->current_decl_state; \
> -  gcc_assert (idx < state->streams[LTO_DECL_STREAM_## UPPER_NAME].size); \
> -  return state->streams[LTO_DECL_STREAM_## UPPER_NAME].trees[idx]; \
> +   return (*state->streams[LTO_DECL_STREAM_## UPPER_NAME])[idx]; \
>  } \
>  \
>  static inline unsigned int \
>  lto_file_decl_data_num_ ## name ## s (struct lto_file_decl_data *data) \
>  { \
>    struct lto_in_decl_state *state = data->current_decl_state; \
> -  return state->streams[LTO_DECL_STREAM_## UPPER_NAME].size; \
> +  return vec_safe_length (state->streams[LTO_DECL_STREAM_## UPPER_NAME]); \
>  }
>
>
> @@ -420,18 +419,6 @@ struct lto_symtab_encoder_iterator
>
>
>
> -
> -/* Mapping from indices to trees.  */
> -struct GTY(()) lto_tree_ref_table
> -{
> -  /* Array of referenced trees . */
> -  tree * GTY((length ("%h.size"))) trees;
> -
> -  /* Size of array. */
> -  unsigned int size;
> -};
> -
> -
>  /* The lto_tree_ref_encoder struct is used to encode trees into indices. */
>
>  struct lto_tree_ref_encoder
> @@ -445,7 +432,7 @@ struct lto_tree_ref_encoder
>  struct GTY(()) lto_in_decl_state
>  {
>    /* Array of lto_in_decl_buffers to store type and decls streams. */
> -  struct lto_tree_ref_table streams[LTO_N_DECL_STREAMS];
> +  vec<tree, va_gc> *streams[LTO_N_DECL_STREAMS];
>
>    /* If this in-decl state is associated with a function. FN_DECL
>       point to the FUNCTION_DECL. */
> diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
> index d8519d9..cdd2331 100644
> --- a/gcc/lto/lto.c
> +++ b/gcc/lto/lto.c
> @@ -260,13 +260,15 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
>    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
>      {
>        uint32_t size = *data++;
> -      tree *decls = ggc_vec_alloc<tree> (size);
> +      vec<tree, va_gc> *decls = NULL;
> +      vec_alloc (decls, size);
>
>        for (j = 0; j < size; j++)
> -       decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
> +       vec_safe_push (decls,
> +                      streamer_tree_cache_get_tree (data_in->reader_cache,
> +                                                    data[j]));
>
> -      state->streams[i].size = size;
> -      state->streams[i].trees = decls;
> +      state->streams[i] = decls;
>        data += size;
>      }
>
> @@ -2806,20 +2808,19 @@ static void
>  lto_fixup_state (struct lto_in_decl_state *state)
>  {
>    unsigned i, si;
> -  struct lto_tree_ref_table *table;
>
>    /* Although we only want to replace FUNCTION_DECLs and VAR_DECLs,
>       we still need to walk from all DECLs to find the reachable
>       FUNCTION_DECLs and VAR_DECLs.  */
>    for (si = 0; si < LTO_N_DECL_STREAMS; si++)
>      {
> -      table = &state->streams[si];
> -      for (i = 0; i < table->size; i++)
> +      vec<tree, va_gc> *trees = state->streams[si];
> +      for (i = 0; i < vec_safe_length (trees); i++)
>         {
> -         tree *tp = table->trees + i;
> -         if (VAR_OR_FUNCTION_DECL_P (*tp)
> -             && (TREE_PUBLIC (*tp) || DECL_EXTERNAL (*tp)))
> -           *tp = lto_symtab_prevailing_decl (*tp);
> +         tree t = (*trees)[i];
> +         if (VAR_OR_FUNCTION_DECL_P (t)
> +             && (TREE_PUBLIC (t) || DECL_EXTERNAL (t)))
> +           (*trees)[i] = lto_symtab_prevailing_decl (t);
>         }
>      }
>  }
> --
> 2.1.3
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2014-11-14 10:37 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-13  5:57 [PATCH 1/5] add an alternative to if_marked using hash_table tsaunders
2014-11-13  5:57 ` [PATCH 5/5] use vec in lto_tree_ref_table tsaunders
2014-11-14  0:56   ` Jeff Law
2014-11-14  2:04     ` Trevor Saunders
2014-11-14 10:44   ` Richard Biener
2014-11-13  5:57 ` [PATCH 3/5] fix hash_table when empty elements are not 0 tsaunders
2014-11-14  0:52   ` Jeff Law
2014-11-13  5:57 ` [PATCH 2/5] remove the remaining uses of if_marked tsaunders
2014-11-13  6:52   ` Marek Polacek
2014-11-14  0:49   ` Jeff Law
2014-11-14  2:35     ` Trevor Saunders
2014-11-13  6:14 ` [PATCH 4/5] remove param$N_is usage tsaunders
2014-11-14  0:56   ` Jeff Law
2014-11-14  2:34     ` Trevor Saunders
2014-11-14  0:37 ` [PATCH 1/5] add an alternative to if_marked using hash_table Jeff Law
2014-11-14  1:33   ` Trevor Saunders

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).