mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
50b56694bb
commit
b35366ce42
|
@ -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>
|
2010-06-29 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
* tree-dfa.c (dump_variable): Remove noalias_state dumping.
|
* tree-dfa.c (dump_variable): Remove noalias_state dumping.
|
||||||
|
|
17
gcc/passes.c
17
gcc/passes.c
|
@ -1243,22 +1243,7 @@ execute_function_todo (void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & TODO_rebuild_frequencies)
|
if (flags & TODO_rebuild_frequencies)
|
||||||
{
|
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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined ENABLE_CHECKING
|
#if defined ENABLE_CHECKING
|
||||||
if (flags & TODO_verify_ssa
|
if (flags & TODO_verify_ssa
|
||||||
|
|
|
@ -1855,9 +1855,6 @@ propagate_freq (basic_block head, bitmap tovisit)
|
||||||
edge_iterator ei;
|
edge_iterator ei;
|
||||||
int count = 0;
|
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);
|
bb = BASIC_BLOCK (i);
|
||||||
|
|
||||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||||
|
@ -1872,6 +1869,9 @@ propagate_freq (basic_block head, bitmap tovisit)
|
||||||
e->src->index, bb->index);
|
e->src->index, bb->index);
|
||||||
}
|
}
|
||||||
BLOCK_INFO (bb)->npredecessors = count;
|
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));
|
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 */
|
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 ();
|
||||||
|
}
|
||||||
|
|
|
@ -42,5 +42,6 @@ extern const char *predictor_name (enum br_predictor);
|
||||||
extern tree build_predict_expr (enum br_predictor, enum prediction);
|
extern tree build_predict_expr (enum br_predictor, enum prediction);
|
||||||
extern void tree_estimate_probability (void);
|
extern void tree_estimate_probability (void);
|
||||||
extern void compute_function_frequency (void);
|
extern void compute_function_frequency (void);
|
||||||
|
extern void rebuild_frequencies (void);
|
||||||
|
|
||||||
#endif /* GCC_PREDICT_H */
|
#endif /* GCC_PREDICT_H */
|
||||||
|
|
|
@ -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>
|
2010-06-29 Bernd Schmidt <bernds@codesourcery.com>
|
||||||
|
|
||||||
PR target/43902
|
PR target/43902
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -2159,6 +2159,8 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale,
|
||||||
bool need_debug_cleanup = false;
|
bool need_debug_cleanup = false;
|
||||||
gcov_type count_scale;
|
gcov_type count_scale;
|
||||||
int last;
|
int last;
|
||||||
|
int incomming_frequency = 0;
|
||||||
|
gcov_type incomming_count = 0;
|
||||||
|
|
||||||
if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)
|
if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)
|
||||||
count_scale = (REG_BR_PROB_BASE * 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. */
|
/* Register specific tree functions. */
|
||||||
gimple_register_cfg_hooks ();
|
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. */
|
/* Must have a CFG here at this point. */
|
||||||
gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION
|
gcc_assert (ENTRY_BLOCK_PTR_FOR_FUNCTION
|
||||||
(DECL_STRUCT_FUNCTION (callee_fndecl)));
|
(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)
|
if (new_entry)
|
||||||
{
|
{
|
||||||
edge e;
|
edge e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
|
||||||
e = make_edge (entry_block_map, (basic_block)new_entry->aux, EDGE_FALLTHRU);
|
|
||||||
e->probability = REG_BR_PROB_BASE;
|
e->probability = REG_BR_PROB_BASE;
|
||||||
e->count = entry_block_map->count;
|
e->count = incomming_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gimple_in_ssa_p (cfun))
|
if (gimple_in_ssa_p (cfun))
|
||||||
|
@ -5206,6 +5229,23 @@ tree_function_versioning (tree old_decl, tree new_decl,
|
||||||
if (id.dst_node->analyzed)
|
if (id.dst_node->analyzed)
|
||||||
cgraph_rebuild_references ();
|
cgraph_rebuild_references ();
|
||||||
update_ssa (TODO_update_ssa);
|
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_DOMINATORS);
|
||||||
free_dominance_info (CDI_POST_DOMINATORS);
|
free_dominance_info (CDI_POST_DOMINATORS);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue