Message ID | 1414423835-7124-1-git-send-email-i.palachev@samsung.com |
---|---|
State | New |
Headers | show |
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.palachev@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);
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; + } + } +} /* 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);