From cb88692574ca59ec688fc3543578557dbfb7df23 Mon Sep 17 00:00:00 2001
From: hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Thu, 21 Aug 2008 12:39:35 +0000
Subject: 	Backport from LTO branch:

	2008-05-05  Kenneth Zadeck <zadeck@naturalbridge.com>
		    Jan Hubicka  <jh@suse.cz>

	* ipa-pure-const.c
	(init_state, finish_state, set_function_state, generate_summary):
	New functions.
	(scan_stmt): Renamed from scan_function.  Changed to keep state in
	local static vars rather than cgraph aux field.
	(propagate): Renamed from static_execute. Changed to keep state in
	local static vars rather than cgraph aux field.
	(pass_ipa_pure_const): Changed from SIMPLE_IPA_PASS to IPA_PASS.
	* tree-pass.h (pass_ipa_pure_const): Turn into IPA_PASS.

	2008-07-15  Kenneth Zadeck <zadeck@naturalbridge.com>

	* tree-pass.h (pass_ipa_reference): Make into ipa_opt_pass.
	* ipa-reference.c (init_function_info, generate_summary,
	propagate): New functions.
	(analyze_function):  Call init_function_info.
	(static_execute): Stripped into generate_summary and propagate.
	(pass_ipa_reference): Made into ipa_opt_pass.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139378 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ipa-reference.c | 304 ++++++++++++++++++++++++++++------------------------
 1 file changed, 166 insertions(+), 138 deletions(-)

(limited to 'gcc/ipa-reference.c')

diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index c28c7327f2c..08bed82ec90 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -1,5 +1,5 @@
 /* Callgraph based analysis of static variables.
-   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
 
 This file is part of GCC.
@@ -642,7 +642,8 @@ propagate_bits (struct cgraph_node *x)
 	{
 	  if (get_reference_vars_info_from_cgraph (y))
 	    {
-	      ipa_reference_vars_info_t y_info = get_reference_vars_info_from_cgraph (y);
+	      ipa_reference_vars_info_t y_info 
+		= get_reference_vars_info_from_cgraph (y);
 	      ipa_reference_global_vars_info_t y_global = y_info->global;
 	      
 	      if (x_global->statics_read
@@ -798,63 +799,71 @@ analyze_variable (struct varpool_node *vnode)
              &wi, wi.pset);
 }
 
-/* This is the main routine for finding the reference patterns for
-   global variables within a function FN.  */
+/* Set up the persistent info for FN.  */
 
-static void
-analyze_function (struct cgraph_node *fn)
+static ipa_reference_local_vars_info_t
+init_function_info (struct cgraph_node *fn)
 {
   ipa_reference_vars_info_t info 
     = XCNEW (struct ipa_reference_vars_info_d);
   ipa_reference_local_vars_info_t l
     = XCNEW (struct ipa_reference_local_vars_info_d);
   tree decl = fn->decl;
-  struct walk_stmt_info wi;
 
   /* Add the info to the tree's annotation.  */
-  get_function_ann (fn->decl)->reference_vars_info = info;
+  get_function_ann (decl)->reference_vars_info = info;
 
   info->local = l;
   l->statics_read = BITMAP_ALLOC (&ipa_obstack);
   l->statics_written = BITMAP_ALLOC (&ipa_obstack);
 
+  return l;
+}
+
+/* This is the main routine for finding the reference patterns for
+   global variables within a function FN.  */
+  
+static void
+analyze_function (struct cgraph_node *fn)
+{
+  ipa_reference_local_vars_info_t l = init_function_info (fn);
+  tree decl = fn->decl;
+  struct walk_stmt_info wi;
+  struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
+  basic_block this_block;
+
   if (dump_file)
     fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
   
-  {
-    struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
-    basic_block this_block;
-
-    FOR_EACH_BB_FN (this_block, this_cfun)
-      {
-	gimple_stmt_iterator gsi;
-	gimple phi;
-	tree op;
-	use_operand_p use;
-	ssa_op_iter iter;
-
-	/* Find the addresses taken in phi node arguments.  */
-	for (gsi = gsi_start_phis (this_block);
-	     !gsi_end_p (gsi);
-	     gsi_next (&gsi))
-	  {
-	    phi = gsi_stmt (gsi);
-	    FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
-	      {
-		op = USE_FROM_PTR (use);
-		if (TREE_CODE (op) == ADDR_EXPR)
-		  check_rhs_var (l, op);
-	      }
-	  }
+  FOR_EACH_BB_FN (this_block, this_cfun)
+    {
+      gimple_stmt_iterator gsi;
+      gimple phi;
+      tree op;
+      use_operand_p use;
+      ssa_op_iter iter;
+
+      /* Find the addresses taken in phi node arguments.  */
+      for (gsi = gsi_start_phis (this_block);
+	   !gsi_end_p (gsi);
+	   gsi_next (&gsi))
+	{
+	  phi = gsi_stmt (gsi);
+	  FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
+	    {
+	      op = USE_FROM_PTR (use);
+	      if (TREE_CODE (op) == ADDR_EXPR)
+		check_rhs_var (l, op);
+	    }
+	}
 
-	memset (&wi, 0, sizeof (wi));
-	wi.info = fn;
-	wi.pset = visited_nodes;
-	for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
-	  walk_gimple_stmt (&gsi, scan_stmt_for_static_refs,
-			    scan_op_for_static_refs, &wi);
-      }
-  }
+      memset (&wi, 0, sizeof (wi));
+      wi.info = fn;
+      wi.pset = visited_nodes;
+      for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
+	walk_gimple_stmt (&gsi, scan_stmt_for_static_refs,
+			  scan_op_for_static_refs, &wi);
+    }
 
   /* There may be const decls with interesting right hand sides.  */
   if (DECL_STRUCT_FUNCTION (decl))
@@ -921,29 +930,28 @@ clean_function (struct cgraph_node *fn)
 	BITMAP_FREE (g->statics_not_written);
       free (g);
     }
