public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table
@ 2014-06-20  6:41 Jan Hubicka
  2014-06-20 10:57 ` Trevor Saunders
  2014-06-21  8:26 ` Andreas Schwab
  0 siblings, 2 replies; 4+ messages in thread
From: Jan Hubicka @ 2014-06-20  6:41 UTC (permalink / raw)
  To: gcc-patches

Hi,
this patch moves init and fini priorities to symbol table instead of trees.
They are already in on-side hashtables, but the hashtables are now maintaned
by symbol table.  This is needed for correctness with LTO.

Currently tree merging may load declaration with priority and then ggc_free
it creating a stale entry in the hashtable.  This is usually not problem, because
ctor declarations are usually static, but it is not safe.

I would really like to have template for such a sparse annotations to symbols
(writting our old school pch friendly hashtable is not a fun) but I am not sure
I can get it done in GGC/PCH safe way. Is user marking working for PCH?

Bootstrapped/regtested x86_64-linux, will commit it shortly.

Honza

	* cgraph.h (struct symtab_node): Add field in_init_priority_hash
	(set_init_priority, get_init_priority, set_fini_priority,
	get_fini_priority): New methods.
	* tree.c (init_priority_for_decl): Remove.
	(init_ttree): Do not initialize init priority.
	(decl_init_priority_lookup, decl_fini_priority_lookup): Rewrite.
	(decl_priority_info): Remove.
	(decl_init_priority_insert): Rewrite.
	(decl_fini_priority_insert): Rewrite.
	* tree.h (tree_priority_map_eq, tree_priority_map_hash,
	tree_priority_map_marked_p): Remove.
	* lto-cgraph.c (lto_output_node, input_node): Stream init priorities.
	* lto-streamer-out.c (hash_tree): Do not hash priorities.
	* tree-streamer-out.c (pack_ts_decl_with_vis_value_fields): Do
	not output priorities.
	(pack_ts_function_decl_value_fields): Likewise.
	* tree-streamer-in.c (unpack_ts_decl_with_vis_value_fields): Do
	not input priorities.
	(unpack_ts_function_decl_value_fields): Likewise.
	* symtab.c (symbol_priority_map): Declare.
	(init_priority_hash): Declare.
	(symtab_unregister_node): Unregister from priority hash, too.
	(symtab_node::get_init_priority, cgraph_node::get_fini_priority):
	New methods.
	(symbol_priority_map_eq, symbol_priority_map_hash): New functions.
	(symbol_priority_info): New function.
	(symtab_node::set_init_priority, cgraph_node::set_fini_priority):
	New methods.
	* tree-core.h (tree_priority_map): Remove.

	* lto.c (compare_tree_sccs_1): Do not compare priorities.
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 211831)
+++ cgraph.h	(working copy)
@@ -130,6 +130,8 @@ public:
 
   /* Set when symbol has address taken. */
   unsigned address_taken : 1;
+  /* Set when init priority is set.  */
+  unsigned in_init_priority_hash : 1;
 
 
   /* Ordering of all symtab entries.  */
@@ -163,6 +165,7 @@ public:
       return x_comdat_group;
     }
 
+  /* Return comdat group as identifier_node.  */
   tree get_comdat_group_id ()
     {
       if (x_comdat_group && TREE_CODE (x_comdat_group) != IDENTIFIER_NODE)
@@ -208,6 +211,9 @@ public:
   /* Set section for symbol and its aliases.  */
   void set_section (const char *section);
   void set_section_for_node (const char *section);
+
+  void set_init_priority (priority_type priority);
+  priority_type get_init_priority ();
 };
 
 enum availability
@@ -497,6 +503,9 @@ public:
   /* True if this decl calls a COMDAT-local function.  This is set up in
      compute_inline_parameters and inline_call.  */
   unsigned calls_comdat_local : 1;
+
+  void set_fini_priority (priority_type priority);
+  priority_type get_fini_priority ();
 };
 
 
Index: tree.c
===================================================================
--- tree.c	(revision 211831)
+++ tree.c	(working copy)
@@ -219,10 +219,6 @@ static GTY ((if_marked ("tree_decl_map_m
 static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)))
      htab_t debug_args_for_decl;
 
-static GTY ((if_marked ("tree_priority_map_marked_p"),
-	     param_is (struct tree_priority_map)))
-  htab_t init_priority_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 *);
@@ -573,8 +569,6 @@ init_ttree (void)
 
   value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
 					 tree_decl_map_eq, 0);
-  init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash,
-					    tree_priority_map_eq, 0);
 
   int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
 					int_cst_hash_eq, NULL);
@@ -6492,13 +6486,12 @@ tree_decl_map_hash (const void *item)
 priority_type
 decl_init_priority_lookup (tree decl)
 {
-  struct tree_priority_map *h;
-  struct tree_map_base in;
+  symtab_node *snode = symtab_get_node (decl);
 
-  gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
-  in.from = decl;
-  h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in);
-  return h ? h->init : DEFAULT_INIT_PRIORITY;
+  if (!snode)
+    return DEFAULT_INIT_PRIORITY;
+  return
+    snode->get_init_priority ();
 }
 
 /* Return the finalization priority for DECL.  */
