mirror of git://gcc.gnu.org/git/gcc.git
re PR middle-end/40084 (Revision 147294 failed 483.xalancbmk in SPEC CPU 2006 at -O3)
PR middle-end/40084 * cgraph.c (cgraph_update_edges_for_call_stmt_node): Take old_call argument; rewrite. (cgraph_update_edges_for_call_stmt): Take old_decl argument. * cgraph.h (cgraph_update_edges_for_call_stmt): Update prototype. * tree-inline.c (copy_bb): Set frequency correctly. (fold_marked_statements): Update call of cgraph_update_edges_for_call_stmt. From-SVN: r147337
This commit is contained in:
parent
51e61d333a
commit
4b685e144d
|
@ -1,3 +1,13 @@
|
||||||
|
2009-05-10 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
PR middle-end/40084
|
||||||
|
* cgraph.c (cgraph_update_edges_for_call_stmt_node): Take old_call argument;
|
||||||
|
rewrite.
|
||||||
|
(cgraph_update_edges_for_call_stmt): Take old_decl argument.
|
||||||
|
* cgraph.h (cgraph_update_edges_for_call_stmt): Update prototype.
|
||||||
|
* tree-inline.c (copy_bb): Set frequency correctly.
|
||||||
|
(fold_marked_statements): Update call of cgraph_update_edges_for_call_stmt.
|
||||||
|
|
||||||
2009-05-10 Joseph Myers <joseph@codesourcery.com>
|
2009-05-10 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* config/arc/arc.c (arc_handle_interrupt_attribute): Use %qE for
|
* config/arc/arc.c (arc_handle_interrupt_attribute): Use %qE for
|
||||||
|
|
75
gcc/cgraph.c
75
gcc/cgraph.c
|
@ -898,64 +898,81 @@ cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
|
||||||
|
|
||||||
|
|
||||||
/* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
|
/* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
|
||||||
OLD_STMT changed into NEW_STMT. */
|
OLD_STMT changed into NEW_STMT. OLD_CALL is gimple_call_fndecl
|
||||||
|
of OLD_STMT if it was previously call statement. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
|
cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node,
|
||||||
gimple old_stmt, gimple new_stmt)
|
gimple old_stmt, tree old_call, gimple new_stmt)
|
||||||
{
|
{
|
||||||
tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fn (new_stmt) : 0;
|
tree new_call = (is_gimple_call (new_stmt)) ? gimple_call_fndecl (new_stmt) : 0;
|
||||||
tree old_call = (is_gimple_call (old_stmt)) ? gimple_call_fn (old_stmt) : 0;
|
|
||||||
|
|
||||||
|
/* We are seeing indirect calls, then there is nothing to update. */
|
||||||
|
if (!new_call && !old_call)
|
||||||
|
return;
|
||||||
|
/* See if we turned indirect call into direct call or folded call to one builtin
|
||||||
|
into different bultin. */
|
||||||
if (old_call != new_call)
|
if (old_call != new_call)
|
||||||
{
|
{
|
||||||
struct cgraph_edge *e = cgraph_edge (node, old_stmt);
|
struct cgraph_edge *e = cgraph_edge (node, old_stmt);
|
||||||
struct cgraph_edge *ne = NULL;
|
struct cgraph_edge *ne = NULL;
|
||||||
tree new_decl;
|
gcov_type count;
|
||||||
|
int frequency;
|
||||||
|
int loop_nest;
|
||||||
|
|
||||||
if (e)
|
if (e)
|
||||||
{
|
{
|
||||||
gcov_type count = e->count;
|
/* See if the call is already there. It might be because of indirect
|
||||||
int frequency = e->frequency;
|
inlining already found it. */
|
||||||
int loop_nest = e->loop_nest;
|
if (new_call && e->callee->decl == new_call)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Otherwise remove edge and create new one; we can't simply redirect
|
||||||
|
since function has changed, so inline plan and other information
|
||||||
|
attached to edge is invalid. */
|
||||||
cgraph_remove_edge (e);
|
cgraph_remove_edge (e);
|
||||||
if (new_call)
|
count = e->count;
|
||||||
{
|
frequency = e->frequency;
|
||||||
new_decl = gimple_call_fndecl (new_stmt);
|
loop_nest = e->loop_nest;
|
||||||
if (new_decl)
|
}
|
||||||
{
|
else
|
||||||
ne = cgraph_create_edge (node, cgraph_node (new_decl),
|
{
|
||||||
new_stmt, count, frequency,
|
/* We are seeing new direct call; compute profile info based on BB. */
|
||||||
loop_nest);
|
basic_block bb = gimple_bb (new_stmt);
|
||||||
gcc_assert (ne->inline_failed);
|
count = bb->count;
|
||||||
}
|
frequency = compute_call_stmt_bb_frequency (current_function_decl,
|
||||||
}
|
bb);
|
||||||
|
loop_nest = bb->loop_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_call)
|
||||||
|
{
|
||||||
|
ne = cgraph_create_edge (node, cgraph_node (new_call),
|
||||||
|
new_stmt, count, frequency,
|
||||||
|
loop_nest);
|
||||||
|
gcc_assert (ne->inline_failed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* We only updated the call stmt; update pointer in cgraph edge.. */
|
||||||
else if (old_stmt != new_stmt)
|
else if (old_stmt != new_stmt)
|
||||||
{
|
cgraph_set_call_stmt (cgraph_edge (node, old_stmt), new_stmt);
|
||||||
struct cgraph_edge *e = cgraph_edge (node, old_stmt);
|
|
||||||
|
|
||||||
if (e)
|
|
||||||
cgraph_set_call_stmt (e, new_stmt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
|
/* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
|
||||||
OLD_STMT changed into NEW_STMT. */
|
OLD_STMT changed into NEW_STMT. OLD_DECL is gimple_call_fndecl
|
||||||
|
of OLD_STMT before it was updated (updating can happen inplace). */
|
||||||
|
|
||||||
void
|
void
|
||||||
cgraph_update_edges_for_call_stmt (gimple old_stmt, gimple new_stmt)
|
cgraph_update_edges_for_call_stmt (gimple old_stmt, tree old_decl, gimple new_stmt)
|
||||||
{
|
{
|
||||||
struct cgraph_node *orig = cgraph_node (cfun->decl);
|
struct cgraph_node *orig = cgraph_node (cfun->decl);
|
||||||
struct cgraph_node *node;
|
struct cgraph_node *node;
|
||||||
|
|
||||||
cgraph_update_edges_for_call_stmt_node (orig, old_stmt, new_stmt);
|
cgraph_update_edges_for_call_stmt_node (orig, old_stmt, old_decl, new_stmt);
|
||||||
if (orig->clones)
|
if (orig->clones)
|
||||||
for (node = orig->clones; node != orig;)
|
for (node = orig->clones; node != orig;)
|
||||||
{
|
{
|
||||||
cgraph_update_edges_for_call_stmt_node (node, old_stmt, new_stmt);
|
cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl, new_stmt);
|
||||||
if (node->clones)
|
if (node->clones)
|
||||||
node = node->clones;
|
node = node->clones;
|
||||||
else if (node->next_sibling_clone)
|
else if (node->next_sibling_clone)
|
||||||
|
|
|
@ -385,7 +385,7 @@ void cgraph_create_edge_including_clones (struct cgraph_node *,
|
||||||
struct cgraph_node *,
|
struct cgraph_node *,
|
||||||
gimple, gcov_type, int, int,
|
gimple, gcov_type, int, int,
|
||||||
cgraph_inline_failed_t);
|
cgraph_inline_failed_t);
|
||||||
void cgraph_update_edges_for_call_stmt (gimple, gimple);
|
void cgraph_update_edges_for_call_stmt (gimple, tree, gimple);
|
||||||
struct cgraph_local_info *cgraph_local_info (tree);
|
struct cgraph_local_info *cgraph_local_info (tree);
|
||||||
struct cgraph_global_info *cgraph_global_info (tree);
|
struct cgraph_global_info *cgraph_global_info (tree);
|
||||||
struct cgraph_rtl_info *cgraph_rtl_info (tree);
|
struct cgraph_rtl_info *cgraph_rtl_info (tree);
|
||||||
|
|
|
@ -1522,7 +1522,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
|
||||||
gcc_assert (dest->needed || !dest->analyzed);
|
gcc_assert (dest->needed || !dest->analyzed);
|
||||||
if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
|
if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
|
||||||
cgraph_create_edge_including_clones (id->dst_node, dest, stmt,
|
cgraph_create_edge_including_clones (id->dst_node, dest, stmt,
|
||||||
bb->count, CGRAPH_FREQ_BASE,
|
bb->count,
|
||||||
|
compute_call_stmt_bb_frequency (id->dst_node->decl, bb),
|
||||||
bb->loop_depth,
|
bb->loop_depth,
|
||||||
CIF_ORIGINALLY_INDIRECT_CALL);
|
CIF_ORIGINALLY_INDIRECT_CALL);
|
||||||
else
|
else
|
||||||
|
@ -3542,6 +3543,7 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
|
||||||
if (pointer_set_contains (statements, gsi_stmt (gsi)))
|
if (pointer_set_contains (statements, gsi_stmt (gsi)))
|
||||||
{
|
{
|
||||||
gimple old_stmt = gsi_stmt (gsi);
|
gimple old_stmt = gsi_stmt (gsi);
|
||||||
|
tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
|
||||||
|
|
||||||
if (fold_stmt (&gsi))
|
if (fold_stmt (&gsi))
|
||||||
{
|
{
|
||||||
|
@ -3550,8 +3552,9 @@ fold_marked_statements (int first, struct pointer_set_t *statements)
|
||||||
gimple new_stmt = gsi_stmt (gsi);
|
gimple new_stmt = gsi_stmt (gsi);
|
||||||
update_stmt (new_stmt);
|
update_stmt (new_stmt);
|
||||||
|
|
||||||
if (is_gimple_call (old_stmt))
|
if (is_gimple_call (old_stmt)
|
||||||
cgraph_update_edges_for_call_stmt (old_stmt, new_stmt);
|
|| is_gimple_call (new_stmt))
|
||||||
|
cgraph_update_edges_for_call_stmt (old_stmt, old_decl, new_stmt);
|
||||||
|
|
||||||
if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
|
if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
|
||||||
gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
|
gimple_purge_dead_eh_edges (BASIC_BLOCK (first));
|
||||||
|
|
Loading…
Reference in New Issue