aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-inline.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-08-09 17:23:19 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2013-08-09 15:23:19 +0000
commit042ae7d242e9def81372edef1eff1046851699f0 (patch)
tree9f0bf5f1369dcb3ba206377f3550a5b0a59cdd38 /gcc/tree-inline.c
parent6efa6002d5b3575c7e1f9096f2e0f15252ac9c4b (diff)
downloadgcc-042ae7d242e9def81372edef1eff1046851699f0.zip
gcc-042ae7d242e9def81372edef1eff1046851699f0.tar.gz
gcc-042ae7d242e9def81372edef1eff1046851699f0.tar.bz2
cgraphbuild.c (cgraph_rebuild_references): Rebuild only non-speculative refs.
* cgraphbuild.c (cgraph_rebuild_references): Rebuild only non-speculative refs. * cgraph.c (cgraph_update_edge_in_call_site_hash): New function. (cgraph_add_edge_to_call_site_hash): Deal with speculative calls. (cgraph_set_call_stmt): Likewise. (cgraph_create_edge_1): Fix release checking compilatoin; clear lto_stmt_uid. (cgraph_free_edge): Free indirect info. (cgraph_turn_edge_to_speculative): New function. (cgraph_speculative_call_info): New function. (cgraph_make_edge_direct): Return direct edge; handle speculation. (cgraph_redirect_edge_call_stmt_to_callee): Expand speculative edges. (dump_cgraph_node): Dump speculation. (verify_edge_count_and_frequency): Accept speculative edges. (verify_edge_corresponds_to_fndecl): Handle partitioned cgraph. (verify_cgraph_node): Handle speculation. * cgraph.h (cgraph_edge): Add SPECULATIVE flag. (cgraph_set_call_stmt): Update prototype. (cgraph_make_edge_direct): Update prototype. (cgraph_speculative_call_info): Declare. * ipa-cp.c (ipcp_discover_new_direct_edges): Be ready for edge to change; update call of ipa_find_references. * ipa-ref.c (ipa_record_reference): Fix return value; clear lto_stmt_uid and speculative flags. (ipa_dump_references): Dump speculation. (ipa_clone_references): Clone speculative flag. (ipa_clone_referring): Likewise. (ipa_clone_ref): New function. (ipa_find_reference): Look into lto_stmt_uids (ipa_clear_stmts_in_references): Do not clear speculative calls. * ipa-ref.h (ipa_ref): Add lto_stmt_uid and speculative flags. (ipa_find_reference): Update declaration. (ipa_clone_ref): Declare. * lto-cgraph.c (lto_output_edge): Make lto_stmt_uids start from 0; stream speculative flag. (lto_output_ref): Stream statements uids and speculation. (input_ref): Likewise. (input_edge): Stream speuclation. * cgraphclones.c (cgraph_clone_edge): Clone speculation. (cgraph_set_call_stmt_including_clones): Handle speculation. * ipa-inline.c (heap_edge_removal_hook): New function. (inline_small_functions): Register it. * lto-streamer-in.c (fixup_call_stmt_edges_1): Bounds checking; also initialize refs. * ipa-prop.c (ipa_make_edge_direct_to_target): Be ready for edge to change. (try_make_edge_direct_simple_call): Likewise. (try_make_edge_direct_simple_call): Likewise. (update_indirect_edges_after_inlining): Likewise. (remove_described_reference): Look proper lto_stmt_uid. (propagate_controlled_uses): Likewise. (propagate_controlled_uses): Liekwise. * tree-inline.c (copy_bb): Copy speculative edges. (redirect_all_calls): New function. (copy_cfg_body): Do redirection after loop info is updated. (delete_unreachable_blocks_update_callgraph): Updadte speculation. From-SVN: r201632
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r--gcc/tree-inline.c158
1 files changed, 108 insertions, 50 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index e33e5a3..00e3198 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1676,6 +1676,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
if (edge)
{
int edge_freq = edge->frequency;
+ int new_freq;
+ struct cgraph_edge *old_edge = edge;
edge = cgraph_clone_edge (edge, id->dst_node, stmt,
gimple_uid (stmt),
REG_BR_PROB_BASE, CGRAPH_FREQ_BASE,
@@ -1683,25 +1685,52 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
/* We could also just rescale the frequency, but
doing so would introduce roundoff errors and make
verifier unhappy. */
- edge->frequency
- = compute_call_stmt_bb_frequency (id->dst_node->symbol.decl,
- copy_basic_block);
- if (dump_file
- && profile_status_for_function (cfun) != PROFILE_ABSENT
- && (edge_freq > edge->frequency + 10
- || edge_freq < edge->frequency - 10))
+ new_freq = compute_call_stmt_bb_frequency (id->dst_node->symbol.decl,
+ copy_basic_block);
+
+ /* Speculative calls consist of two edges - direct and indirect.
+ Duplicate the whole thing and distribute frequencies accordingly. */
+ if (edge->speculative)
+ {
+ struct cgraph_edge *direct, *indirect;
+ struct ipa_ref *ref;
+
+ gcc_assert (!edge->indirect_unknown_callee);
+ cgraph_speculative_call_info (old_edge, direct, indirect, ref);
+ indirect = cgraph_clone_edge (indirect, id->dst_node, stmt,
+ gimple_uid (stmt),
+ REG_BR_PROB_BASE, CGRAPH_FREQ_BASE,
+ true);
+ if (old_edge->frequency + indirect->frequency)
+ {
+ edge->frequency = MIN (RDIV ((gcov_type)new_freq * old_edge->frequency,
+ (old_edge->frequency + indirect->frequency)),
+ CGRAPH_FREQ_MAX);
+ indirect->frequency = MIN (RDIV ((gcov_type)new_freq * indirect->frequency,
+ (old_edge->frequency + indirect->frequency)),
+ CGRAPH_FREQ_MAX);
+ }
+ ipa_clone_ref (ref, (symtab_node)id->dst_node, stmt);
+ }
+ else
{
- fprintf (dump_file, "Edge frequency estimated by "
- "cgraph %i diverge from inliner's estimate %i\n",
- edge_freq,
- edge->frequency);
- fprintf (dump_file,
- "Orig bb: %i, orig bb freq %i, new bb freq %i\n",
- bb->index,
- bb->frequency,
- copy_basic_block->frequency);
+ edge->frequency = new_freq;
+ if (dump_file
+ && profile_status_for_function (cfun) != PROFILE_ABSENT
+ && (edge_freq > edge->frequency + 10
+ || edge_freq < edge->frequency - 10))
+ {
+ fprintf (dump_file, "Edge frequency estimated by "
+ "cgraph %i diverge from inliner's estimate %i\n",
+ edge_freq,
+ edge->frequency);
+ fprintf (dump_file,
+ "Orig bb: %i, orig bb freq %i, new bb freq %i\n",
+ bb->index,
+ bb->frequency,
+ copy_basic_block->frequency);
+ }
}
- stmt = cgraph_redirect_edge_call_stmt_to_callee (edge);
}
break;
@@ -2232,6 +2261,23 @@ copy_loops (bitmap blocks_to_copy,
}
}
+/* Call cgraph_redirect_edge_call_stmt_to_callee on all calls in BB */
+
+void
+redirect_all_calls (copy_body_data * id, basic_block bb)
+{
+ gimple_stmt_iterator si;
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ if (is_gimple_call (gsi_stmt (si)))
+ {
+ struct cgraph_edge *edge = cgraph_edge (id->dst_node, gsi_stmt (si));
+ if (edge)
+ cgraph_redirect_edge_call_stmt_to_callee (edge);
+ }
+ }
+}
+
/* Make a copy of the body of FN so that it can be inserted inline in
another function. Walks FN via CFG, returns new fndecl. */
@@ -2356,6 +2402,10 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
&& bb->index != ENTRY_BLOCK
&& bb->index != EXIT_BLOCK)
maybe_move_debug_stmts_to_successors (id, (basic_block) bb->aux);
+ /* Update call edge destinations. This can not be done before loop
+ info is updated, because we may split basic blocks. */
+ if (id->transform_call_graph_edges == CB_CGE_DUPLICATE)
+ redirect_all_calls (id, (basic_block)bb->aux);
((basic_block)bb->aux)->aux = NULL;
bb->aux = NULL;
}
@@ -2367,6 +2417,10 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
if (need_debug_cleanup)
maybe_move_debug_stmts_to_successors (id, BASIC_BLOCK (last));
BASIC_BLOCK (last)->aux = NULL;
+ /* Update call edge destinations. This can not be done before loop
+ info is updated, because we may split basic blocks. */
+ if (id->transform_call_graph_edges == CB_CGE_DUPLICATE)
+ redirect_all_calls (id, BASIC_BLOCK (last));
}
entry_block_map->aux = NULL;
exit_block_map->aux = NULL;
@@ -4941,43 +4995,47 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id)
gimple_stmt_iterator bsi;
for (bsi = gsi_start_bb (b); !gsi_end_p (bsi); gsi_next (&bsi))
- if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL)
- {
- struct cgraph_edge *e;
- struct cgraph_node *node;
+ {
+ struct cgraph_edge *e;
+ struct cgraph_node *node;
- if ((e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
+ ipa_remove_stmt_references ((symtab_node)id->dst_node, gsi_stmt (bsi));
+
+ if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
+ &&(e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL)
+ {
+ if (!e->inline_failed)
+ cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
+ else
+ cgraph_remove_edge (e);
+ }
+ if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES
+ && id->dst_node->clones)
+ for (node = id->dst_node->clones; node != id->dst_node;)
{
- if (!e->inline_failed)
- cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
+ ipa_remove_stmt_references ((symtab_node)node, gsi_stmt (bsi));
+ if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL
+ && (e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
+ {
+ if (!e->inline_failed)
+ cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
+ else
+ cgraph_remove_edge (e);
+ }
+
+ if (node->clones)
+ node = node->clones;
+ else if (node->next_sibling_clone)
+ node = node->next_sibling_clone;
else
- cgraph_remove_edge (e);
+ {
+ while (node != id->dst_node && !node->next_sibling_clone)
+ node = node->clone_of;
+ if (node != id->dst_node)
+ node = node->next_sibling_clone;
+ }
}
- if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES
- && id->dst_node->clones)
- for (node = id->dst_node->clones; node != id->dst_node;)
- {
- if ((e = cgraph_edge (node, gsi_stmt (bsi))) != NULL)
- {
- if (!e->inline_failed)
- cgraph_remove_node_and_inline_clones (e->callee, id->dst_node);
- else
- cgraph_remove_edge (e);
- }
-
- if (node->clones)
- node = node->clones;
- else if (node->next_sibling_clone)
- node = node->next_sibling_clone;
- else
- {
- while (node != id->dst_node && !node->next_sibling_clone)
- node = node->clone_of;
- if (node != id->dst_node)
- node = node->next_sibling_clone;
- }
- }
- }
+ }
delete_basic_block (b);
changed = true;
}