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]

[PATCH] Update callgraph edges if fold_marked_statements folds some CALL_EXPR (PR middle-end/34969)


Hi!

If fold_marked_statements during {cgraph,tree}_function_versioning
folds any CALL_EXPRs into non-calls or different calls, gcc ICEs
during cgraph_remove_unreachable_nodes verification, as cgraph edges
have not been updated.

The following patch fixes that (and also temporarily changes cfun during
verify_cgraph_node, as debug_generic_stmt that function calls in error
cases expects correct cfun), by updating callgraph edges if something
changed.  AFAIK there are no execute_todo calls between that
fold_marked_statements and cgraph_remove_unreachable_nodes, so delaying
that into an todo task is too late.

Ok for trunk?

2008-01-29  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/34969
	* cgraph.h (cgraph_update_edges_for_call_stmt): New prototype.
	* cgraph.c (cgraph_update_edges_for_call_stmt): New function.
	* tree-inline.c (fold_marked_statements): Call
	cgraph_update_edges_for_call_stmt if folding a call statement.
	* cgraphunit.c (verify_cgraph_node): Set cfun to this_cfun for
	debug_generic_stmt calls, reset it back afterwards.

	* gcc.dg/pr34969.c: New test.

--- gcc/cgraphunit.c.jj	2008-01-28 09:30:03.000000000 +0100
+++ gcc/cgraphunit.c	2008-01-28 09:31:03.000000000 +0100
@@ -658,6 +658,7 @@ verify_cgraph_node (struct cgraph_node *
   struct cgraph_edge *e;
   struct cgraph_node *main_clone;
   struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl);
+  struct function *saved_cfun = cfun;
   basic_block this_block;
   block_stmt_iterator bsi;
   bool error_found = false;
@@ -666,6 +667,8 @@ verify_cgraph_node (struct cgraph_node *
     return;
 
   timevar_push (TV_CGRAPH_VERIFY);
+  /* debug_generic_stmt needs correct cfun */
+  set_cfun (this_cfun);
   for (e = node->callees; e; e = e->next_callee)
     if (e->aux)
       {
@@ -808,6 +811,7 @@ verify_cgraph_node (struct cgraph_node *
       dump_cgraph_node (stderr, node);
       internal_error ("verify_cgraph_node failed");
     }
+  set_cfun (saved_cfun);
   timevar_pop (TV_CGRAPH_VERIFY);
 }
 
--- gcc/cgraph.h.jj	2007-11-02 19:02:47.000000000 +0100
+++ gcc/cgraph.h	2008-01-29 13:23:29.000000000 +0100
@@ -1,5 +1,6 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 This file is part of GCC.
@@ -303,6 +304,7 @@ struct cgraph_node *cgraph_node (tree);
 struct cgraph_node *cgraph_node_for_asm (tree asmname);
 struct cgraph_edge *cgraph_edge (struct cgraph_node *, tree);
 void cgraph_set_call_stmt (struct cgraph_edge *, tree);
+void cgraph_update_edges_for_call_stmt (tree, tree, tree);
 struct cgraph_local_info *cgraph_local_info (tree);
 struct cgraph_global_info *cgraph_global_info (tree);
 struct cgraph_rtl_info *cgraph_rtl_info (tree);
--- gcc/tree-inline.c.jj	2008-01-22 15:03:23.000000000 +0100
+++ gcc/tree-inline.c	2008-01-29 13:15:44.000000000 +0100
@@ -2936,11 +2936,17 @@ fold_marked_statements (int first, struc
 	  if (pointer_set_contains (statements, bsi_stmt (bsi)))
 	    {
 	      tree old_stmt = bsi_stmt (bsi);
+	      tree old_call = get_call_expr_in (old_stmt);
+
 	      if (fold_stmt (bsi_stmt_ptr (bsi)))
 		{
 		  update_stmt (bsi_stmt (bsi));
-		  if (maybe_clean_or_replace_eh_stmt (old_stmt, bsi_stmt (bsi)))
-		     tree_purge_dead_eh_edges (BASIC_BLOCK (first));
+		  if (old_call)
+		    cgraph_update_edges_for_call_stmt (old_stmt, old_call,
+						       bsi_stmt (bsi));
+		  if (maybe_clean_or_replace_eh_stmt (old_stmt,
+						      bsi_stmt (bsi)))
+		    tree_purge_dead_eh_edges (BASIC_BLOCK (first));
 		}
 	    }
       }
--- gcc/cgraph.c.jj	2007-11-02 19:02:47.000000000 +0100
+++ gcc/cgraph.c	2008-01-29 13:59:06.000000000 +0100
@@ -1,5 +1,6 @@
 /* Callgraph handling code.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 This file is part of GCC.
@@ -440,6 +441,47 @@ cgraph_redirect_edge_callee (struct cgra
   e->callee = n;
 }
 
+/* Update or remove corresponding cgraph edge if a call OLD_CALL
+   in OLD_STMT changed into NEW_STMT.  */
+
+void
+cgraph_update_edges_for_call_stmt (tree old_stmt, tree old_call,
+				   tree new_stmt)
+{
+  tree new_call = get_call_expr_in (new_stmt);
+  struct cgraph_node *node = cgraph_node (cfun->decl);
+
+  if (old_call != new_call)
+    {
+      struct cgraph_edge *e = cgraph_edge (node, old_stmt);
+      struct cgraph_edge *ne = NULL;
+      tree new_decl;
+
+      if (e)
+	{
+	  if (new_call)
+	    {
+	      new_decl = get_callee_fndecl (new_call);
+	      if (new_decl)
+		{
+		  ne = cgraph_create_edge (node, cgraph_node (new_decl),
+					   new_stmt, e->count, e->frequency,
+					   e->loop_nest);
+		  ne->inline_failed = e->inline_failed;
+		}
+	    }
+	  cgraph_remove_edge (e);
+	}
+    }
+  else if (old_stmt != new_stmt)
+    {
+      struct cgraph_edge *e = cgraph_edge (node, old_stmt);
+
+      if (e)
+	cgraph_set_call_stmt (e, new_stmt);
+    }
+}
+
 /* Remove all callees from the node.  */
 
 void
--- gcc/testsuite/gcc.dg/pr34969.c.jj	2008-01-28 10:45:55.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr34969.c	2008-01-28 10:45:29.000000000 +0100
@@ -0,0 +1,15 @@
+/* PR middle-end/34969 */
+/* { dg-do compile } */
+/* { dg-options "-O -fipa-cp -ffast-math" } */
+
+double
+foo (double x)
+{
+  return x * x;
+}
+
+double
+bar (void)
+{
+  return foo (0);
+}

	Jakub


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