@@ -6506,39 +6499,12 @@ decl_init_priority_lookup (tree decl)
 priority_type
 decl_fini_priority_lookup (tree decl)
 {
-  struct tree_priority_map *h;
-  struct tree_map_base in;
-
-  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
-  in.from = decl;
-  h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in);
-  return h ? h->fini : DEFAULT_INIT_PRIORITY;
-}
-
-/* Return the initialization and finalization priority information for
-   DECL.  If there is no previous priority information, a freshly
-   allocated structure is returned.  */
-
-static struct tree_priority_map *
-decl_priority_info (tree decl)
-{
-  struct tree_priority_map in;
-  struct tree_priority_map *h;
-  void **loc;
-
-  in.base.from = decl;
-  loc = htab_find_slot (init_priority_for_decl, &in, INSERT);
-  h = (struct tree_priority_map *) *loc;
-  if (!h)
-    {
-      h = ggc_cleared_alloc<tree_priority_map> ();
-      *loc = h;
-      h->base.from = decl;
-      h->init = DEFAULT_INIT_PRIORITY;
-      h->fini = DEFAULT_INIT_PRIORITY;
-    }
+  cgraph_node *node = cgraph_get_node (decl);
 
-  return h;
+  if (!node)
+    return DEFAULT_INIT_PRIORITY;
+  return
+    node->get_fini_priority ();
 }
 
 /* Set the initialization priority for DECL to PRIORITY.  */
@@ -6546,13 +6512,19 @@ decl_priority_info (tree decl)
 void
 decl_init_priority_insert (tree decl, priority_type priority)
 {
-  struct tree_priority_map *h;
+  struct symtab_node *snode;
 
-  gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
   if (priority == DEFAULT_INIT_PRIORITY)
-    return;
-  h = decl_priority_info (decl);
-  h->init = priority;
+    {
+      snode = symtab_get_node (decl);
+      if (!snode)
+	return;
+    }
+  else if (TREE_CODE (decl) == VAR_DECL)
+    snode = varpool_node_for_decl (decl);
+  else
+    snode = cgraph_get_create_node (decl);
+  snode->set_init_priority (priority);
 }
 
 /* Set the finalization priority for DECL to PRIORITY.  */
@@ -6560,13 +6532,17 @@ decl_init_priority_insert (tree decl, pr
 void
 decl_fini_priority_insert (tree decl, priority_type priority)
 {
-  struct tree_priority_map *h;
+  struct cgraph_node *node;
 
-  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
   if (priority == DEFAULT_INIT_PRIORITY)
-    return;
-  h = decl_priority_info (decl);
-  h->fini = priority;
+    {
+      node = cgraph_get_node (decl);
+      if (!node)
+	return;
+    }
+  else
+    node = cgraph_get_create_node (decl);
+  node->set_fini_priority (priority);
 }
 
 /* Print out the statistics for the DECL_DEBUG_EXPR hash table.  */
Index: tree.h
===================================================================
--- tree.h	(revision 211831)
+++ tree.h	(working copy)
@@ -4345,10 +4345,6 @@ extern unsigned int tree_decl_map_hash (
 #define tree_int_map_hash tree_map_base_hash
 #define tree_int_map_marked_p tree_map_base_marked_p
 
-#define tree_priority_map_eq tree_map_base_eq
-#define tree_priority_map_hash tree_map_base_hash
-#define tree_priority_map_marked_p tree_map_base_marked_p
-
 #define tree_vec_map_eq tree_map_base_eq
 #define tree_vec_map_hash tree_decl_map_hash
 #define tree_vec_map_marked_p tree_map_base_marked_p
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 211831)
+++ lto-cgraph.c	(working copy)
@@ -557,6 +557,10 @@ lto_output_node (struct lto_simple_outpu
       streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
     }
   streamer_write_hwi_stream (ob->main_stream, node->profile_id);
+  if (DECL_STATIC_CONSTRUCTOR (node->decl))
+    streamer_write_hwi_stream (ob->main_stream, DECL_INIT_PRIORITY (node->decl));
+  if (DECL_STATIC_DESTRUCTOR (node->decl))
+    streamer_write_hwi_stream (ob->main_stream, DECL_FINI_PRIORITY (node->decl));
 }
 
 /* Output the varpool NODE to OB. 
@@ -1210,6 +1214,10 @@ input_node (struct lto_file_decl_data *f
   if (node->alias && !node->analyzed && node->weakref)
     node->alias_target = get_alias_symbol (node->decl);
   node->profile_id = streamer_read_hwi (ib);
+  if (DECL_STATIC_CONSTRUCTOR (node->decl))
+    SET_DECL_INIT_PRIORITY (node->decl, streamer_read_hwi (ib));
+  if (DECL_STATIC_DESTRUCTOR (node->decl))
+    SET_DECL_FINI_PRIORITY (node->decl, streamer_read_hwi (ib));
   return node;
 }
 
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 211831)
+++ lto-streamer-out.c	(working copy)
@@ -827,8 +827,6 @@ hash_tree (struct streamer_tree_cache_d
 					  | (DECL_CXX_CONSTRUCTOR_P (t) << 1)
 					  | (DECL_CXX_DESTRUCTOR_P (t) << 2),
 					  v);
-      if (VAR_OR_FUNCTION_DECL_P (t))
-	v = iterative_hash_host_wide_int (DECL_INIT_PRIORITY (t), v);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
@@ -852,8 +850,6 @@ hash_tree (struct streamer_tree_cache_d
 					| (DECL_LOOPING_CONST_OR_PURE_P (t) << 15), v);
       if (DECL_BUILT_IN_CLASS (t) != NOT_BUILT_IN)
 	v = iterative_hash_host_wide_int (DECL_FUNCTION_CODE (t), v);
-      if (DECL_STATIC_DESTRUCTOR (t))
-	v = iterative_hash_host_wide_int (DECL_FINI_PRIORITY (t), v);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 211831)
+++ lto/lto.c	(working copy)
@@ -1300,8 +1300,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t
           /* DECL_IN_TEXT_SECTION is set during final asm output only.  */
 	  compare_values (DECL_IN_CONSTANT_POOL);
 	}
