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]

Clenaup ipa-fnsummary/ipa-inline after frequency removal


Hi,
now when frequencies are no longer part of cgraph structure, there is no need
to convert counts into fixed point CGRAPH_FREQ_BASE frequency and immediately
convert it into sreal. 

Old code lost precision but also capped large values (frequencies was never
over 10). I would be curious to know about negative impacts of this change.
We may want to have some cap for cases where statically estimated profile gets
out of scale and unrealistically large.

Bootstrapped/regtested x86_64-linux. Comitted.

Honza

	* cgraph.c (cgraph_edge::sreal_frequency): New function.
	* cgraph.h (cgraph_edge::sreal_frequency): Declare.
	* ipa-fnsummary.c (dump_ipa_call_summary): Use sreal_frequency.
	(estimate_edge_size_and_time): Likewise.
	(ipa_merge_fn_summary_after_inlining): Likewise.
	* ipa-inline.c (cgraph_freq_base_rec): Remove.
	(compute_uninlined_call_time): Use sreal_frequency.
	(compute_inlined_call_time): Likewise.
	(ipa_inline): Do not initialize cgraph_freq_base_rec.
	* profile-count.c: Include sreal.h.
	(profile_count::to_sreal_scale): New.
	* profile-count.h: Forward declare sreal.
	(profile_count::to_sreal_scale): Declare.
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 254690)
+++ cgraph.c	(working copy)
@@ -3880,4 +3880,16 @@ cgraph_node::has_thunk_p (cgraph_node *n
   return false;
 }
 
