This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Inliner heuristics TLC 2/n - dump stats about inliner behaviour


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]