predict.c (propagate_freq): Clear EXIT_BLOCK_PTR frequency if it is unreachable.

* predict.c (propagate_freq): Clear EXIT_BLOCK_PTR frequency if it is
	unreachable.
	(rebuild_frequencies): New function.
	* predict.h (rebuild_frequencies): Declare.
	* tree-inline.c (copy_cfg_body): Compute properly count & frequency of
	entry block and edge reaching new_entry.
	(tree_function_versioning): When doing partial cloning, rebuild frequencies
	when done.
	* passes.c (execute_function_todo): Use rebild_frequencies.

From-SVN: r161536
This commit is contained in:
Jan Hubicka 2010-06-29 16:14:15 +02:00 committed by Jan Hubicka
parent 50b56694bb
commit b35366ce42
7 changed files with 109 additions and 22 deletions

View File

@ -1,3 +1,15 @@
2010-06-29 Jan Hubicka <jh@suse.cz>
* predict.c (propagate_freq): Clear EXIT_BLOCK_PTR frequency if it is
unreachable.
(rebuild_frequencies): New function.
* predict.h (rebuild_frequencies): Declare.
* tree-inline.c (copy_cfg_body): Compute properly count & frequency of
entry block and edge reaching new_entry.
(tree_function_versioning): When doing partial cloning, rebuild frequencies
when done.
* passes.c (execute_function_todo): Use rebild_frequencies.
2010-06-29 Richard Guenther <rguenther@suse.de>
* tree-dfa.c (dump_variable): Remove noalias_state dumping.

View File

@ -1243,22 +1243,7 @@ execute_function_todo (void *data)
}
if (flags & TODO_rebuild_frequencies)
{
if (profile_status == PROFILE_GUESSED)
{
loop_optimizer_init (0);
add_noreturn_fake_exit_edges ();
mark_irreducible_loops ();
connect_infinite_loops_to_exit ();
estimate_bb_frequencies ();
remove_fake_exit_edges ();
loop_optimizer_finalize ();
}
else if (profile_status == PROFILE_READ)
counts_to_freqs ();
else
gcc_unreachable ();
}
rebuild_frequencies ();
#if defined ENABLE_CHECKING
if (flags & TODO_verify_ssa

View File

@ -1855,9 +1855,6 @@ propagate_freq (basic_block head, bitmap tovisit)
edge_iterator ei;
int count = 0;
/* The outermost "loop" includes the exit block, which we can not
look up via BASIC_BLOCK. Detect this and use EXIT_BLOCK_PTR
directly. Do the same for the entry block. */
bb = BASIC_BLOCK (i);
FOR_EACH_EDGE (e, ei, bb->preds)
@ -1872,6 +1869,9 @@ propagate_freq (basic_block head, bitmap tovisit)
e->src->index, bb->index);
}
BLOCK_INFO (bb)->npredecessors = count;
/* When function never returns, we will never process exit block. */
if (!count && bb == EXIT_BLOCK_PTR)
bb->count = bb->frequency = 0;
}
memcpy (&BLOCK_INFO (head)->frequency, &real_one, sizeof (real_one));
@ -2282,3 +2282,27 @@ struct gimple_opt_pass pass_strip_predict_hints =
TODO_ggc_collect | TODO_verify_ssa /* todo_flags_finish */
}
};
/* Rebuild function frequencies. Passes are in general expected to
maintain profile by hand, however in some cases this is not possible:
for example when inlining several functions with loops freuqencies might run
out of scale and thus needs to be recomputed. */
void
rebuild_frequencies (void)
{
if (profile_status == PROFILE_GUESSED)
{
loop_optimizer_init (0);
add_noreturn_fake_exit_edges ();
mark_irreducible_loops ();
connect_infinite_loops_to_exit ();
estimate_bb_frequencies ();
remove_fake_exit_edges ();
loop_optimizer_finalize ();
}
else if (profile_status == PROFILE_READ)
counts_to_freqs ();
else
gcc_unreachable ();
}

View File

@ -42,5 +42,6 @@ extern const char *predictor_name (enum br_predictor);
extern tree build_predict_expr (enum br_predictor, enum prediction);
extern void tree_estimate_probability (void);
extern void compute_function_frequency (void);
extern void rebuild_frequencies (void);
#endif /* GCC_PREDICT_H */

View File

@ -1,3 +1,7 @@
2010-06-29 Jan Hubicka <jh@suse.cz>
* gcc.dg/tree-ssa/ipa-split-3.c: New testcase.
2010-06-29 Bernd Schmidt <bernds@codesourcery.com>
PR target/43902

View File

@ -0,0 +1,21 @@
int baz (void);
static int
foo (int x)
{
if (__builtin_expect (x <= 0, 0))
{
__builtin_printf ("foo\n");
__builtin_printf ("foo\n");
__builtin_printf ("foo\n");
__builtin_abort ();
}
return 6;
}
int a,b,c;
int
bar (int x)
{
return foo (a) + foo (b) + foo (c);
}

View File

@ -2159,6 +2159,8 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
bool need_debug_cleanup = false;
gcov_type count_scale;
int last;
int incomming_frequency = 0;
gcov_type incomming_count = 0;
if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)
count_scale = (REG_BR_PROB_BASE * count
@ -2169,6 +2171,28 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
/* Register specific tree functions. */
gimple_register_cfg_hooks ();
/* If we are inlining just region of the function, make sure to connect new entry
to ENTRY_BLOCK_PTR. Since new entry can be part of loop, we must compute
frequency and probability of ENTRY_BLOCK_PTR based on the frequencies and
probabilities of edges incomming from nonduplicated region. */
if (new_entry)
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, new_entry->preds)
if (!e->src->aux)
{
incomming_frequency += EDGE_FREQUENCY (e);
incomming_count += e->count;
}
incomming_count = incomming_count * count_scale / REG_BR_PROB_BASE;
incomming_frequency
= incomming_frequency * frequency_scale / REG_BR_PROB_BASE;
ENTRY_BLOCK_PTR->count = incomming_count;
ENTRY_BLOCK_PTR->frequency = incomming_frequency;
}
/* Must have a CFG here at this point. */
gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION
(DECL_STRUCT_FUNCTION (callee_fndecl)));
@ -2204,10 +2228,9 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
if (new_entry)
{
edge e;
e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
e->probability = REG_BR_PROB_BASE;
e->count = entry_block_map->count;
e->count = incomming_count;
}
if (gimple_in_ssa_p (cfun))
@ -5206,6 +5229,23 @@ tree_function_versioning (tree old_decl, tree new_decl,
if (id.dst_node->analyzed)
cgraph_rebuild_references ();
update_ssa (TODO_update_ssa);
/* After partial cloning we need to rescale frequencies, so they are
within proper range in the cloned function. */
if (new_entry)
{
struct cgraph_edge *e;
rebuild_frequencies ();
new_version_node->count = ENTRY_BLOCK_PTR->count;
for (e = new_version_node->callees; e; e = e->next_callee)
{
basic_block bb = gimple_bb (e->call_stmt);
e->frequency = compute_call_stmt_bb_frequency (current_function_decl, bb);
e->count = bb->count;
}
}
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);