-      if (VAR_OR_FUNCTION_DECL_P (t1))
-	compare_values (DECL_INIT_PRIORITY);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
@@ -1328,8 +1326,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t
       compare_values (DECL_CXX_DESTRUCTOR_P);
       if (DECL_BUILT_IN_CLASS (t1) != NOT_BUILT_IN)
 	compare_values (DECL_FUNCTION_CODE);
-      if (DECL_STATIC_DESTRUCTOR (t1))
-	compare_values (DECL_FINI_PRIORITY);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
Index: tree-streamer-out.c
===================================================================
--- tree-streamer-out.c	(revision 211831)
+++ tree-streamer-out.c	(working copy)
@@ -256,8 +256,6 @@ pack_ts_decl_with_vis_value_fields (stru
       bp_pack_value (bp, DECL_CXX_CONSTRUCTOR_P (expr), 1);
       bp_pack_value (bp, DECL_CXX_DESTRUCTOR_P (expr), 1);
     }
-  if (VAR_OR_FUNCTION_DECL_P (expr))
-    bp_pack_var_len_unsigned (bp, DECL_INIT_PRIORITY (expr));
 }
 
 
@@ -291,8 +289,6 @@ pack_ts_function_decl_value_fields (stru
   bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1);
   if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
     bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 11);
-  if (DECL_STATIC_DESTRUCTOR (expr))
-    bp_pack_var_len_unsigned (bp, DECL_FINI_PRIORITY (expr));
 }
 
 
Index: tree-streamer-in.c
===================================================================
--- tree-streamer-in.c	(revision 211831)
+++ tree-streamer-in.c	(working copy)
@@ -288,12 +288,6 @@ unpack_ts_decl_with_vis_value_fields (st
       DECL_CXX_CONSTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
       DECL_CXX_DESTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
     }
-  if (VAR_OR_FUNCTION_DECL_P (expr))
-    {
-      priority_type p;
-      p = (priority_type) bp_unpack_var_len_unsigned (bp);
-      SET_DECL_INIT_PRIORITY (expr, p);
-    }
 }
 
 
@@ -336,12 +330,6 @@ unpack_ts_function_decl_value_fields (st
 	    fatal_error ("target specific builtin not available");
 	}
     }
-  if (DECL_STATIC_DESTRUCTOR (expr))
-    {
-      priority_type p;
-      p = (priority_type) bp_unpack_var_len_unsigned (bp);
-      SET_DECL_FINI_PRIORITY (expr, p);
-    }
 }
 
 
Index: symtab.c
===================================================================
--- symtab.c	(revision 211831)
+++ symtab.c	(working copy)
@@ -64,6 +64,17 @@ static GTY((param_is (section_hash_entry
 /* Hash table used to convert assembler names into nodes.  */
 static GTY((param_is (symtab_node))) htab_t assembler_name_hash;
 
+/* Map from a symbol to initialization/finalization priorities.  */
+struct GTY(()) symbol_priority_map {
+  symtab_node *symbol;
+  priority_type init;
+  priority_type fini;
+};
+
+/* Hash table used to hold init priorities.  */
+static GTY ((param_is (struct symbol_priority_map)))
+  htab_t init_priority_hash;
+
 /* Linked list of symbol table nodes.  */
 symtab_node *symtab_nodes;
 
@@ -337,6 +348,16 @@ symtab_unregister_node (symtab_node *nod
     }
   if (!is_a <varpool_node *> (node) || !DECL_HARD_REGISTER (node->decl))
     unlink_from_assembler_name_hash (node, false);
+  if (node->in_init_priority_hash)
+    {
+      struct symbol_priority_map in;
+      void **slot;
+      in.symbol = node;
+
+      slot = htab_find_slot (init_priority_hash, &in, NO_INSERT);
+      if (slot)
+	htab_clear_slot (init_priority_hash, slot);
+    }
 }
 
 
@@ -1176,6 +1197,122 @@ symtab_node::set_section (const char *se
   symtab_for_node_and_aliases (this, set_section_1, const_cast<char *>(section), true);
 }
 
+/* Return the initialization priority.  */
+
+priority_type
+symtab_node::get_init_priority ()
+{
+  struct symbol_priority_map *h;
+  struct symbol_priority_map in;
+
+  if (!this->in_init_priority_hash)
+    return DEFAULT_INIT_PRIORITY;
+  in.symbol = this;
+  h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in);
+  return h ? h->init : DEFAULT_INIT_PRIORITY;
+}
+
+/* Return the finalization priority.  */
+
+priority_type
+cgraph_node::get_fini_priority ()
+{
+  struct symbol_priority_map *h;
+  struct symbol_priority_map in;
+
+  if (!this->in_init_priority_hash)
+    return DEFAULT_INIT_PRIORITY;
+  in.symbol = this;
+  h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in);
+  return h ? h->fini : DEFAULT_INIT_PRIORITY;
+}
+
+/* Return true if the from tree in both priority maps are equal.  */
+
+int
+symbol_priority_map_eq (const void *va, const void *vb)
+{
+  const struct symbol_priority_map *const a = (const struct symbol_priority_map *) va,
+    *const b = (const struct symbol_priority_map *) vb;
+  return (a->symbol == b->symbol);
+}
+
+/* Hash a from symbol in a symbol_priority_map.  */
+
+unsigned int
+symbol_priority_map_hash (const void *item)
+{
+  return htab_hash_pointer (((const struct symbol_priority_map *)item)->symbol);
+}
+
+/* Return the initialization and finalization priority information for
+   DECL.  If there is no previous priority information, a freshly
+   allocated structure is returned.  */
+
+static struct symbol_priority_map *
+symbol_priority_info (struct symtab_node *symbol)
+{
+  struct symbol_priority_map in;
+  struct symbol_priority_map *h;
+  void **loc;
+
+  in.symbol = symbol;
+  if (!init_priority_hash)
+    init_priority_hash = htab_create_ggc (512, symbol_priority_map_hash,
+                                          symbol_priority_map_eq, 0);
+
+  loc = htab_find_slot (init_priority_hash, &in, INSERT);
+  h = (struct symbol_priority_map *) *loc;
+  if (!h)
+    {
+      h = ggc_cleared_alloc<symbol_priority_map> ();
+      *loc = h;
+      h->symbol = symbol;
+      h->init = DEFAULT_INIT_PRIORITY;
+      h->fini = DEFAULT_INIT_PRIORITY;
+      symbol->in_init_priority_hash = true;
+    }
+
+  return h;
+}
+
+/* Set initialization priority to PRIORITY.  */
+
+void
+symtab_node::set_init_priority (priority_type priority)
+{
+  struct symbol_priority_map *h;
+
+  if (is_a <cgraph_node *> (this))
+    gcc_assert (DECL_STATIC_CONSTRUCTOR (this->decl));
+
+  if (priority == DEFAULT_INIT_PRIORITY)
+    {
+      gcc_assert (get_init_priority() == priority);
+      return;
+    }
+  h = symbol_priority_info (this);
+  h->init = priority;
+}
+
+/* Set fialization priority to PRIORITY.  */
+
+void
+cgraph_node::set_fini_priority (priority_type priority)
+{
+  struct symbol_priority_map *h;
+
+  gcc_assert (DECL_STATIC_DESTRUCTOR (this->decl));
+
+  if (priority == DEFAULT_INIT_PRIORITY)
+    {
+      gcc_assert (get_fini_priority() == priority);
+      return;
+    }
+  h = symbol_priority_info (this);
+  h->fini = priority;
+}
+
 /* Worker for symtab_resolve_alias.  */
 
 static bool
