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);


Reply via email to