public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Martin Jambor <mjambor@suse.cz>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Cc: Jan Hubicka <hubicka@ucw.cz>
Subject: [PATCH 1/6] Clarify edge redirection for inline clones
Date: Sat, 13 Feb 2010 18:03:00 -0000	[thread overview]
Message-ID: <20100213180156.993252867@alvy.suse.cz> (raw)
In-Reply-To: <20100213180136.555197900@alvy.suse.cz>

[-- Attachment #1: improve_cgraph_edge_redirection.diff --]
[-- Type: text/plain, Size: 8414 bytes --]

Hi,

this patch a new one in the series and it changes how we set
declarations in call statements to reflect the callee of the
corresponding call graph edge.  Currently we do this for all nodes in
cgraph_materialize_all_clones and since at this point inline clones
still share their bodies, we do it only for one of them, the one which
passes through condition 

  (!node->clone_of || node->clone_of->decl != node->decl)

For the same reason, it is also never done for call statements for
which gimple_call_fndecl returns NULL - so that we don't change
statements of all inline clones because of an indirect-inlining
created edge out of one of them.

However, in order to use this mechanism for IPA-CP devirtualization we
need to be able to redirect even these statements.  Therefore this
patch keeps the current redirection only for nodes which are not
inlined and deals with these in copy_bb in tree-inline.c.

I have put this change to the beginning of the series because the
current mechanism is quite fragile and I suspect that PR 41290 is
caused by an original node (with inline clones) somehow ceasing to
exist which would lead exactly to these kinds of cgraph verification
issues.  I have asked the reporter to verify this hypothesis and if it
fixes the issue, I will request an approval to commit to trunk now.
Otherwise I will wait with this until stage1.

I have bootstrapped and regression tested this patch separately on
x86_64-linux.

Thanks,

Martin


2010-02-12  Martin Jambor  <mjambor@suse.cz>

	* cgraph.h (cgraph_redirect_edge_call_stmt_to_callee): Declare.
	* cgraphunit.c (cgraph_materialize_all_clones): Moved call
	redirection...
	(cgraph_redirect_edge_call_stmt_to_callee): ...to this new
	function.
	(verify_cgraph_node): Do not check for edges pointing to wrong
	nodes in inline clones.
	* tree-inline.c (copy_bb): Call
	cgraph_redirect_edge_call_stmt_to_callee.


Index: icln/gcc/cgraph.h
===================================================================
--- icln.orig/gcc/cgraph.h
+++ icln/gcc/cgraph.h
@@ -530,7 +530,7 @@ void cgraph_remove_edge_duplication_hook
 struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_hook, void *);
 void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
 void cgraph_materialize_all_clones (void);
-
+gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
 /* In cgraphbuild.c  */
 unsigned int rebuild_cgraph_edges (void);
 void reset_inline_failed (struct cgraph_node *);
Index: icln/gcc/cgraphunit.c
===================================================================
--- icln.orig/gcc/cgraphunit.c
+++ icln/gcc/cgraphunit.c
@@ -751,8 +751,9 @@ verify_cgraph_node (struct cgraph_node *
 			    debug_tree (e->callee->decl);
 			    error_found = true;
 			  }
-			else if (!clone_of_p (cgraph_node (decl), e->callee)
-			         && !e->callee->global.inlined_to)
+			else if (!node->global.inlined_to
+				 && !e->callee->global.inlined_to
+				 && !clone_of_p (cgraph_node (decl), e->callee))
 			  {
 			    error ("edge points to wrong declaration:");
 			    debug_tree (e->callee->decl);
@@ -2222,11 +2223,60 @@ cgraph_materialize_clone (struct cgraph_
   bitmap_obstack_release (NULL);
 }
 
+/* If necessary, change the function declaration in the call statement
+   associated with E so that it corresponds to the edge callee.  */
+
+gimple
+cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
+{
+  tree decl = gimple_call_fndecl (e->call_stmt);
+  gimple new_stmt;
+  gimple_stmt_iterator gsi;
+
+  if (!decl || decl == e->callee->decl
+      /* Don't update call from same body alias to the real function.  */
+      || cgraph_get_node (decl) == cgraph_get_node (e->callee->decl))
+    return e->call_stmt;
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "updating call of %s in %s:",
+	       cgraph_node_name (e->caller),
+	       cgraph_node_name (e->callee));
+      print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
+    }
+
+  if (e->callee->clone.combined_args_to_skip)
+    new_stmt = gimple_call_copy_skip_args (e->call_stmt,
+				       e->callee->clone.combined_args_to_skip);
+  else
+    new_stmt = e->call_stmt;
+  if (gimple_vdef (new_stmt)
+      && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
+    SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
+  gimple_call_set_fndecl (new_stmt, e->callee->decl);
+
+  gsi = gsi_for_stmt (e->call_stmt);
+  gsi_replace (&gsi, new_stmt, true);
+
+  /* Update EH information too, just in case.  */
+  maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt);
+
+  cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt);
+
+  if (cgraph_dump_file)
+    {
+      fprintf (cgraph_dump_file, "  updated to:");
+      print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
+    }
+  return new_stmt;
+}
+
 /* Once all functions from compilation unit are in memory, produce all clones
-   and update all calls.
-   We might also do this on demand if we don't want to bring all functions to
-   memory prior compilation, but current WHOPR implementation does that and it is
-   is bit easier to keep everything right in this order.  */
+   and update all calls.  We might also do this on demand if we don't want to
+   bring all functions to memory prior compilation, but current WHOPR
+   implementation does that and it is is bit easier to keep everything right in
+   this order.  */
 void
 cgraph_materialize_all_clones (void)
 {
@@ -2302,63 +2352,15 @@ cgraph_materialize_all_clones (void)
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "Updating call sites\n");
   for (node = cgraph_nodes; node; node = node->next)
