Patchwork lto-symtab and cgraph aliases

login
register
mail settings
Submitter Jan Hubicka
Date July 6, 2010, 11:55 a.m.
Message ID <20100706115549.GA12425@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/58000/
State New
Headers show

Comments

Jan Hubicka - July 6, 2010, 11:55 a.m.
> Changelog is incomplete (missing cgraph.h change).
> 
> Otherwise it makes sense.
> 
> Thanks,
> Richard.

Must've got incomplette file somehow.  This is full version I am re-testing now.
OK if it passes?

	* lto-symtab.c (lto_cgraph_replace_node): Handle aliases.
	(lto_symtab_resolve_can_prevail_p): Also alias of cgraph node
	with body can prevail.
	(lto_symtab_resolve_symbols): Use cgraph_get_node_or_alias.
	(lto_symtab_merge_cgraph_nodes_1): Do not remove nodes from aliases.
	* cgraph.c (cgraph_get_node_or_alias): New function.
	* cgraph.h (cgraph_get_node_or_alias): Declare.
Richard Guenther - July 6, 2010, 12:13 p.m.
On Tue, Jul 6, 2010 at 1:55 PM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> Changelog is incomplete (missing cgraph.h change).
>>
>> Otherwise it makes sense.
>>
>> Thanks,
>> Richard.
>
> Must've got incomplette file somehow.  This is full version I am re-testing now.
> OK if it passes?

Yes.

Thanks,
Richard.