-
   
   free (get_function_ann (fn->decl)->reference_vars_info);
   get_function_ann (fn->decl)->reference_vars_info = NULL;
 }
 
-
-/* Produce the global information by preforming a transitive closure
-   on the local information that was produced by ipa_analyze_function
-   and ipa_analyze_variable.  */
 
-static unsigned int
-static_execute (void)
+/* Analyze each function in the cgraph to see which global or statics
+   are read or written.  */
+
+static void 
+generate_summary (void)
 {
   struct cgraph_node *node;
   struct varpool_node *vnode;
-  struct cgraph_node *w;
-  struct cgraph_node **order =
-    XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
-  int order_pos = ipa_utils_reduced_inorder (order, false, true);
-  int i;
-
+  unsigned int index;
+  bitmap_iterator bi;
+  bitmap module_statics_readonly;
+  bitmap bm_temp;
+  
   ipa_init ();
+  module_statics_readonly = BITMAP_ALLOC (&ipa_obstack);
+  bm_temp = BITMAP_ALLOC (&ipa_obstack);
 
   /* Process all of the variables first.  */
   FOR_EACH_STATIC_INITIALIZER (vnode)
@@ -969,105 +977,101 @@ static_execute (void)
 
   pointer_set_destroy (visited_nodes);
   visited_nodes = NULL;
-  if (dump_file) 
-    dump_cgraph (dump_file);
 
   /* Prune out the variables that were found to behave badly
      (i.e. have their address taken).  */
-  {
-    unsigned int index;
-    bitmap_iterator bi;
-    bitmap module_statics_readonly = BITMAP_ALLOC (&ipa_obstack);
-    bitmap bm_temp = BITMAP_ALLOC (&ipa_obstack);
-
-    EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
-      {
-	splay_tree_remove (reference_vars_to_consider, index);
-      }
-
-    bitmap_and_compl_into (all_module_statics, 
-			   module_statics_escape);
-
-    bitmap_and_compl (module_statics_readonly, all_module_statics,
-		      module_statics_written);
-
-    /* If the address is not taken, we can unset the addressable bit
-       on this variable.  */
+  EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
+    {
+      splay_tree_remove (reference_vars_to_consider, index);
+    }
+  
+  bitmap_and_compl_into (all_module_statics, 
+			 module_statics_escape);
+  
+  bitmap_and_compl (module_statics_readonly, all_module_statics,
+		    module_statics_written);
+  
+  /* If the address is not taken, we can unset the addressable bit
+     on this variable.  */
+  EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
+    {
+      tree var = get_static_decl (index);
+      TREE_ADDRESSABLE (var) = 0;
+      if (dump_file) 
+	fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
+		 get_static_name (index));
+    }
+  
+  /* If the variable is never written, we can set the TREE_READONLY
+     flag.  Additionally if it has a DECL_INITIAL that is made up of
+     constants we can treat the entire global as a constant.  */
+  
+  bitmap_and_compl (module_statics_readonly, all_module_statics,
+		    module_statics_written);
+  EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
+    {
+      tree var = get_static_decl (index);
+      
+      /* Readonly on a function decl is very different from the
+	 variable.  */
+      if (TREE_CODE (var) == FUNCTION_DECL)
+	continue;
+      
+      /* Ignore variables in named sections - changing TREE_READONLY
+	 changes the section flags, potentially causing conflicts with
+	 other variables in the same named section.  */
+      if (DECL_SECTION_NAME (var) == NULL_TREE)
+	{
+	  TREE_READONLY (var) = 1;
+	  if (dump_file)
+	    fprintf (dump_file, "read-only var %s\n", 
+		     get_static_name (index));
+	}
+    }
+  
+  BITMAP_FREE(module_statics_escape);
+  BITMAP_FREE(module_statics_written);
+  
+  if (dump_file)
     EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
       {
-	tree var = get_static_decl (index);
- 	TREE_ADDRESSABLE (var) = 0;
-	if (dump_file) 
-	  fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
-		   get_static_name (index));
+	fprintf (dump_file, "\nPromotable global:%s",
+		 get_static_name (index));
       }
