From fa5f5e275ffb6346e1f35180cd3a7283c98340dd Mon Sep 17 00:00:00 2001
From: Jan Hubicka <jh@suse.cz>
Date: Tue, 27 Apr 2010 11:44:30 +0200
Subject: [PATCH] cgraph.c (cgraph_propagate_frequency): New function.

	* cgraph.c (cgraph_propagate_frequency): New function.
	* cgraph.h (cgraph_propagate_frequency): Declare.
	* ipa-inline.c (cgraph_clone_inlined_nodes): Call
	cgraph_propagate_frequency.

	* testsuite/gcc.dg/ipa/iinline-1.c (main): Rename to...
	(test): ... this one.

From-SVN: r158775
---
 gcc/ChangeLog                        |  7 ++++
 gcc/cgraph.c                         | 63 ++++++++++++++++++++++++++++
 gcc/cgraph.h                         |  1 +
 gcc/ipa-inline.c                     |  1 +
 gcc/testsuite/ChangeLog              |  5 +++
 gcc/testsuite/gcc.dg/ipa/iinline-1.c |  4 +-
 6 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index fe4e26ec3495..65c8feab413d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2010-04-27  Jan Hubicka  <jh@suse.cz>
+
+	* cgraph.c (cgraph_propagate_frequency): New function.
+	* cgraph.h (cgraph_propagate_frequency): Declare.
+	* ipa-inline.c (cgraph_clone_inlined_nodes): Call
+	cgraph_propagate_frequency.
+
 2010-04-27  Jakub Jelinek  <jakub@redhat.com>
 
 	* unwind-dw2.c (_Unwind_DebugHook): Add used and noclone attributes.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index b58d4ee5516d..95f441132f39 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2307,4 +2307,67 @@ cgraph_set_looping_const_or_pure_flag (struct cgraph_node *node,
     DECL_LOOPING_CONST_OR_PURE_P (alias->decl) = looping_const_or_pure;
 }
 
+/* See if the frequency of NODE can be updated based on frequencies of its
+   callers.  */
+bool
+cgraph_propagate_frequency (struct cgraph_node *node)
+{
+  bool maybe_unlikely_executed = true, maybe_executed_once = true;
+  struct cgraph_edge *edge;
+  if (node->needed || node->local.externally_visible)
+    return false;
+  gcc_assert (node->analyzed);
+  if (node->frequency == NODE_FREQUENCY_HOT)
+    return false;
+  if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
+    return false;
+  if (dump_file && (dump_flags & TDF_DETAILS))
+    fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
+  for (edge = node->callers;
+       edge && (maybe_unlikely_executed || maybe_executed_once);
+       edge = edge->next_caller)
+    {
+      if (!edge->frequency)
+	continue;
+      switch (edge->caller->frequency)
+        {
+	case NODE_FREQUENCY_UNLIKELY_EXECUTED:
+	  break;
+	case NODE_FREQUENCY_EXECUTED_ONCE:
+	  if (dump_file && (dump_flags & TDF_DETAILS))
+	    fprintf (dump_file, "  Called by %s that is executed once\n", cgraph_node_name (node));
+	  maybe_unlikely_executed = false;
+	  if (edge->loop_nest)
+	    {
+	      maybe_executed_once = false;
+	      if (dump_file && (dump_flags & TDF_DETAILS))
+	        fprintf (dump_file, "  Called in loop\n");
+	    }
+	  break;
+	case NODE_FREQUENCY_HOT:
+	case NODE_FREQUENCY_NORMAL:
+	  if (dump_file && (dump_flags & TDF_DETAILS))
+	    fprintf (dump_file, "  Called by %s that is normal or hot\n", cgraph_node_name (node));
+	  maybe_unlikely_executed = false;
+	  maybe_executed_once = false;
+	  break;
+	}
+    }
+   if (maybe_unlikely_executed)
+     {
+       node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
+       if (dump_file)
+         fprintf (dump_file, "Node %s promoted to unlikely executed.\n", cgraph_node_name (node));
+       return true;
+     }
+   if (maybe_executed_once && node->frequency != NODE_FREQUENCY_EXECUTED_ONCE)
+     {
+       node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
+       if (dump_file)
+         fprintf (dump_file, "Node %s promoted to executed once.\n", cgraph_node_name (node));
+       return true;
+     }
+   return false;
+}
+
 #include "gt-cgraph.h"
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 9b9bf4d42d71..c208cfaeb636 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -557,6 +557,7 @@ struct cgraph_2node_hook_list *cgraph_add_node_duplication_hook (cgraph_2node_ho
 void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
 void cgraph_materialize_all_clones (void);
 gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
+bool cgraph_propagate_frequency (struct cgraph_node *node);
 /* In cgraphbuild.c  */
 unsigned int rebuild_cgraph_edges (void);
 void reset_inline_failed (struct cgraph_node *);
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index fbd695d129ca..381942a55864 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -285,6 +285,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
       + inline_summary (e->callee)->estimated_self_stack_size;
   if (e->callee->global.inlined_to->global.estimated_stack_size < peak)
     e->callee->global.inlined_to->global.estimated_stack_size = peak;
+  cgraph_propagate_frequency (e->callee);
 
   /* Recursively clone all bodies.  */
   for (e = e->callee->callees; e; e = e->next_callee)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e3b7527bec82..72e61c0e348f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-27  Jan Hubicka  <jh@suse.cz>
+
+	* gcc.dg/ipa/iinline-1.c (main): Rename to...
+	(test): ... this one.
+
 2010-04-27  Bernd Schmidt  <bernds@codesourcery.com>
 
 	PR target/40657
diff --git a/gcc/testsuite/gcc.dg/ipa/iinline-1.c b/gcc/testsuite/gcc.dg/ipa/iinline-1.c
index 9f0ad68e9faa..617c484994b4 100644
--- a/gcc/testsuite/gcc.dg/ipa/iinline-1.c
+++ b/gcc/testsuite/gcc.dg/ipa/iinline-1.c
@@ -16,11 +16,11 @@ static void hiphip (void (*f)())
   f ();
 }
 
-int main (int argc, int *argv[])
+int test (void)
 {
   hiphip (hooray);
   return 0;
 }
 
-/* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in main"  "inline"  } } */
+/* { dg-final { scan-ipa-dump "hooray\[^\\n\]*inline copy in test"  "inline"  } } */
 /* { dg-final { cleanup-ipa-dump "inline" } } */
-- 
GitLab