>        * lto-symtab.c (lto_cgraph_replace_node): Handle aliases.
>        (lto_symtab_resolve_can_prevail_p): Also alias of cgraph node
>        with body can prevail.
>        (lto_symtab_resolve_symbols): Use cgraph_get_node_or_alias.
>        (lto_symtab_merge_cgraph_nodes_1): Do not remove nodes from aliases.
>        * cgraph.c (cgraph_get_node_or_alias): New function.
>        * cgraph.h (cgraph_get_node_or_alias): Declare.
> Index: lto-symtab.c
> ===================================================================
> --- lto-symtab.c        (revision 161847)
> +++ lto-symtab.c        (working copy)
> @@ -206,6 +206,24 @@ lto_cgraph_replace_node (struct cgraph_n
>                         struct cgraph_node *prevailing_node)
>  {
>   struct cgraph_edge *e, *next;
> +  bool no_aliases_please = false;
> +
> +  if (cgraph_dump_file)
> +    {
> +      fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i"
> +              " for symbol %s\n",
> +              cgraph_node_name (node), node->uid,
> +              cgraph_node_name (prevailing_node),
> +              prevailing_node->uid,
> +              IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
> +    }
> +
> +  if (prevailing_node->same_body_alias)
> +    {
> +      if (prevailing_node->thunk.thunk_p)
> +       no_aliases_please = true;
> +      prevailing_node = prevailing_node->same_body;
> +    }
>
>   /* Merge node flags.  */
>   if (node->needed)
> @@ -227,27 +244,37 @@ lto_cgraph_replace_node (struct cgraph_n
>   /* Redirect incomming references.  */
>   ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
>
> -  if (node->same_body)
> +  /* If we have aliases, redirect them to the prevailing node.  */
> +  if (!node->same_body_alias && node->same_body)
>     {
> -      struct cgraph_node *alias;
> +      struct cgraph_node *alias, *last;
> +      /* We prevail aliases/tunks by a thunk.  This is doable but
> +         would need thunk combination.  Hopefully no ABI changes will
> +         every be crazy enough.  */
> +      gcc_assert (!no_aliases_please);
>
>       for (alias = node->same_body; alias; alias = alias->next)
> -       if (DECL_ASSEMBLER_NAME_SET_P (alias->decl))
> -         {
> -           lto_symtab_entry_t se
> -             = lto_symtab_get (DECL_ASSEMBLER_NAME (alias->decl));
> -
> -           for (; se; se = se->next)
> -             if (se->node == node)
> -               {
> -                 se->node = NULL;
> -                 break;
> -               }
> -         }
> +       {
> +         last = alias;
> +         gcc_assert (alias->same_body_alias);
> +         alias->same_body = prevailing_node;
> +         alias->thunk.alias = prevailing_node->decl;
> +       }
> +      last->next = prevailing_node->same_body;
> +      /* Node with aliases is prevailed by alias.
> +        We could handle this, but combining thunks together will be tricky.
> +        Hopefully this does not happen.  */
> +      if (prevailing_node->same_body)
> +       prevailing_node->same_body->previous = last;
> +      prevailing_node->same_body = node->same_body;
> +      node->same_body = NULL;
>     }
>
>   /* Finally remove the replaced node.  */
> -  cgraph_remove_node (node);
> +  if (node->same_body_alias)
> +    cgraph_remove_same_body_alias (node);
> +  else
> +    cgraph_remove_node (node);
>  }
>
>  /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
> @@ -433,7 +460,9 @@ lto_symtab_resolve_can_prevail_p (lto_sy
>
>   /* For functions we need a non-discarded body.  */
>   if (TREE_CODE (e->decl) == FUNCTION_DECL)
> -    return (e->node && e->node->analyzed);
> +    return (e->node
> +           && (e->node->analyzed
> +               || (e->node->same_body_alias && e->node->same_body->analyzed)));
>
>   /* A variable should have a size.  */
>   else if (TREE_CODE (e->decl) == VAR_DECL)
> @@ -461,7 +490,7 @@ lto_symtab_resolve_symbols (void **slot)
>   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
>     {
>       if (TREE_CODE (e->decl) == FUNCTION_DECL)
> -       e->node = cgraph_get_node (e->decl);
> +       e->node = cgraph_get_node_or_alias (e->decl);
>       else if (TREE_CODE (e->decl) == VAR_DECL)
>        {
>          e->vnode = varpool_get_node (e->decl);
> @@ -751,22 +780,7 @@ lto_symtab_merge_cgraph_nodes_1 (void **
>   for (e = prevailing->next; e; e = e->next)
>     {
>       if (e->node != NULL)
> -       {
> -         if (e->node->decl != e->decl && e->node->same_body)
> -           {
> -             struct cgraph_node *alias;
> -
> -             for (alias = e->node->same_body; alias; alias = alias->next)
> -               if (alias->decl == e->decl)
> -                 break;
> -             if (alias)
> -               {
> -                 cgraph_remove_same_body_alias (alias);
> -                 continue;
> -               }
> -           }
> -         lto_cgraph_replace_node (e->node, prevailing->node);
> -       }
> +       lto_cgraph_replace_node (e->node, prevailing->node);
>       if (e->vnode != NULL)
>        lto_varpool_replace_node (e->vnode, prevailing->vnode);
>     }
> Index: cgraph.c
> ===================================================================
> --- cgraph.c    (revision 161847)
> +++ cgraph.c    (working copy)
> @@ -604,6 +604,29 @@ cgraph_add_thunk (tree alias, tree decl,
>    is assigned.  */
>
> +/* Returns the cgraph or alias node assigned to DECL or NULL if no cgraph node
> +   is assigned.  */
> +
>  struct cgraph_node *
> +cgraph_get_node_or_alias (tree decl)
> +{
> +  struct cgraph_node key, *node = NULL, **slot;
> +
> +  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
> +
> +  if (!cgraph_hash)
> +    return NULL;
> +
> +  key.decl = decl;
> +
> +  slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
> +                                                NO_INSERT);
> +
> +  if (slot && *slot)
> +    node = *slot;
> +  return node;
> +}
> +
> +/* Returns the cgraph node assigned to DECL or NULL if no cgraph node
> +   is assigned.  */
> +
> +struct cgraph_node *
>  cgraph_get_node (tree decl)
>  {
>   struct cgraph_node key, *node = NULL, **slot;
> Index: cgraph.h
> ===================================================================
> --- cgraph.h    (revision 161866)
> +++ cgraph.h    (working copy)
> @@ -556,6 +560,7 @@ struct cgraph_edge *cgraph_create_edge (
>  struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int,
>                                                 gcov_type, int, int);
>  struct cgraph_node * cgraph_get_node (tree);
> +struct cgraph_node * cgraph_get_node_or_alias (tree);
>  struct cgraph_node *cgraph_node (tree);
>  bool cgraph_same_body_alias (tree, tree);
>  void cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree);
>

Patch

Index: lto-symtab.c
===================================================================
--- lto-symtab.c	(revision 161847)
+++ lto-symtab.c	(working copy)
@@ -206,6 +206,24 @@  lto_cgraph_replace_node (struct cgraph_n
 			 struct cgraph_node *prevailing_node)
 {
   struct cgraph_edge *e, *next;
+  bool no_aliases_please = false;
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i"
+ 	       " for symbol %s\n",
+	       cgraph_node_name (node), node->uid,
+	       cgraph_node_name (prevailing_node),
+	       prevailing_node->uid,
+	       IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
+    }
+
+  if (prevailing_node->same_body_alias)
+    {
+      if (prevailing_node->thunk.thunk_p)
+	no_aliases_please = true;
+      prevailing_node = prevailing_node->same_body;
+    }
 
   /* Merge node flags.  */
   if (node->needed)
@@ -227,27 +244,37 @@  lto_cgraph_replace_node (struct cgraph_n
   /* Redirect incomming references.  */
   ipa_clone_refering (prevailing_node, NULL, &node->ref_list);
 
-  if (node->same_body)
+  /* If we have aliases, redirect them to the prevailing node.  */
+  if (!node->same_body_alias && node->same_body)
     {
-      struct cgraph_node *alias;
+      struct cgraph_node *alias, *last;
+      /* We prevail aliases/tunks by a thunk.  This is doable but
+         would need thunk combination.  Hopefully no ABI changes will
+         every be crazy enough.  */
+      gcc_assert (!no_aliases_please);
 
       for (alias = node->same_body; alias; alias = alias->next)
-	if (DECL_ASSEMBLER_NAME_SET_P (alias->decl))
-	  {
-	    lto_symtab_entry_t se
-	      = lto_symtab_get (DECL_ASSEMBLER_NAME (alias->decl));
-
-	    for (; se; se = se->next)
-	      if (se->node == node)
-		{
-		  se->node = NULL;
-		  break;
-		}
-	  }
+	{
+	  last = alias;
+	  gcc_assert (alias->same_body_alias);
+	  alias->same_body = prevailing_node;
+	  alias->thunk.alias = prevailing_node->decl;
+	}
+      last->next = prevailing_node->same_body;
+      /* Node with aliases is prevailed by alias.
+	 We could handle this, but combining thunks together will be tricky.
+	 Hopefully this does not happen.  */
+      if (prevailing_node->same_body)
+	prevailing_node->same_body->previous = last;
+      prevailing_node->same_body = node->same_body;
+      node->same_body = NULL;
     }
 
   /* Finally remove the replaced node.  */
-  cgraph_remove_node (node);
+  if (node->same_body_alias)
+    cgraph_remove_same_body_alias (node);
+  else
+    cgraph_remove_node (node);
 }
 
 /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
@@ -433,7 +460,9 @@  lto_symtab_resolve_can_prevail_p (lto_sy
 
   /* For functions we need a non-discarded body.  */
   if (TREE_CODE (e->decl) == FUNCTION_DECL)
-    return (e->node && e->node->analyzed);
+    return (e->node
+	    && (e->node->analyzed
+	        || (e->node->same_body_alias && e->node->same_body->analyzed)));
 
   /* A variable should have a size.  */
   else if (TREE_CODE (e->decl) == VAR_DECL)
@@ -461,7 +490,7 @@  lto_symtab_resolve_symbols (void **slot)
   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
     {
       if (TREE_CODE (e->decl) == FUNCTION_DECL)
-	e->node = cgraph_get_node (e->decl);
+	e->node = cgraph_get_node_or_alias (e->decl);
       else if (TREE_CODE (e->decl) == VAR_DECL)
 	{
 	  e->vnode = varpool_get_node (e->decl);
@@ -751,22 +780,7 @@  lto_symtab_merge_cgraph_nodes_1 (void **
   for (e = prevailing->next; e; e = e->next)
     {
       if (e->node != NULL)
-	{
-	  if (e->node->decl != e->decl && e->node->same_body)
-	    {
-	      struct cgraph_node *alias;
-
-	      for (alias = e->node->same_body; alias; alias = alias->next)
-		if (alias->decl == e->decl)
-		  break;
-	      if (alias)
-		{
-		  cgraph_remove_same_body_alias (alias);
-		  continue;
-		}
-	    }
-	  lto_cgraph_replace_node (e->node, prevailing->node);
-	}
+	lto_cgraph_replace_node (e->node, prevailing->node);
       if (e->vnode != NULL)
 	lto_varpool_replace_node (e->vnode, prevailing->vnode);
     }
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 161847)
+++ cgraph.c	(working copy)
@@ -604,6 +604,29 @@  cgraph_add_thunk (tree alias, tree decl,
    is assigned.  */
 
+/* Returns the cgraph or alias node assigned to DECL or NULL if no cgraph node
+   is assigned.  */
+
 struct cgraph_node *
+cgraph_get_node_or_alias (tree decl)
+{
+  struct cgraph_node key, *node = NULL, **slot;
+
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+
+  if (!cgraph_hash)
+    return NULL;
+
+  key.decl = decl;
+
+  slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
+						 NO_INSERT);
+
+  if (slot && *slot)
+    node = *slot;
+  return node;
+}
+
+/* Returns the cgraph node assigned to DECL or NULL if no cgraph node
+   is assigned.  */
+
+struct cgraph_node *
 cgraph_get_node (tree decl)
 {
   struct cgraph_node key, *node = NULL, **slot;
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 161866)
+++ cgraph.h	(working copy)
@@ -556,6 +560,7 @@  struct cgraph_edge *cgraph_create_edge (
 struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int,
 						 gcov_type, int, int);
 struct cgraph_node * cgraph_get_node (tree);
+struct cgraph_node * cgraph_get_node_or_alias (tree);
 struct cgraph_node *cgraph_node (tree);
 bool cgraph_same_body_alias (tree, tree);
 void cgraph_add_thunk (tree, tree, bool, HOST_WIDE_INT, HOST_WIDE_INT, tree, tree);