-
-    /* If the variable is never written, we can set the TREE_READONLY
-       flag.  Additionally if it has a DECL_INITIAL that is made up of
-       constants we can treat the entire global as a constant.  */
-
-    bitmap_and_compl (module_statics_readonly, all_module_statics,
-		      module_statics_written);
-    EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
-      {
-	tree var = get_static_decl (index);
-
-	/* Readonly on a function decl is very different from the
-	   variable.  */
-	if (TREE_CODE (var) == FUNCTION_DECL)
-	  continue;
-
-	/* Ignore variables in named sections - changing TREE_READONLY
-	   changes the section flags, potentially causing conflicts with
-	   other variables in the same named section.  */
-	if (DECL_SECTION_NAME (var) == NULL_TREE)
-	  {
-	    TREE_READONLY (var) = 1;
-	    if (dump_file)
-	      fprintf (dump_file, "read-only var %s\n", 
-		       get_static_name (index));
-	  }
-      }
-
-    BITMAP_FREE(module_statics_escape);
-    BITMAP_FREE(module_statics_written);
-
-    if (dump_file)
-      EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
-	{
-	  fprintf (dump_file, "\nPromotable global:%s",
-		   get_static_name (index));
-	}
-
-    for (i = 0; i < order_pos; i++ )
+  
+  for (node = cgraph_nodes; node; node = node->next)
+    if (node->analyzed 
+	&& (cgraph_is_master_clone (node)
+	    || (cgraph_function_body_availability (node) 
+		== AVAIL_OVERWRITABLE)))
       {
 	ipa_reference_local_vars_info_t l;
-	node = order[i];
 	l = get_reference_vars_info_from_cgraph (node)->local;
-
+	
 	/* Any variables that are not in all_module_statics are
 	   removed from the local maps.  This will include all of the
 	   variables that were found to escape in the function
 	   scanning.  */
 	bitmap_and_into (l->statics_read, 
-		         all_module_statics);
+			 all_module_statics);
 	bitmap_and_into (l->statics_written, 
-		         all_module_statics);
+			 all_module_statics);
       }
-
-    BITMAP_FREE(module_statics_readonly);
-    BITMAP_FREE(bm_temp);
-  }
-
+  
+  BITMAP_FREE(module_statics_readonly);
+  BITMAP_FREE(bm_temp);
+  
   if (dump_file)
-    {
-      for (i = 0; i < order_pos; i++ )
+    for (node = cgraph_nodes; node; node = node->next)
+      if (node->analyzed 
+	  && (cgraph_is_master_clone (node)
+	      || (cgraph_function_body_availability (node) 
+		  == AVAIL_OVERWRITABLE)))
 	{
-	  unsigned int index;
 	  ipa_reference_local_vars_info_t l;
+	  unsigned int index;
 	  bitmap_iterator bi;
-
-	  node = order[i];
+	  
 	  l = get_reference_vars_info_from_cgraph (node)->local;
 	  fprintf (dump_file, 
 		   "\nFunction name:%s/%i:", 
@@ -1087,7 +1091,24 @@ static_execute (void)
 		      get_static_name (index));
 	    }
 	}
-    }
+}
+
+/* Produce the global information by preforming a transitive closure
+   on the local information that was produced by ipa_analyze_function
+   and ipa_analyze_variable.  */
+
+static unsigned int
+propagate (void)
+{
+  struct cgraph_node *node;
+  struct cgraph_node *w;
+  struct cgraph_node **order =
+    XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
+  int order_pos = ipa_utils_reduced_inorder (order, false, true);
+  int i;
+
+  if (dump_file) 
+    dump_cgraph (dump_file);
 
   /* Propagate the local information thru the call graph to produce
      the global information.  All the nodes within a cycle will have
@@ -1348,13 +1369,13 @@ gate_reference (void)
 	  && !(errorcount || sorrycount));
 }
 
-struct simple_ipa_opt_pass pass_ipa_reference =
+struct ipa_opt_pass pass_ipa_reference =
 {
  {
-  SIMPLE_IPA_PASS,
+  IPA_PASS,
   "static-var",				/* name */
   gate_reference,			/* gate */
-  static_execute,			/* execute */
+  propagate,			        /* execute */
   NULL,					/* sub */
   NULL,					/* next */
   0,					/* static_pass_number */
@@ -1364,7 +1385,14 @@ struct simple_ipa_opt_pass pass_ipa_reference =
   0,					/* properties_destroyed */
   0,					/* todo_flags_start */
   0                                     /* todo_flags_finish */
- }
+ },
+ generate_summary,		        /* generate_summary */
+ NULL,					/* write_summary */
+ NULL,					/* read_summary */
+ NULL,					/* function_read_summary */
+ 0,					/* TODOs */
+ NULL,			                /* function_transform */
+ NULL					/* variable_transform */
 };
 
 #include "gt-ipa-reference.h"
-- 
cgit v1.2.1