aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/passes.c17
-rw-r--r--gcc/predict.c30
-rw-r--r--gcc/predict.h1
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c21
-rw-r--r--gcc/tree-inline.c46
7 files changed, 109 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ff7f4fd..0bfee7c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/passes.c b/gcc/passes.c
index 03de581..8828967 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -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
diff --git a/gcc/predict.c b/gcc/predict.c
index 1bccd4d..5d61140 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -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 ();
+}
diff --git a/gcc/predict.h b/gcc/predict.h
index 18e57d7..a0ca3a2 100644
--- a/gcc/predict.h
+++ b/gcc/predict.h
@@ -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 */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7338354..00e5e84 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c
new file mode 100644
index 0000000..05a37f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c
@@ -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);
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 2604c6b..3ef1cc3 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -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);