From 71cafea943fbb7a69a92c80e6dfdb5de119bfb33 Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Thu, 8 Aug 2013 16:15:15 +0200
Subject: [PATCH] cgraphbuild.c (build_cgraph_edges): Do not walk into debugs.

	* cgraphbuild.c (build_cgraph_edges): Do not walk into debugs.
	(make_pass_rebuild_cgraph_edges): Also clear references.
	* cgraph.c (verify_cgraph_node): Add basic ipa-ref verifier.
	* ipa-inline-transform.c (inline_transform): Remove all references
	after inlining.
	* cgraphunit.c (expand_function): Remove all references after expansion.
	* ipa-ref.c (ipa_ref_has_aliases_p): Fix formatting.
	(ipa_find_reference): Rewrite to iterator.
	(remove_stmt_references): Likewise.
	(ipa_clear_stmts_in_references): New function.
	* ipa-ref.h (ipa_clear_stmts_in_references): Declare.
	* cgraphclones.c (cgraph_materialize_all_clones): Remove or clear references.
	* ipa-split.c (split_function): Remove references in split function.

From-SVN: r201601
---
 gcc/ChangeLog              |  16 ++++++
 gcc/cgraph.c               | 110 ++++++++++++++++++++++---------------
 gcc/cgraphbuild.c          |   7 ++-
 gcc/cgraphclones.c         |   7 ++-
 gcc/cgraphunit.c           |   1 +
 gcc/ipa-inline-transform.c |   1 +
 gcc/ipa-inline.c           |   1 +
 gcc/ipa-ref.c              |  18 +++++-
 gcc/ipa-ref.h              |   1 +
 gcc/ipa-split.c            |   1 +
 10 files changed, 114 insertions(+), 49 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e55b5db7608e..349981c24ef6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2013-08-08  Jan Hubicka  <jh@suse.cz>
+
+	* cgraphbuild.c (build_cgraph_edges): Do not walk into debugs.
+	(make_pass_rebuild_cgraph_edges): Also clear references.
+	* cgraph.c (verify_cgraph_node): Add basic ipa-ref verifier.
+	* ipa-inline-transform.c (inline_transform): Remove all references
+	after inlining.
+	* cgraphunit.c (expand_function): Remove all references after expansion.
+	* ipa-ref.c (ipa_ref_has_aliases_p): Fix formatting.
+	(ipa_find_reference): Rewrite to iterator.
+	(remove_stmt_references): Likewise.
+	(ipa_clear_stmts_in_references): New function.
+	* ipa-ref.h (ipa_clear_stmts_in_references): Declare.
+	* cgraphclones.c (cgraph_materialize_all_clones): Remove or clear references.
+	* ipa-split.c (split_function): Remove references in split function.
+
 2013-08-08  Richard Earnshaw  <rearnsha@arm.com>
 
 	PR target/57431
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index bb7016f441d3..d217b4af3c54 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2537,55 +2537,75 @@ verify_cgraph_node (struct cgraph_node *node)
     {
       if (this_cfun->cfg)
 	{
+	  pointer_set_t *stmts = pointer_set_create ();
+	  int i;
+	  struct ipa_ref *ref;
+
 	  /* Reach the trees by walking over the CFG, and note the
 	     enclosing basic-blocks in the call edges.  */
 	  FOR_EACH_BB_FN (this_block, this_cfun)
-	    for (gsi = gsi_start_bb (this_block);
-                 !gsi_end_p (gsi);
-                 gsi_next (&gsi))
-	      {
-		gimple stmt = gsi_stmt (gsi);
-		if (is_gimple_call (stmt))
-		  {
-		    struct cgraph_edge *e = cgraph_edge (node, stmt);
-		    tree decl = gimple_call_fndecl (stmt);
-		    if (e)
-		      {
-			if (e->aux)
-			  {
-			    error ("shared call_stmt:");
-			    cgraph_debug_gimple_stmt (this_cfun, stmt);
-			    error_found = true;
-			  }
-			if (!e->indirect_unknown_callee)
-			  {
-			    if (verify_edge_corresponds_to_fndecl (e, decl))
-			      {
-				error ("edge points to wrong declaration:");
-				debug_tree (e->callee->symbol.decl);
-				fprintf (stderr," Instead of:");
-				debug_tree (decl);
-				error_found = true;
-			      }
-			  }
-			else if (decl)
-			  {
-			    error ("an indirect edge with unknown callee "
-				   "corresponding to a call_stmt with "
-				   "a known declaration:");
-			    error_found = true;
-			    cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
-			  }
-			e->aux = (void *)1;
-		      }
-		    else if (decl)
-		      {
-			error ("missing callgraph edge for call stmt:");
-			cgraph_debug_gimple_stmt (this_cfun, stmt);
-			error_found = true;
-		      }
-		  }
+	    {
+	      for (gsi = gsi_start_phis (this_block);
+		   !gsi_end_p (gsi); gsi_next (&gsi))
+		pointer_set_insert (stmts, gsi_stmt (gsi));
+	      for (gsi = gsi_start_bb (this_block);
+		   !gsi_end_p (gsi);
+		   gsi_next (&gsi))
+		{
+		  gimple stmt = gsi_stmt (gsi);
+		  pointer_set_insert (stmts, stmt);
+		  if (is_gimple_call (stmt))
+		    {
+		      struct cgraph_edge *e = cgraph_edge (node, stmt);
+		      tree decl = gimple_call_fndecl (stmt);
+		      if (e)
+			{
+			  if (e->aux)
+			    {
+			      error ("shared call_stmt:");
+			      cgraph_debug_gimple_stmt (this_cfun, stmt);
+			      error_found = true;
+			    }
+			  if (!e->indirect_unknown_callee)
+			    {
+			      if (verify_edge_corresponds_to_fndecl (e, decl))
+				{
+				  error ("edge points to wrong declaration:");
+				  debug_tree (e->callee->symbol.decl);
+				  fprintf (stderr," Instead of:");
+				  debug_tree (decl);
+				  error_found = true;
+				}
+			    }
+			  else if (decl)
+			    {
+			      error ("an indirect edge with unknown callee "
+				     "corresponding to a call_stmt with "
+				     "a known declaration:");
+			      error_found = true;
+			      cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
+			    }
+			  e->aux = (void *)1;
+			}
+		      else if (decl)
+			{
+			  error ("missing callgraph edge for call stmt:");
+			  cgraph_debug_gimple_stmt (this_cfun, stmt);
+			  error_found = true;
+			}
+		    }
+		}
 	      }
+	    for (i = 0;
+		 ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);
+		 i++)
+	      if (ref->stmt && !pointer_set_contains (stmts, ref->stmt))
+		{
+		  error ("reference to dead statement");
+		  cgraph_debug_gimple_stmt (this_cfun, ref->stmt);
+		  error_found = true;
+		}
+	    pointer_set_destroy (stmts);
 	}
       else
 	/* No CFG available?!  */
diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c
index a7872dea9e16..333deed81460 100644
--- a/gcc/cgraphbuild.c
+++ b/gcc/cgraphbuild.c
@@ -318,6 +318,9 @@ build_cgraph_edges (void)
 	  gimple stmt = gsi_stmt (gsi);
 	  tree decl;
 
+	  if (is_gimple_debug (stmt))
+	    continue;
+
 	  if (is_gimple_call (stmt))
 	    {
 	      int freq = compute_call_stmt_bb_frequency (current_function_decl,
@@ -537,7 +540,9 @@ make_pass_rebuild_cgraph_edges (gcc::context *ctxt)
 static unsigned int
 remove_cgraph_callee_edges (void)
 {
-  cgraph_node_remove_callees (cgraph_get_node (current_function_decl));
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
+  cgraph_node_remove_callees (node);
+  ipa_remove_all_references (&node->symbol.ref_list);
   return 0;
 }
 
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 21ef1f57f12d..464c524fd28f 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -876,7 +876,12 @@ cgraph_materialize_all_clones (void)
     }
   FOR_EACH_FUNCTION (node)
     if (!node->symbol.analyzed && node->callees)
-      cgraph_node_remove_callees (node);
+      {
+        cgraph_node_remove_callees (node);
+	ipa_remove_all_references (&node->symbol.ref_list);
+      }
+    else
+      ipa_clear_stmts_in_references ((symtab_node)node);
   if (cgraph_dump_file)
     fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
 #ifdef ENABLE_CHECKING
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 1472483342f1..3cd2b417ca7b 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1677,6 +1677,7 @@ expand_function (struct cgraph_node *node)
   /* Eliminate all call edges.  This is important so the GIMPLE_CALL no longer
      points to the dead function body.  */
   cgraph_node_remove_callees (node);
+  ipa_remove_all_references (&node->symbol.ref_list);
 }
 
 
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index 5e666aee3871..54b113ac0001 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -414,6 +414,7 @@ inline_transform (struct cgraph_node *node)
 
   for (e = node->callees; e; e = e->next_callee)
     cgraph_redirect_edge_call_stmt_to_callee (e);
+  ipa_remove_all_references (&node->symbol.ref_list);
 
   timevar_push (TV_INTEGRATION);
   if (node->callees)
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 96cbc9a0133f..8c5b430b5a2c 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -2011,6 +2011,7 @@ early_inliner (void)
 #ifdef ENABLE_CHECKING
   verify_cgraph_node (node);
 #endif
+  ipa_remove_all_references (&node->symbol.ref_list);
 
   /* Even when not optimizing or not inlining inline always-inline
      functions.  */
diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c
index a6ffdf3e5bbd..d2c6002e1767 100644
--- a/gcc/ipa-ref.c
+++ b/gcc/ipa-ref.c
@@ -218,6 +218,7 @@ ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list)
 {
   struct ipa_ref *ref;
   int i;
+
   for (i = 0; ipa_ref_list_referring_iterate (ref_list, i, ref); i++)
     if (ref->use == IPA_REF_ALIAS)
       return true;
@@ -234,7 +235,7 @@ ipa_find_reference (symtab_node referring_node, symtab_node referred_node,
   struct ipa_ref *r = NULL;
   int i;
 
-  FOR_EACH_VEC_SAFE_ELT (referring_node->symbol.ref_list.references, i, r)
+  for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++)
     if (r->referred == referred_node
 	&& (in_lto_p || r->stmt == stmt))
       return r;
@@ -250,7 +251,20 @@ ipa_remove_stmt_references (symtab_node referring_node, gimple stmt)
   struct ipa_ref *r = NULL;
   int i;
 
-  FOR_EACH_VEC_SAFE_ELT (referring_node->symbol.ref_list.references, i, r)
+  for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++)
     if (r->stmt == stmt)
       ipa_remove_reference (r);
 }
