summaryrefslogtreecommitdiff
path: root/gcc/ipa-reference.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2008-08-21 12:39:35 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2008-08-21 12:39:35 +0000
commitcb88692574ca59ec688fc3543578557dbfb7df23 (patch)
tree1e0757ed3e2361b67a6c5193b290e905111f925c /gcc/ipa-reference.c
parent373055064d92fe02d97bdac0891fe76d748d2122 (diff)
downloadgcc-cb88692574ca59ec688fc3543578557dbfb7df23.tar.gz
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
Diffstat (limited to 'gcc/ipa-reference.c')
-rw-r--r--gcc/ipa-reference.c304
1 files changed, 166 insertions, 138 deletions
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"