-    if (node->analyzed && gimple_has_body_p (node->decl)
-        && (!node->clone_of || node->clone_of->decl != node->decl))
+    if (node->analyzed && !node->global.inlined_to
+	&& gimple_has_body_p (node->decl))
       {
         struct cgraph_edge *e;
 
 	current_function_decl = node->decl;
         push_cfun (DECL_STRUCT_FUNCTION (node->decl));
 	for (e = node->callees; e; e = e->next_callee)
-	  {
-	    tree decl = gimple_call_fndecl (e->call_stmt);
-	    /* When function gets inlined, indirect inlining might've invented
-	       new edge for orginally indirect stmt.  Since we are not
-	       preserving clones in the original form, we must not update here
-	       since other inline clones don't need to contain call to the same
-	       call.  Inliner will do the substitution for us later.  */
-	    if (decl && decl != e->callee->decl)
-	      {
-		gimple new_stmt;
-		gimple_stmt_iterator gsi;
-
-		if (cgraph_get_node (decl) == cgraph_get_node (e->callee->decl))
-		  /* Don't update call from same body alias to the real function.  */
-		  continue;
-
-		if (cgraph_dump_file)
-		  {
-		    fprintf (cgraph_dump_file, "updating call of %s in %s:",
-		             cgraph_node_name (node),
-			     cgraph_node_name (e->callee));
-      		    print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
-		  }
-
-		if (e->callee->clone.combined_args_to_skip)
-		  new_stmt = gimple_call_copy_skip_args (e->call_stmt,
-							 e->callee->clone.combined_args_to_skip);
-		else
-		  new_stmt = e->call_stmt;
-		if (gimple_vdef (new_stmt)
-		    && TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)
-		  SSA_NAME_DEF_STMT (gimple_vdef (new_stmt)) = new_stmt;
-                gimple_call_set_fndecl (new_stmt, e->callee->decl);
-
-		gsi = gsi_for_stmt (e->call_stmt);
-		gsi_replace (&gsi, new_stmt, true);
-
-		/* Update EH information too, just in case.  */
-		maybe_clean_or_replace_eh_stmt (e->call_stmt, new_stmt);
-
-		cgraph_set_call_stmt_including_clones (node, e->call_stmt, new_stmt);
-
-		if (cgraph_dump_file)
-		  {
-		    fprintf (cgraph_dump_file, "  updated to:");
-      		    print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags);
-		  }
-	      }
-	  }
+	  cgraph_redirect_edge_call_stmt_to_callee (e);
 	pop_cfun ();
 	current_function_decl = NULL;
 #ifdef ENABLE_CHECKING
Index: icln/gcc/tree-inline.c
===================================================================
--- icln.orig/gcc/tree-inline.c
+++ icln/gcc/tree-inline.c
@@ -1651,6 +1651,7 @@ copy_bb (copy_body_data *id, basic_block
 				   bb->frequency,
 				   copy_basic_block->frequency);
 			}
+		      stmt = cgraph_redirect_edge_call_stmt_to_callee (edge);
 		    }
 		  break;
 

  reply	other threads:[~2010-02-13 18:03 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-02-13 18:03 [PATCH 0/6] Cgraph changes and various devirtualizations Martin Jambor
2010-02-13 18:03 ` Martin Jambor [this message]
2010-02-22 14:23   ` [PATCH 1/6] Clarify edge redirection for inline clones Jan Hubicka
2010-02-13 18:04 ` [PATCH 2/6] Indirect call graph edges Martin Jambor
2010-02-13 18:17   ` Richard Guenther
2010-02-13 18:25     ` Richard Guenther
2010-03-05 17:06       ` Martin Jambor
2010-02-22 15:52   ` Jan Hubicka
2010-02-22 16:05     ` Richard Guenther
2010-02-22 16:06       ` Jan Hubicka
2010-02-13 18:04 ` [PATCH 4/6] Remove unused ipa_note_param_call.called flag (approved) Martin Jambor
2010-02-13 18:14   ` Richard Guenther
2010-03-05 16:19     ` Martin Jambor
2010-02-22 15:04   ` Jan Hubicka
2010-02-13 18:04 ` [PATCH 5/6] Indirect inlining of virtual calls Martin Jambor
2010-02-22 16:49   ` Jan Hubicka
2010-03-10 13:45     ` Martin Jambor
2010-03-10 15:24       ` Jan Hubicka
2010-02-13 18:04 ` [PATCH 3/6] Folding " Martin Jambor
2010-02-13 18:12   ` Richard Guenther
2010-02-13 18:04 ` [PATCH 6/6] Devirtualization in ipa-cp Martin Jambor
2010-02-22 16:37   ` Jan Hubicka
2010-03-11 13:42     ` Martin Jambor

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100213180156.993252867@alvy.suse.cz \
    --to=mjambor@suse.cz \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=hubicka@ucw.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).