+/* Expected frequency of executions within the function.
+   When set to CGRAPH_FREQ_BASE, the edge is expected to be called once
+   per function call.  The range is 0 to CGRAPH_FREQ_MAX.  */
+
+sreal
+cgraph_edge::sreal_frequency ()
+{
+  return count.to_sreal_scale (caller->global.inlined_to
+			       ? caller->global.inlined_to->count
+			       : caller->count);
+}
+
 #include "gt-cgraph.h"
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 254690)
+++ cgraph.h	(working copy)
@@ -1766,6 +1766,9 @@ struct GTY((chain_next ("%h.next_caller"
      When set to CGRAPH_FREQ_BASE, the edge is expected to be called once
      per function call.  The range is 0 to CGRAPH_FREQ_MAX.  */
   int frequency ();
+
+  /* Expected frequency of executions within the function.  */
+  sreal sreal_frequency ();
 private:
   /* Remove the edge from the list of the callers of the callee.  */
   void remove_caller (void);
Index: ipa-fnsummary.c
===================================================================
--- ipa-fnsummary.c	(revision 254690)
+++ ipa-fnsummary.c	(working copy)
@@ -817,12 +817,12 @@ dump_ipa_call_summary (FILE *f, int inde
       int i;
 
       fprintf (f,
-	       "%*s%s/%i %s\n%*s  loop depth:%2i freq:%4i size:%2i"
+	       "%*s%s/%i %s\n%*s  loop depth:%2i freq:%4.2f size:%2i"
 	       " time: %2i callee size:%2i stack:%2i",
 	       indent, "", callee->name (), callee->order,
 	       !edge->inline_failed
 	       ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed),
-	       indent, "", es->loop_depth, edge->frequency (),
+	       indent, "", es->loop_depth, edge->sreal_frequency ().to_double (),
 	       es->call_stmt_size, es->call_stmt_time,
 	       (int) ipa_fn_summaries->get (callee)->size / ipa_fn_summary::size_scale,
 	       (int) ipa_fn_summaries->get (callee)->estimated_stack_size);
@@ -860,11 +860,12 @@ dump_ipa_call_summary (FILE *f, int inde
   for (edge = node->indirect_calls; edge; edge = edge->next_callee)
     {
       struct ipa_call_summary *es = ipa_call_summaries->get (edge);
-      fprintf (f, "%*sindirect call loop depth:%2i freq:%4i size:%2i"
+      fprintf (f, "%*sindirect call loop depth:%2i freq:%4.2f size:%2i"
 	       " time: %2i",
 	       indent, "",
 	       es->loop_depth,
-	       edge->frequency (), es->call_stmt_size, es->call_stmt_time);
+	       edge->sreal_frequency ().to_double (), es->call_stmt_size,
+	       es->call_stmt_time);
       if (es->predicate)
 	{
 	  fprintf (f, "predicate: ");
@@ -2578,10 +2579,10 @@ estimate_edge_size_and_time (struct cgra
   if (min_size)
     *min_size += cur_size;
   if (prob == REG_BR_PROB_BASE)
-    *time += ((sreal)(call_time * e->frequency ())) / CGRAPH_FREQ_BASE;
+    *time += ((sreal)call_time) * e->sreal_frequency ();
   else
-    *time += ((sreal)call_time) * (prob * e->frequency ())
-	      / (CGRAPH_FREQ_BASE * REG_BR_PROB_BASE);
+    *time += ((sreal)call_time * prob) * e->sreal_frequency ()
+	      / CGRAPH_FREQ_BASE;
 }
 
 
@@ -3058,7 +3059,7 @@ ipa_merge_fn_summary_after_inlining (str
 				      toplev_predicate);
       if (p != false && nonconstp != false)
 	{
-	  sreal add_time = ((sreal)e->time * edge->frequency ()) / CGRAPH_FREQ_BASE;
+	  sreal add_time = ((sreal)e->time * edge->sreal_frequency ());
 	  int prob = e->nonconst_predicate.probability (callee_info->conds,
 							clause, es->param);
 	  add_time = add_time * prob / REG_BR_PROB_BASE;
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 254690)
+++ ipa-inline.c	(working copy)
@@ -129,8 +129,8 @@ static int overall_size;
 static profile_count max_count;
 static profile_count spec_rem;
 
-/* Pre-computed constants 1/CGRAPH_FREQ_BASE and 1/100. */
-static sreal cgraph_freq_base_rec, percent_rec;
+/* Pre-computed constant 1/100. */
+static sreal percent_rec;
 
 /* Return false when inlining edge E would lead to violating
    limits on function unit growth or stack usage growth.  
@@ -644,8 +644,9 @@ compute_uninlined_call_time (struct cgra
       && caller->count.ipa ().nonzero_p ())
     uninlined_call_time *= (sreal)edge->count.ipa ().to_gcov_type ()
 			   / caller->count.ipa ().to_gcov_type ();
-  if (edge->frequency ())
-    uninlined_call_time *= cgraph_freq_base_rec * edge->frequency ();
+  sreal freq = edge->sreal_frequency ();
+  if (freq != 0)
+    uninlined_call_time *= freq;
   else
     uninlined_call_time = uninlined_call_time >> 11;
 
@@ -668,8 +669,9 @@ compute_inlined_call_time (struct cgraph
   if (edge->count.ipa ().nonzero_p ()
       && caller->count.ipa ().nonzero_p ())
     time *= (sreal)edge->count.to_gcov_type () / caller->count.to_gcov_type ();
-  if (edge->frequency ())
-    time *= cgraph_freq_base_rec * edge->frequency ();
+  sreal freq = edge->sreal_frequency ();
+  if (freq != 0)
+    time *= freq;
   else
     time = time >> 11;
 
@@ -2390,7 +2392,6 @@ ipa_inline (void)
   int cold;
   bool remove_functions = false;
 
-  cgraph_freq_base_rec = (sreal) 1 / (sreal) CGRAPH_FREQ_BASE;
   percent_rec = (sreal) 1 / (sreal) 100;
 
   order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
Index: profile-count.c
===================================================================
--- profile-count.c	(revision 254690)
+++ profile-count.c	(working copy)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
 #include "data-streamer.h"
 #include "cgraph.h"
 #include "wide-int.h"
+#include "sreal.h"
 
 /* Dump THIS to F.  */
 
@@ -256,6 +257,32 @@ profile_count::to_cgraph_frequency (prof
   return MIN (scale, CGRAPH_FREQ_MAX);
 }
 
+/* Return THIS/IN as sreal value.  */
+
+sreal
+profile_count::to_sreal_scale (profile_count in, bool *known) const
+{
+  if (!initialized_p ())
+    {
+      if (known)
+	*known = false;
+      return CGRAPH_FREQ_BASE;
+    }
+  if (known)
+    *known = true;
+  if (*this == profile_count::zero ())
+    return 0;
+  gcc_checking_assert (in.initialized_p ());
+
+  if (!in.m_val)
+    {
+      if (!m_val)
+	return 1;
+      return m_val * 4;
+    }
+  return (sreal)m_val / (sreal)in.m_val;
+}
+
 /* We want to scale profile across function boundary from NUM to DEN.
    Take care of the side case when DEN is zeros.  We still want to behave
    sanely here which means
Index: profile-count.h
===================================================================
--- profile-count.h	(revision 254690)
+++ profile-count.h	(working copy)
@@ -601,6 +601,8 @@ public:
 
  */
 
+class sreal;
+
 class GTY(()) profile_count
 {
   /* Use 62bit to hold basic block counters.  Should be at least
@@ -1034,6 +1036,7 @@ public:
 
   int to_frequency (struct function *fun) const;
   int to_cgraph_frequency (profile_count entry_bb_count) const;
+  sreal to_sreal_scale (profile_count in, bool *known = NULL) const;
 
   /* Output THIS to F.  */
   void dump (FILE *f) const;


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