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


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

Fix remove_unreachable_nodes wrt comdat locals


Hi,
this patch fixes ICE seen when compiling libreoffice with LTO
at 4.9 release tree.  The problem is that we now use comdat locals for
decloned constructors and symtab_remove_unreachable_nodes sometimes
remove their bodies but keeps their nodes around.

In this case the nodes needs to be brought out of comdat groups or
LTO streaming will mess up the linked list holding them.

Bootstrapped/regtested x86_64-linux and tested with libreoffice LTO build
will commit it to mainline and release branch shortly.

Honza

	* ipa.c (symtab_remove_unreachable_nodes): Remove
	symbol from comdat group if its body was eliminated.
	(comdat_can_be_unshared_p_1): Static symbols can always
	be privatized.
	* symtab.c (symtab_remove_from_same_comdat_group): Break out
	from ...
	(symtab_unregister_node): ... this one.
	(verify_symtab_base): More strict checking of comdats.
	* cgraph.h (symtab_remove_from_same_comdat_group): Declare.
Index: ipa.c
===================================================================
--- ipa.c	(revision 210563)
+++ ipa.c	(working copy)
@@ -517,6 +517,7 @@ symtab_remove_unreachable_nodes (bool be
 	      if (!node->in_other_partition)
 		node->local.local = false;
 	      cgraph_node_remove_callees (node);
+	      symtab_remove_from_same_comdat_group (node);
 	      ipa_remove_all_references (&node->ref_list);
 	      changed = true;
 	    }
@@ -572,6 +573,8 @@ symtab_remove_unreachable_nodes (bool be
 	  vnode->analyzed = false;
 	  vnode->aux = NULL;
 
+	  symtab_remove_from_same_comdat_group (vnode);
+
 	  /* Keep body if it may be useful for constant folding.  */
 	  if ((init = ctor_for_folding (vnode->decl)) == error_mark_node)
 	    varpool_remove_initializer (vnode);
@@ -708,6 +711,8 @@ address_taken_from_non_vtable_p (symtab_
 static bool
 comdat_can_be_unshared_p_1 (symtab_node *node)
 {
+  if (!node->externally_visible)
+    return true;
   /* When address is taken, we don't know if equality comparison won't
      break eventually. Exception are virutal functions, C++
      constructors/destructors and vtables, where this is not possible by
Index: symtab.c
===================================================================
--- symtab.c	(revision 210563)
+++ symtab.c	(working copy)
@@ -323,16 +323,11 @@ symtab_insert_node_to_hashtable (symtab_
   *slot = node;
 }
 
-/* Remove node from symbol table.  This function is not used directly, but via
-   cgraph/varpool node removal routines.  */
+/* Remove NODE from same comdat group.   */
 
 void
-symtab_unregister_node (symtab_node *node)
+symtab_remove_from_same_comdat_group (symtab_node *node)
 {
-  void **slot;
-  ipa_remove_all_references (&node->ref_list);
-  ipa_remove_all_referring (&node->ref_list);
-
   if (node->same_comdat_group)
     {
       symtab_node *prev;
@@ -346,6 +341,19 @@ symtab_unregister_node (symtab_node *nod
 	prev->same_comdat_group = node->same_comdat_group;
       node->same_comdat_group = NULL;
     }
+}
+
+/* Remove node from symbol table.  This function is not used directly, but via
+   cgraph/varpool node removal routines.  */
+
+void
+symtab_unregister_node (symtab_node *node)
+{
+  void **slot;
+  ipa_remove_all_references (&node->ref_list);
+  ipa_remove_all_referring (&node->ref_list);
+
+  symtab_remove_from_same_comdat_group (node);
 
   if (node->previous)
     node->previous->next = node->next;
@@ -829,6 +837,16 @@ verify_symtab_base (symtab_node *node)
 	  error ("non-DECL_ONE_ONLY node in a same_comdat_group list");
 	  error_found = true;
 	}
+      if (DECL_COMDAT_GROUP (n->decl) != DECL_COMDAT_GROUP (node->same_comdat_group->decl))
+	{
+	  error ("same_comdat_group list across different groups");
+	  error_found = true;
+	}
+      if (!n->definition)
+	{
+	  error ("Node has same_comdat_group but it is not a definition");
+	  error_found = true;
+	}
       if (n->type != node->type)
 	{
 	  error ("mixing different types of symbol in same comdat groups is not supported");
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 210563)
+++ cgraph.h	(working copy)
@@ -723,6 +723,7 @@ enum symbol_partitioning_class
 /* In symtab.c  */
 void symtab_register_node (symtab_node *);
 void symtab_unregister_node (symtab_node *);
+void symtab_remove_from_same_comdat_group (symtab_node *);
 void symtab_remove_node (symtab_node *);
 symtab_node *symtab_get_node (const_tree);
 symtab_node *symtab_node_for_asm (const_tree asmname);
Index: gimple-fold.c
===================================================================
--- gimple-fold.c	(revision 210563)
+++ gimple-fold.c	(working copy)
@@ -105,7 +105,9 @@ can_refer_decl_in_current_unit_p (tree d
      external var.  */
   if (!from_decl
       || TREE_CODE (from_decl) != VAR_DECL
-      || !DECL_EXTERNAL (from_decl)
+      || (!DECL_EXTERNAL (from_decl)
+	  && (vnode = varpool_get_node (from_decl)) != NULL
+	  && vnode->definition)
       || (flag_ltrans
 	  && symtab_get_node (from_decl)->in_other_partition))
     return true;


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