On 27/10/14 15:30, Ilya Palachev wrote:
Hi all,
The attached patch is an attempt to fix the bug PR ipa/63576.
As it is said in the comment to the bug,
Jan Hubicka wrote:
THen you need to sum counts (instead of taking ones from BB) and
turn them back to frequencies (because it is profile only counts
should be non-0)
It seems that counts and frequencies are gathered in some special
manner, and this patch simply adds counts from speculative edges and
from basic blocks. Of course, I don't know whether this way is proper
one, so please correct me or redirect to right place where it is
documented :)
Anyway, the patch was bootstrapped and regtested on
x86_64-unknown-linux-gnu.
Ok for trunk?
gcc/
2014-10-22 Ilya Palachev <i.palac...@samsung.com>
* ipa-utils.c (compute_edge_count_and_frequency): New function
(ipa_merge_profiles): handle speculative case
---
gcc/ipa-utils.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 42 insertions(+), 10 deletions(-)
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 552071e..335ab05 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -380,6 +380,46 @@ get_base_var (tree t)
return t;
}
+/* Computes count and frequency for edges. */
+
+static void
+compute_edge_count_and_frequency(struct cgraph_edge *e,
+ struct cgraph_node *dst)
+{
+ basic_block bb = gimple_bb (e->call_stmt);
+ if (!e->speculative)
+ {
+ e->count = bb->count;
+ e->frequency = compute_call_stmt_bb_frequency (dst->decl, bb);
+ }
+ else
+ {
+ if (profile_status_for_fn (DECL_STRUCT_FUNCTION (dst->decl))
+ == PROFILE_ABSENT)
+ {
+ e->count = bb->count;
+ e->frequency = CGRAPH_FREQ_BASE;
+ }
+ else
+ {
+ gcc_assert (e->count >= 0);
+ e->count += bb->count;
+ gcc_assert (e->frequency >= 0);
+
+ int entry_freq = ENTRY_BLOCK_PTR_FOR_FN
+ (DECL_STRUCT_FUNCTION (dst->decl))->frequency;
+ int freq = e->frequency + bb->frequency;
+
+ if (!entry_freq)
+ entry_freq = 1, freq++;
+
+ freq = freq * CGRAPH_FREQ_BASE / entry_freq;
+ if (freq > CGRAPH_FREQ_MAX)
+ freq = CGRAPH_FREQ_MAX;
+ e->frequency = freq;
+ }
+ }
+}
how about using early exit for above code, something like:
if (!e->speculative
|| profile_status_for_fn (DECL_STRUCT_FUNCTION (dst->decl))
== PROFILE_ABSEN))
{
e->count = bb->count;
e->frequency = (e->speculative ? CGRAPH_FREQ_BASE
: compute_call_stmt_bb_frequency (dst->decl, bb));
return;
}
gcc_assert (e->count >= 0);
...
...
/* SRC and DST are going to be merged. Take SRC's profile and merge it into
DST so it is not going to be lost. Destroy SRC's body on the way. */
@@ -537,19 +577,11 @@ ipa_merge_profiles (struct cgraph_node *dst,
pop_cfun ();
for (e = dst->callees; e; e = e->next_callee)
{
- gcc_assert (!e->speculative);
- e->count = gimple_bb (e->call_stmt)->count;
- e->frequency = compute_call_stmt_bb_frequency
- (dst->decl,
- gimple_bb (e->call_stmt));
+ compute_edge_count_and_frequency(e, dst);
}
for (e = dst->indirect_calls; e; e = e->next_callee)
{
- gcc_assert (!e->speculative);
- e->count = gimple_bb (e->call_stmt)->count;
- e->frequency = compute_call_stmt_bb_frequency
- (dst->decl,
- gimple_bb (e->call_stmt));
+ compute_edge_count_and_frequency(e, dst);
}
src->release_body ();
inline_update_overall_summary (dst);