diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-21 12:39:35 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-21 12:39:35 +0000 |
commit | cb88692574ca59ec688fc3543578557dbfb7df23 (patch) | |
tree | 1e0757ed3e2361b67a6c5193b290e905111f925c /gcc/ipa-reference.c | |
parent | 373055064d92fe02d97bdac0891fe76d748d2122 (diff) | |
download | gcc-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.c | 304 |
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" |