Hi,
this patch adds dumping of some summary stats that I used to getnerate
data for 
http://hubicka.blogspot.ca/2014/04/devirtualization-in-c-part-5-feedback.html
and found it relatively enlightening, so I think they are useful for mainline, 
too.

Bootstrapped/regtested x86_64-linux, comitted.

        * ipa-inline.c (spec_rem): New static variable.
        (dump_overall_stats): New function.
        (dump_inline_stats): New function.
Index: ipa-inline.c
===================================================================
--- ipa-inline.c        (revision 209490)
+++ ipa-inline.c        (working copy)
@@ -127,6 +127,7 @@ along with GCC; see the file COPYING3.
 static int overall_size;
 static gcov_type max_count;
 static sreal max_count_real, max_relbenefit_real, half_int_min_real;
+static gcov_type spec_rem;
 
 /* Return false when inlining edge E would lead to violating
    limits on function unit growth or stack usage growth.  
@@ -1533,6 +1534,7 @@ resolve_noninline_speculation (fibheap_t
                                  ? node->global.inlined_to : node;
       bitmap updated_nodes = BITMAP_ALLOC (NULL);
 
+      spec_rem += edge->count;
       cgraph_resolve_speculation (edge, NULL);
       reset_edge_caches (where);
       inline_update_overall_summary (where);
@@ -1996,6 +1998,130 @@ inline_to_all_callers (struct cgraph_nod
   return false;
 }
 
+/* Output overall time estimate.  */
+static void
+dump_overall_stats (void)
+{
+  HOST_WIDEST_INT sum_weighted = 0, sum = 0;
+  struct cgraph_node *node;
+
+  FOR_EACH_DEFINED_FUNCTION (node)
+    if (!node->global.inlined_to
+       && !node->alias)
+      {
+       int time = inline_summary (node)->time;
+       sum += time;
+       sum_weighted += time * node->count;
+      }
+  fprintf (dump_file, "Overall time estimate: "
+          HOST_WIDEST_INT_PRINT_DEC" weighted by profile: "
+          HOST_WIDEST_INT_PRINT_DEC"\n", sum, sum_weighted);
+}
+
+/* Output some useful stats about inlining.  */
+
+static void
+dump_inline_stats (void)
+{
+  HOST_WIDEST_INT inlined_cnt = 0, inlined_indir_cnt = 0;
+  HOST_WIDEST_INT inlined_virt_cnt = 0, inlined_virt_indir_cnt = 0;
+  HOST_WIDEST_INT noninlined_cnt = 0, noninlined_indir_cnt = 0;
+  HOST_WIDEST_INT noninlined_virt_cnt = 0, noninlined_virt_indir_cnt = 0;
+  HOST_WIDEST_INT  inlined_speculative = 0, inlined_speculative_ply = 0;
+  HOST_WIDEST_INT indirect_poly_cnt = 0, indirect_cnt = 0;
+  HOST_WIDEST_INT reason[CIF_N_REASONS][3];
+  int i;
+  struct cgraph_node *node;
+
+  memset (reason, 0, sizeof (reason));
+  FOR_EACH_DEFINED_FUNCTION (node)
+  {
+    struct cgraph_edge *e;
+    for (e = node->callees; e; e = e->next_callee)
+      {
+       if (e->inline_failed)
+         {
+           reason[(int) e->inline_failed][0] += e->count;
+           reason[(int) e->inline_failed][1] += e->frequency;
+           reason[(int) e->inline_failed][2] ++;
+           if (DECL_VIRTUAL_P (e->callee->decl))
+             {
+               if (e->indirect_inlining_edge)
+                 noninlined_virt_indir_cnt += e->count;
+               else
+                 noninlined_virt_cnt += e->count;
+             }
+           else
+             {
+               if (e->indirect_inlining_edge)
+                 noninlined_indir_cnt += e->count;
+               else
+                 noninlined_cnt += e->count;
+             }
+         }
+       else
+         {
+           if (e->speculative)
+             {
+               if (DECL_VIRTUAL_P (e->callee->decl))
+                 inlined_speculative_ply += e->count;
+               else
+                 inlined_speculative += e->count;
+             }
+           else if (DECL_VIRTUAL_P (e->callee->decl))
+             {
+               if (e->indirect_inlining_edge)
+                 inlined_virt_indir_cnt += e->count;
+               else
+                 inlined_virt_cnt += e->count;
+             }
+           else
+             {
+               if (e->indirect_inlining_edge)
+                 inlined_indir_cnt += e->count;
+               else
+                 inlined_cnt += e->count;
+             }
+         }
+      }
+    for (e = node->indirect_calls; e; e = e->next_callee)
+      if (e->indirect_info->polymorphic)
+       indirect_poly_cnt += e->count;
+      else
+       indirect_cnt += e->count;
+  }
+  if (max_count)
+    {
+      fprintf (dump_file,
+              "Inlined " HOST_WIDEST_INT_PRINT_DEC " + speculative "
+              HOST_WIDEST_INT_PRINT_DEC " + speculative polymorphic "
+              HOST_WIDEST_INT_PRINT_DEC " + previously indirect "
+              HOST_WIDEST_INT_PRINT_DEC " + virtual "
+              HOST_WIDEST_INT_PRINT_DEC " + virtual and previously indirect "
+              HOST_WIDEST_INT_PRINT_DEC "\n" "Not inlined "
+              HOST_WIDEST_INT_PRINT_DEC " + previously indirect "
+              HOST_WIDEST_INT_PRINT_DEC " + virtual "
+              HOST_WIDEST_INT_PRINT_DEC " + virtual and previously indirect "
+              HOST_WIDEST_INT_PRINT_DEC " + stil indirect "
+              HOST_WIDEST_INT_PRINT_DEC " + still indirect polymorphic "
+              HOST_WIDEST_INT_PRINT_DEC "\n", inlined_cnt,
+              inlined_speculative, inlined_speculative_ply,
+              inlined_indir_cnt, inlined_virt_cnt, inlined_virt_indir_cnt,
+              noninlined_cnt, noninlined_indir_cnt, noninlined_virt_cnt,
+              noninlined_virt_indir_cnt, indirect_cnt, indirect_poly_cnt);
+      fprintf (dump_file,
+              "Removed speculations " HOST_WIDEST_INT_PRINT_DEC "\n",
+              spec_rem);
+    }
+  dump_overall_stats ();
+  fprintf (dump_file, "\nWhy inlining failed?\n");
+  for (i = 0; i < CIF_N_REASONS; i++)
+    if (reason[i][2])
+      fprintf (dump_file, "%-50s: %8i calls, %8i freq, 
"HOST_WIDEST_INT_PRINT_DEC" count\n",
+              cgraph_inline_failed_string ((cgraph_inline_failed_t) i),
+              (int) reason[i][2], (int) reason[i][1], reason[i][0]);
+}
+
 /* Decide on the inlining.  We do so in the topological order to avoid
    expenses on updating data structures.  */
 
@@ -2048,6 +2174,8 @@ ipa_inline (void)
          flatten_function (node, false);
        }
     }
+  if (dump_file)
+    dump_overall_stats ();
 
   inline_small_functions ();
 
@@ -2092,6 +2220,7 @@ ipa_inline (void)
              if (edge->speculative && !speculation_useful_p (edge, false))
                {
                  cgraph_resolve_speculation (edge, NULL);
+                 spec_rem += edge->count;
                  update = true;
                  remove_functions = true;
                }
@@ -2122,9 +2251,12 @@ ipa_inline (void)
     ipa_free_all_structures_after_iinln ();
 
   if (dump_file)
-    fprintf (dump_file,
-            "\nInlined %i calls, eliminated %i functions\n\n",
-            ncalls_inlined, nfunctions_inlined);
+    {
+      fprintf (dump_file,
+              "\nInlined %i calls, eliminated %i functions\n\n",
+              ncalls_inlined, nfunctions_inlined);
+      dump_inline_stats ();
+    }
 
   if (dump_file)
     dump_inline_summaries (dump_file);

Reply via email to