Index: tree-core.h
===================================================================
--- tree-core.h	(revision 211831)
+++ tree-core.h	(working copy)
@@ -1761,13 +1761,6 @@ struct GTY(()) tree_int_map {
   unsigned int to;
 };
 
-/* Map from a tree to initialization/finalization priorities.  */
-struct GTY(()) tree_priority_map {
-  struct tree_map_base base;
-  priority_type init;
-  priority_type fini;
-};
-
 /* Map from a decl tree to a tree vector.  */
 struct GTY(()) tree_vec_map {
   struct tree_map_base base;

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

* Re: Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table
  2014-06-20  6:41 Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table Jan Hubicka
@ 2014-06-20 10:57 ` Trevor Saunders
  2014-06-21  8:26 ` Andreas Schwab
  1 sibling, 0 replies; 4+ messages in thread
From: Trevor Saunders @ 2014-06-20 10:57 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc-patches

On Fri, Jun 20, 2014 at 08:41:22AM +0200, Jan Hubicka wrote:
> Hi,
> this patch moves init and fini priorities to symbol table instead of trees.
> They are already in on-side hashtables, but the hashtables are now maintaned
> by symbol table.  This is needed for correctness with LTO.
> 
> Currently tree merging may load declaration with priority and then ggc_free
> it creating a stale entry in the hashtable.  This is usually not problem, because
> ctor declarations are usually static, but it is not safe.
> 
> I would really like to have template for such a sparse annotations to symbols
> (writting our old school pch friendly hashtable is not a fun) but I am not sure
> I can get it done in GGC/PCH safe way. Is user marking working for PCH?

hm, so thinking about this a little more I wonder if you can just use
hash_table, and add a dtor to symtab_node that removes its entry from
the hash table.  ggc should invoke your dtor as a finalizer for the node
then.

Trev

> 
> Bootstrapped/regtested x86_64-linux, will commit it shortly.
> 
> Honza
> 
> 	* cgraph.h (struct symtab_node): Add field in_init_priority_hash
> 	(set_init_priority, get_init_priority, set_fini_priority,
> 	get_fini_priority): New methods.
> 	* tree.c (init_priority_for_decl): Remove.
> 	(init_ttree): Do not initialize init priority.
> 	(decl_init_priority_lookup, decl_fini_priority_lookup): Rewrite.
> 	(decl_priority_info): Remove.
> 	(decl_init_priority_insert): Rewrite.
> 	(decl_fini_priority_insert): Rewrite.
> 	* tree.h (tree_priority_map_eq, tree_priority_map_hash,
> 	tree_priority_map_marked_p): Remove.
> 	* lto-cgraph.c (lto_output_node, input_node): Stream init priorities.
> 	* lto-streamer-out.c (hash_tree): Do not hash priorities.
> 	* tree-streamer-out.c (pack_ts_decl_with_vis_value_fields): Do
> 	not output priorities.
> 	(pack_ts_function_decl_value_fields): Likewise.
> 	* tree-streamer-in.c (unpack_ts_decl_with_vis_value_fields): Do
> 	not input priorities.
> 	(unpack_ts_function_decl_value_fields): Likewise.
> 	* symtab.c (symbol_priority_map): Declare.
> 	(init_priority_hash): Declare.
> 	(symtab_unregister_node): Unregister from priority hash, too.
> 	(symtab_node::get_init_priority, cgraph_node::get_fini_priority):
> 	New methods.
> 	(symbol_priority_map_eq, symbol_priority_map_hash): New functions.
> 	(symbol_priority_info): New function.
> 	(symtab_node::set_init_priority, cgraph_node::set_fini_priority):
> 	New methods.
> 	* tree-core.h (tree_priority_map): Remove.
> 
> 	* lto.c (compare_tree_sccs_1): Do not compare priorities.
> Index: cgraph.h
> ===================================================================
> --- cgraph.h	(revision 211831)
> +++ cgraph.h	(working copy)
> @@ -130,6 +130,8 @@ public:
>  
>    /* Set when symbol has address taken. */
>    unsigned address_taken : 1;
> +  /* Set when init priority is set.  */
> +  unsigned in_init_priority_hash : 1;
>  
>  
>    /* Ordering of all symtab entries.  */
> @@ -163,6 +165,7 @@ public:
>        return x_comdat_group;
>      }
>  
> +  /* Return comdat group as identifier_node.  */
>    tree get_comdat_group_id ()
>      {
>        if (x_comdat_group && TREE_CODE (x_comdat_group) != IDENTIFIER_NODE)
> @@ -208,6 +211,9 @@ public:
>    /* Set section for symbol and its aliases.  */
>    void set_section (const char *section);
>    void set_section_for_node (const char *section);
> +
> +  void set_init_priority (priority_type priority);
> +  priority_type get_init_priority ();
>  };
>  
>  enum availability
> @@ -497,6 +503,9 @@ public:
>    /* True if this decl calls a COMDAT-local function.  This is set up in
>       compute_inline_parameters and inline_call.  */
>    unsigned calls_comdat_local : 1;
> +
> +  void set_fini_priority (priority_type priority);
> +  priority_type get_fini_priority ();
>  };
>  
>  
> Index: tree.c
> ===================================================================
> --- tree.c	(revision 211831)
> +++ tree.c	(working copy)
> @@ -219,10 +219,6 @@ static GTY ((if_marked ("tree_decl_map_m
>  static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)))
>       htab_t debug_args_for_decl;
>  
> -static GTY ((if_marked ("tree_priority_map_marked_p"),
> -	     param_is (struct tree_priority_map)))
> -  htab_t init_priority_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 *);
> @@ -573,8 +569,6 @@ init_ttree (void)
>  
>    value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
>  					 tree_decl_map_eq, 0);
> -  init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash,
> -					    tree_priority_map_eq, 0);
>  
>    int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
>  					int_cst_hash_eq, NULL);
> @@ -6492,13 +6486,12 @@ tree_decl_map_hash (const void *item)
>  priority_type
>  decl_init_priority_lookup (tree decl)
>  {
> -  struct tree_priority_map *h;
> -  struct tree_map_base in;
> +  symtab_node *snode = symtab_get_node (decl);
>  
> -  gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
> -  in.from = decl;
> -  h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in);
> -  return h ? h->init : DEFAULT_INIT_PRIORITY;
> +  if (!snode)
> +    return DEFAULT_INIT_PRIORITY;
> +  return
> +    snode->get_init_priority ();
>  }
>  
>  /* Return the finalization priority for DECL.  */
> @@ -6506,39 +6499,12 @@ decl_init_priority_lookup (tree decl)
>  priority_type
>  decl_fini_priority_lookup (tree decl)
>  {
> -  struct tree_priority_map *h;
> -  struct tree_map_base in;
> -
> -  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
> -  in.from = decl;
> -  h = (struct tree_priority_map *) htab_find (init_priority_for_decl, &in);
> -  return h ? h->fini : DEFAULT_INIT_PRIORITY;
> -}
> -
> -/* Return the initialization and finalization priority information for
> -   DECL.  If there is no previous priority information, a freshly
> -   allocated structure is returned.  */
> -
> -static struct tree_priority_map *
> -decl_priority_info (tree decl)
> -{
> -  struct tree_priority_map in;
> -  struct tree_priority_map *h;
> -  void **loc;
> -
> -  in.base.from = decl;
> -  loc = htab_find_slot (init_priority_for_decl, &in, INSERT);
> -  h = (struct tree_priority_map *) *loc;
> -  if (!h)
> -    {
> -      h = ggc_cleared_alloc<tree_priority_map> ();
> -      *loc = h;
> -      h->base.from = decl;
> -      h->init = DEFAULT_INIT_PRIORITY;
> -      h->fini = DEFAULT_INIT_PRIORITY;
> -    }
> +  cgraph_node *node = cgraph_get_node (decl);
>  
> -  return h;
> +  if (!node)
> +    return DEFAULT_INIT_PRIORITY;
> +  return
> +    node->get_fini_priority ();
>  }
>  
>  /* Set the initialization priority for DECL to PRIORITY.  */
> @@ -6546,13 +6512,19 @@ decl_priority_info (tree decl)
>  void
>  decl_init_priority_insert (tree decl, priority_type priority)
>  {
> -  struct tree_priority_map *h;
> +  struct symtab_node *snode;
>  
> -  gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
>    if (priority == DEFAULT_INIT_PRIORITY)
> -    return;
> -  h = decl_priority_info (decl);
> -  h->init = priority;
> +    {
> +      snode = symtab_get_node (decl);
> +      if (!snode)
> +	return;
> +    }
> +  else if (TREE_CODE (decl) == VAR_DECL)
> +    snode = varpool_node_for_decl (decl);
> +  else
> +    snode = cgraph_get_create_node (decl);
> +  snode->set_init_priority (priority);
>  }
>  
>  /* Set the finalization priority for DECL to PRIORITY.  */
> @@ -6560,13 +6532,17 @@ decl_init_priority_insert (tree decl, pr
>  void
>  decl_fini_priority_insert (tree decl, priority_type priority)
>  {
> -  struct tree_priority_map *h;
> +  struct cgraph_node *node;
>  
> -  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
>    if (priority == DEFAULT_INIT_PRIORITY)
> -    return;
> -  h = decl_priority_info (decl);
> -  h->fini = priority;
> +    {
> +      node = cgraph_get_node (decl);
> +      if (!node)
> +	return;
> +    }
> +  else
> +    node = cgraph_get_create_node (decl);
> +  node->set_fini_priority (priority);
>  }
>  
>  /* Print out the statistics for the DECL_DEBUG_EXPR hash table.  */
> Index: tree.h
> ===================================================================
> --- tree.h	(revision 211831)
> +++ tree.h	(working copy)
> @@ -4345,10 +4345,6 @@ extern unsigned int tree_decl_map_hash (
>  #define tree_int_map_hash tree_map_base_hash
>  #define tree_int_map_marked_p tree_map_base_marked_p
>  
> -#define tree_priority_map_eq tree_map_base_eq
> -#define tree_priority_map_hash tree_map_base_hash
> -#define tree_priority_map_marked_p tree_map_base_marked_p
> -
>  #define tree_vec_map_eq tree_map_base_eq
>  #define tree_vec_map_hash tree_decl_map_hash
>  #define tree_vec_map_marked_p tree_map_base_marked_p
> Index: lto-cgraph.c
> ===================================================================
> --- lto-cgraph.c	(revision 211831)
> +++ lto-cgraph.c	(working copy)
> @@ -557,6 +557,10 @@ lto_output_node (struct lto_simple_outpu
>        streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
>      }
>    streamer_write_hwi_stream (ob->main_stream, node->profile_id);
> +  if (DECL_STATIC_CONSTRUCTOR (node->decl))
> +    streamer_write_hwi_stream (ob->main_stream, DECL_INIT_PRIORITY (node->decl));
> +  if (DECL_STATIC_DESTRUCTOR (node->decl))
> +    streamer_write_hwi_stream (ob->main_stream, DECL_FINI_PRIORITY (node->decl));
>  }
>  
>  /* Output the varpool NODE to OB. 
> @@ -1210,6 +1214,10 @@ input_node (struct lto_file_decl_data *f
>    if (node->alias && !node->analyzed && node->weakref)
>      node->alias_target = get_alias_symbol (node->decl);
>    node->profile_id = streamer_read_hwi (ib);
> +  if (DECL_STATIC_CONSTRUCTOR (node->decl))
> +    SET_DECL_INIT_PRIORITY (node->decl, streamer_read_hwi (ib));
> +  if (DECL_STATIC_DESTRUCTOR (node->decl))
> +    SET_DECL_FINI_PRIORITY (node->decl, streamer_read_hwi (ib));
>    return node;
>  }
>  
> Index: lto-streamer-out.c
> ===================================================================
> --- lto-streamer-out.c	(revision 211831)
> +++ lto-streamer-out.c	(working copy)
> @@ -827,8 +827,6 @@ hash_tree (struct streamer_tree_cache_d
>  					  | (DECL_CXX_CONSTRUCTOR_P (t) << 1)
>  					  | (DECL_CXX_DESTRUCTOR_P (t) << 2),
>  					  v);
> -      if (VAR_OR_FUNCTION_DECL_P (t))
> -	v = iterative_hash_host_wide_int (DECL_INIT_PRIORITY (t), v);
>      }
>  
>    if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
> @@ -852,8 +850,6 @@ hash_tree (struct streamer_tree_cache_d
>  					| (DECL_LOOPING_CONST_OR_PURE_P (t) << 15), v);
>        if (DECL_BUILT_IN_CLASS (t) != NOT_BUILT_IN)
>  	v = iterative_hash_host_wide_int (DECL_FUNCTION_CODE (t), v);
> -      if (DECL_STATIC_DESTRUCTOR (t))
> -	v = iterative_hash_host_wide_int (DECL_FINI_PRIORITY (t), v);
>      }
>  
>    if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c	(revision 211831)
> +++ lto/lto.c	(working copy)
> @@ -1300,8 +1300,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t
>            /* DECL_IN_TEXT_SECTION is set during final asm output only.  */
>  	  compare_values (DECL_IN_CONSTANT_POOL);
>  	}
> -      if (VAR_OR_FUNCTION_DECL_P (t1))
> -	compare_values (DECL_INIT_PRIORITY);
>      }
>  
>    if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
> @@ -1328,8 +1326,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t
>        compare_values (DECL_CXX_DESTRUCTOR_P);
>        if (DECL_BUILT_IN_CLASS (t1) != NOT_BUILT_IN)
>  	compare_values (DECL_FUNCTION_CODE);
> -      if (DECL_STATIC_DESTRUCTOR (t1))
> -	compare_values (DECL_FINI_PRIORITY);
>      }
>  
>    if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
> Index: tree-streamer-out.c
> ===================================================================
> --- tree-streamer-out.c	(revision 211831)
> +++ tree-streamer-out.c	(working copy)
> @@ -256,8 +256,6 @@ pack_ts_decl_with_vis_value_fields (stru
>        bp_pack_value (bp, DECL_CXX_CONSTRUCTOR_P (expr), 1);
>        bp_pack_value (bp, DECL_CXX_DESTRUCTOR_P (expr), 1);
>      }
> -  if (VAR_OR_FUNCTION_DECL_P (expr))
> -    bp_pack_var_len_unsigned (bp, DECL_INIT_PRIORITY (expr));
>  }
>  
>  
> @@ -291,8 +289,6 @@ pack_ts_function_decl_value_fields (stru
>    bp_pack_value (bp, DECL_LOOPING_CONST_OR_PURE_P (expr), 1);
>    if (DECL_BUILT_IN_CLASS (expr) != NOT_BUILT_IN)
>      bp_pack_value (bp, DECL_FUNCTION_CODE (expr), 11);
> -  if (DECL_STATIC_DESTRUCTOR (expr))
> -    bp_pack_var_len_unsigned (bp, DECL_FINI_PRIORITY (expr));
>  }
>  
>  
> Index: tree-streamer-in.c
> ===================================================================
> --- tree-streamer-in.c	(revision 211831)
> +++ tree-streamer-in.c	(working copy)
> @@ -288,12 +288,6 @@ unpack_ts_decl_with_vis_value_fields (st
>        DECL_CXX_CONSTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
>        DECL_CXX_DESTRUCTOR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
>      }
> -  if (VAR_OR_FUNCTION_DECL_P (expr))
> -    {
> -      priority_type p;
> -      p = (priority_type) bp_unpack_var_len_unsigned (bp);
> -      SET_DECL_INIT_PRIORITY (expr, p);
> -    }
>  }
>  
>  
> @@ -336,12 +330,6 @@ unpack_ts_function_decl_value_fields (st
>  	    fatal_error ("target specific builtin not available");
>  	}
>      }
> -  if (DECL_STATIC_DESTRUCTOR (expr))
> -    {
> -      priority_type p;
> -      p = (priority_type) bp_unpack_var_len_unsigned (bp);
> -      SET_DECL_FINI_PRIORITY (expr, p);
> -    }
>  }
>  
>  
> Index: symtab.c
> ===================================================================
> --- symtab.c	(revision 211831)
> +++ symtab.c	(working copy)
> @@ -64,6 +64,17 @@ static GTY((param_is (section_hash_entry
>  /* Hash table used to convert assembler names into nodes.  */
>  static GTY((param_is (symtab_node))) htab_t assembler_name_hash;
>  
> +/* Map from a symbol to initialization/finalization priorities.  */
> +struct GTY(()) symbol_priority_map {
> +  symtab_node *symbol;
> +  priority_type init;
> +  priority_type fini;
> +};
> +
> +/* Hash table used to hold init priorities.  */
> +static GTY ((param_is (struct symbol_priority_map)))
> +  htab_t init_priority_hash;
> +
>  /* Linked list of symbol table nodes.  */
>  symtab_node *symtab_nodes;
>  
> @@ -337,6 +348,16 @@ symtab_unregister_node (symtab_node *nod
>      }
>    if (!is_a <varpool_node *> (node) || !DECL_HARD_REGISTER (node->decl))
>      unlink_from_assembler_name_hash (node, false);
> +  if (node->in_init_priority_hash)
> +    {
> +      struct symbol_priority_map in;
> +      void **slot;
> +      in.symbol = node;
> +
> +      slot = htab_find_slot (init_priority_hash, &in, NO_INSERT);
> +      if (slot)
> +	htab_clear_slot (init_priority_hash, slot);
> +    }
>  }
>  
>  
> @@ -1176,6 +1197,122 @@ symtab_node::set_section (const char *se
>    symtab_for_node_and_aliases (this, set_section_1, const_cast<char *>(section), true);
>  }
>  
> +/* Return the initialization priority.  */
> +
> +priority_type
> +symtab_node::get_init_priority ()
> +{
> +  struct symbol_priority_map *h;
> +  struct symbol_priority_map in;
> +
> +  if (!this->in_init_priority_hash)
> +    return DEFAULT_INIT_PRIORITY;
> +  in.symbol = this;
> +  h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in);
> +  return h ? h->init : DEFAULT_INIT_PRIORITY;
> +}
> +
> +/* Return the finalization priority.  */
> +
> +priority_type
> +cgraph_node::get_fini_priority ()
> +{
> +  struct symbol_priority_map *h;
> +  struct symbol_priority_map in;
> +
> +  if (!this->in_init_priority_hash)
> +    return DEFAULT_INIT_PRIORITY;
> +  in.symbol = this;
> +  h = (struct symbol_priority_map *) htab_find (init_priority_hash, &in);
> +  return h ? h->fini : DEFAULT_INIT_PRIORITY;
> +}
> +
> +/* Return true if the from tree in both priority maps are equal.  */
> +
> +int
> +symbol_priority_map_eq (const void *va, const void *vb)
> +{
> +  const struct symbol_priority_map *const a = (const struct symbol_priority_map *) va,
> +    *const b = (const struct symbol_priority_map *) vb;
> +  return (a->symbol == b->symbol);
> +}
> +
> +/* Hash a from symbol in a symbol_priority_map.  */
> +
> +unsigned int
> +symbol_priority_map_hash (const void *item)
> +{
> +  return htab_hash_pointer (((const struct symbol_priority_map *)item)->symbol);
> +}
> +
> +/* Return the initialization and finalization priority information for
> +   DECL.  If there is no previous priority information, a freshly
> +   allocated structure is returned.  */
> +
> +static struct symbol_priority_map *
> +symbol_priority_info (struct symtab_node *symbol)
> +{
> +  struct symbol_priority_map in;
> +  struct symbol_priority_map *h;
> +  void **loc;
> +
> +  in.symbol = symbol;
> +  if (!init_priority_hash)
> +    init_priority_hash = htab_create_ggc (512, symbol_priority_map_hash,
> +                                          symbol_priority_map_eq, 0);
> +
> +  loc = htab_find_slot (init_priority_hash, &in, INSERT);
> +  h = (struct symbol_priority_map *) *loc;
> +  if (!h)
> +    {
> +      h = ggc_cleared_alloc<symbol_priority_map> ();
> +      *loc = h;
> +      h->symbol = symbol;
> +      h->init = DEFAULT_INIT_PRIORITY;
> +      h->fini = DEFAULT_INIT_PRIORITY;
> +      symbol->in_init_priority_hash = true;
> +    }
> +
> +  return h;
> +}
> +
> +/* Set initialization priority to PRIORITY.  */
> +
> +void
> +symtab_node::set_init_priority (priority_type priority)
> +{
> +  struct symbol_priority_map *h;
> +
> +  if (is_a <cgraph_node *> (this))
> +    gcc_assert (DECL_STATIC_CONSTRUCTOR (this->decl));
> +
> +  if (priority == DEFAULT_INIT_PRIORITY)
> +    {
> +      gcc_assert (get_init_priority() == priority);
> +      return;
> +    }
> +  h = symbol_priority_info (this);
> +  h->init = priority;
> +}
> +
> +/* Set fialization priority to PRIORITY.  */
> +
> +void
> +cgraph_node::set_fini_priority (priority_type priority)
> +{
> +  struct symbol_priority_map *h;
> +
> +  gcc_assert (DECL_STATIC_DESTRUCTOR (this->decl));
> +
> +  if (priority == DEFAULT_INIT_PRIORITY)
> +    {
> +      gcc_assert (get_fini_priority() == priority);
> +      return;
> +    }
> +  h = symbol_priority_info (this);
> +  h->fini = priority;
> +}
> +
>  /* Worker for symtab_resolve_alias.  */
>  
>  static bool
> Index: tree-core.h
> ===================================================================
> --- tree-core.h	(revision 211831)
> +++ tree-core.h	(working copy)
> @@ -1761,13 +1761,6 @@ struct GTY(()) tree_int_map {
>    unsigned int to;
>  };
>  
> -/* Map from a tree to initialization/finalization priorities.  */
> -struct GTY(()) tree_priority_map {
> -  struct tree_map_base base;
> -  priority_type init;
> -  priority_type fini;
> -};
> -
>  /* Map from a decl tree to a tree vector.  */
>  struct GTY(()) tree_vec_map {
>    struct tree_map_base base;

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

* Re: Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table
  2014-06-20  6:41 Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table Jan Hubicka
  2014-06-20 10:57 ` Trevor Saunders
@ 2014-06-21  8:26 ` Andreas Schwab
  2014-06-23  6:44   ` Jan Hubicka
  1 sibling, 1 reply; 4+ messages in thread
From: Andreas Schwab @ 2014-06-21  8:26 UTC (permalink / raw)
  To: Jan Hubicka; +Cc: gcc-patches

Jan Hubicka <hubicka@ucw.cz> writes:

> this patch moves init and fini priorities to symbol table instead of trees.
> They are already in on-side hashtables, but the hashtables are now maintaned
> by symbol table.  This is needed for correctness with LTO.

This breaks gcc.dg/initpri3.c.  The constructor and destructor are
miscompiled to unconditionally call abort.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table
  2014-06-21  8:26 ` Andreas Schwab
@ 2014-06-23  6:44   ` Jan Hubicka
  0 siblings, 0 replies; 4+ messages in thread
From: Jan Hubicka @ 2014-06-23  6:44 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Jan Hubicka, gcc-patches

> Jan Hubicka <hubicka@ucw.cz> writes:
> 
> > this patch moves init and fini priorities to symbol table instead of trees.
> > They are already in on-side hashtables, but the hashtables are now maintaned
> > by symbol table.  This is needed for correctness with LTO.
> 
> This breaks gcc.dg/initpri3.c.  The constructor and destructor are
> miscompiled to unconditionally call abort.

Sorry for that. This is caused by lto-cgraph using the set_decl_init_priority that
it should not.  I am sure I updated this once already.  This patch fixes the problem.

Bootstrapped/regtested x86_64-linux, comitted.

	* lto-cgraph.c (lto_output_node, input_node): Set/get init/fini priority
	directly.
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 211881)
+++ lto-cgraph.c	(working copy)
@@ -558,9 +558,9 @@ lto_output_node (struct lto_simple_outpu
     }
   streamer_write_hwi_stream (ob->main_stream, node->profile_id);
   if (DECL_STATIC_CONSTRUCTOR (node->decl))
-    streamer_write_hwi_stream (ob->main_stream, DECL_INIT_PRIORITY (node->decl));
+    streamer_write_hwi_stream (ob->main_stream, node->get_init_priority ());
   if (DECL_STATIC_DESTRUCTOR (node->decl))
-    streamer_write_hwi_stream (ob->main_stream, DECL_FINI_PRIORITY (node->decl));
+    streamer_write_hwi_stream (ob->main_stream, node->get_fini_priority ());
 }
 
 /* Output the varpool NODE to OB. 
@@ -1215,9 +1216,9 @@ input_node (struct lto_file_decl_data *f
     node->alias_target = get_alias_symbol (node->decl);
   node->profile_id = streamer_read_hwi (ib);
   if (DECL_STATIC_CONSTRUCTOR (node->decl))
-    SET_DECL_INIT_PRIORITY (node->decl, streamer_read_hwi (ib));
+    node->set_init_priority (streamer_read_hwi (ib));
   if (DECL_STATIC_DESTRUCTOR (node->decl))
-    SET_DECL_FINI_PRIORITY (node->decl, streamer_read_hwi (ib));
+    node->set_fini_priority (streamer_read_hwi (ib));
   return node;
 }
 

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

end of thread, other threads:[~2014-06-23  6:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-20  6:41 Move DECL_INIT_PRIORITY/FINI_PRIORITY to symbol table Jan Hubicka
2014-06-20 10:57 ` Trevor Saunders
2014-06-21  8:26 ` Andreas Schwab
2014-06-23  6:44   ` Jan Hubicka

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).