+
+/* Remove all stmt references in non-speculative references.
+   Those are not maintained during inlining & clonning. */
+
+void
+ipa_clear_stmts_in_references (symtab_node referring_node)
+{
+  struct ipa_ref *r = NULL;
+  int i;
+
+  for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++)
+    r->stmt = NULL;
+}
diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
index c25e4e46f9da..0b37a14ee6e1 100644
--- a/gcc/ipa-ref.h
+++ b/gcc/ipa-ref.h
@@ -75,3 +75,4 @@ bool ipa_ref_cannot_lead_to_return (struct ipa_ref *);
 bool ipa_ref_has_aliases_p (struct ipa_ref_list *);
 struct ipa_ref * ipa_find_reference (symtab_node, symtab_node, gimple);
 void ipa_remove_stmt_references (symtab_node, gimple);
+void ipa_clear_stmts_in_references (symtab_node);
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index c83c4d04dbfa..faf7c8480c96 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1223,6 +1223,7 @@ split_function (struct split_point *split_point)
       DECL_FUNCTION_CODE (node->symbol.decl) = (enum built_in_function) 0;
     }
   cgraph_node_remove_callees (cur_node);
+  ipa_remove_all_references (&cur_node->symbol.ref_list);
   if (!split_part_return_p)
     TREE_THIS_VOLATILE (node->symbol.decl) = 1;
   if (dump_file)
-- 
GitLab