(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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@201601
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
{
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?! */
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,
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;
}
}
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
/* 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);
}
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)
#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. */
{
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;
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;
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;
+}
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);
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)