Hi all,

This patch is an attempt to fix bug PR ipa/63576, corrected according
to note made by Jiong Wang:

On 27.10.2014 18:41, Jiong Wang wrote:
> 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);
>   ...
>   ...

Ok, that's right idea.

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.

Honza, can you explain your comment to the bug?

I've changed the patch, bootstrapped and
regtested on x86_64-unknown-linux-gnu again.

Ok for trunk?

--
Best regards,
Ilya Palachev

-------------------------------------------------------------------------------

gcc/

2014-10-27  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 | 43 +++++++++++++++++++++++++++++++++----------
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index e4ea84c..177a170 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -390,6 +390,37 @@ 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
+      || profile_status_for_fn (DECL_STRUCT_FUNCTION (dst->decl))
+               == PROFILE_ABSENT)
+    {
+      e->count = bb->count;
+      e->frequency = compute_call_stmt_bb_frequency (dst->decl, bb);
+      return;
+    }
+  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.  */
@@ -547,19 +578,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);
-- 
2.1.1

Reply via email to