diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-16 16:06:29 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-16 16:06:29 +0000 |
commit | e2d3f42272e712ce0bda8583066fdf858041ce77 (patch) | |
tree | 67e2fac7c1db371237d730ab058e8d5d1a4d330a /gcc/tree-inline.c | |
parent | 8bc34e340f263fe78def23eeb33c46a2501b7ae7 (diff) | |
download | gcc-e2d3f42272e712ce0bda8583066fdf858041ce77.tar.gz |
* cgraphbuild.c (compute_call_stmt_bb_frequency): Use proper ENTRY_BLOCK_PTR.
* cgraph.c (cgraph_clone_edge): Avoid freq_scale 0 to completely zero out all
callees.
* cgraphunit.c (verify_cgraph_node): Verify cgraph nodes for frequency and count match.
* ipa-inline.c (update_noncloned_frequencies): New function.
(cgraph_clone_inlined_nodes): Use it.
* tree-inline.c (copy_bb): Fix frequency scaling; output
diagnostic on frequency mismatches to dump file.
(initialize_cfun): Do not scale frequency; fix count scaling;
initialize entry and exit block frequencies; copy profile
info.
(copy_cfg_body): Use frequency_scale as argument;
fix count scaling.
(copy_body): Use frequency_scale as argument.
(expand_call_inline): Compute frequency scale and output diagnostic
to dump file.
(delete_unreachable_blocks_update_callgrah): Remove checking that
has to be done after edge redirection.
(tree_function_versioning): Update initialize_cfun and copy_body call.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154205 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 127 |
1 files changed, 62 insertions, 65 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 629ccfb524f..34a8e9d8d07 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1472,6 +1472,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, gimple_stmt_iterator gsi, copy_gsi, seq_gsi; basic_block copy_basic_block; tree decl; + gcov_type freq; /* create_basic_block() will append every new block to basic_block_info automatically. */ @@ -1481,11 +1482,12 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, /* We are going to rebuild frequencies from scratch. These values have just small importance to drive canonicalize_loop_headers. */ - copy_basic_block->frequency = ((gcov_type)bb->frequency - * frequency_scale / REG_BR_PROB_BASE); + freq = ((gcov_type)bb->frequency * frequency_scale / REG_BR_PROB_BASE); - if (copy_basic_block->frequency > BB_FREQ_MAX) - copy_basic_block->frequency = BB_FREQ_MAX; + /* We recompute frequencies after inlining, so this is quite safe. */ + if (freq > BB_FREQ_MAX) + freq = BB_FREQ_MAX; + copy_basic_block->frequency = freq; copy_gsi = gsi_start_bb (copy_basic_block); @@ -1631,10 +1633,34 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, case CB_CGE_DUPLICATE: edge = cgraph_edge (id->src_node, orig_stmt); if (edge) - edge = cgraph_clone_edge (edge, id->dst_node, stmt, - gimple_uid (stmt), - REG_BR_PROB_BASE, 1, - edge->frequency, true); + { + int edge_freq = edge->frequency; + edge = cgraph_clone_edge (edge, id->dst_node, stmt, + gimple_uid (stmt), + REG_BR_PROB_BASE, CGRAPH_FREQ_BASE, + edge->frequency, true); + /* 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->decl, + copy_basic_block); + 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); + } + } break; case CB_CGE_MOVE_CLONES: @@ -1674,7 +1700,8 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES) cgraph_create_edge_including_clones (id->dst_node, dest, stmt, bb->count, - compute_call_stmt_bb_frequency (id->dst_node->decl, bb), + compute_call_stmt_bb_frequency (id->dst_node->decl, + copy_basic_block), bb->loop_depth, CIF_ORIGINALLY_INDIRECT_CALL); else cgraph_create_edge (id->dst_node, dest, stmt, @@ -1948,24 +1975,16 @@ remap_decl_1 (tree decl, void *data) NEW_FNDECL to be build. CALLEE_FNDECL is the original */ static void -initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count, - int frequency) +initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count) { struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl); - gcov_type count_scale, frequency_scale; + gcov_type count_scale; if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count) count_scale = (REG_BR_PROB_BASE * count / ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count); else - count_scale = 1; - - if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency) - frequency_scale = (REG_BR_PROB_BASE * frequency - / - ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency); - else - frequency_scale = count_scale; + count_scale = REG_BR_PROB_BASE; /* Register specific tree functions. */ gimple_register_cfg_hooks (); @@ -1998,18 +2017,17 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count, init_empty_tree_cfg (); + profile_status_for_function (cfun) = profile_status_for_function (src_cfun); ENTRY_BLOCK_PTR->count = (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count * count_scale / REG_BR_PROB_BASE); - ENTRY_BLOCK_PTR->frequency = - (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency * - frequency_scale / REG_BR_PROB_BASE); + ENTRY_BLOCK_PTR->frequency + = ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency; EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count * count_scale / REG_BR_PROB_BASE); EXIT_BLOCK_PTR->frequency = - (EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency * - frequency_scale / REG_BR_PROB_BASE); + EXIT_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency; if (src_cfun->eh) init_eh_for_function (); @@ -2026,7 +2044,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count, another function. Walks FN via CFG, returns new fndecl. */ static tree -copy_cfg_body (copy_body_data * id, gcov_type count, int frequency, +copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale, basic_block entry_block_map, basic_block exit_block_map) { tree callee_fndecl = id->src_fn; @@ -2035,21 +2053,14 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency, struct function *cfun_to_copy; basic_block bb; tree new_fndecl = NULL; - gcov_type count_scale, frequency_scale; + gcov_type count_scale; int last; if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count) count_scale = (REG_BR_PROB_BASE * count / ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count); else - count_scale = 1; - - if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency) - frequency_scale = (REG_BR_PROB_BASE * frequency - / - ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->frequency); - else - frequency_scale = count_scale; + count_scale = REG_BR_PROB_BASE; /* Register specific tree functions. */ gimple_register_cfg_hooks (); @@ -2204,7 +2215,7 @@ copy_tree_body (copy_body_data *id) another function. */ static tree -copy_body (copy_body_data *id, gcov_type count, int frequency, +copy_body (copy_body_data *id, gcov_type count, int frequency_scale, basic_block entry_block_map, basic_block exit_block_map) { tree fndecl = id->src_fn; @@ -2212,7 +2223,7 @@ copy_body (copy_body_data *id, gcov_type count, int frequency, /* If this body has a CFG, walk CFG and copy. */ gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (fndecl))); - body = copy_cfg_body (id, count, frequency, entry_block_map, exit_block_map); + body = copy_cfg_body (id, count, frequency_scale, entry_block_map, exit_block_map); copy_debug_stmts (id); return body; @@ -3732,12 +3743,23 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) cfun->local_decls); } + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Inlining "); + print_generic_expr (dump_file, id->src_fn, 0); + fprintf (dump_file, " to "); + print_generic_expr (dump_file, id->dst_fn, 0); + fprintf (dump_file, " with frequency %i\n", cg_edge->frequency); + } + /* This is it. Duplicate the callee body. Assume callee is pre-gimplified. Note that we must not alter the caller function in any way before this point, as this CALL_EXPR may be a self-referential call; if we're calling ourselves, we need to duplicate our body before altering anything. */ - copy_body (id, bb->count, bb->frequency, bb, return_block); + copy_body (id, bb->count, + cg_edge->frequency * REG_BR_PROB_BASE / CGRAPH_FREQ_BASE, + bb, return_block); /* Reset the escaped and callused solutions. */ if (cfun->gimple_df) @@ -4732,30 +4754,6 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) if (changed) tidy_fallthru_edges (); -#ifdef ENABLE_CHECKING0 - verify_cgraph_node (id->dst_node); - if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES - && id->dst_node->clones) - { - struct cgraph_node *node; - for (node = id->dst_node->clones; node != id->dst_node;) - { - verify_cgraph_node (node); - - 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; - } - } - } -#endif return changed; } @@ -4876,8 +4874,7 @@ tree_function_versioning (tree old_decl, tree new_decl, old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (old_decl)); initialize_cfun (new_decl, old_decl, - old_entry_block->count, - old_entry_block->frequency); + old_entry_block->count); push_cfun (DECL_STRUCT_FUNCTION (new_decl)); /* Copy the function's static chain. */ @@ -4947,7 +4944,7 @@ tree_function_versioning (tree old_decl, tree new_decl, } /* Copy the Function's body. */ - copy_body (&id, old_entry_block->count, old_entry_block->frequency, + copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR); if (DECL_RESULT (old_decl) != NULL_TREE) |