diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-22 11:40:18 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-22 11:40:18 +0000 |
commit | ef378c275d52d00d8ed044dc81ec9c48be2222e6 (patch) | |
tree | 0ab06e5072b8d0118d4bed1aa031422e8dd59204 /gcc/ipa-reference.c | |
parent | 8867b500961593ba73be72ea17bbbd4f8a2d74ef (diff) | |
download | gcc-ef378c275d52d00d8ed044dc81ec9c48be2222e6.tar.gz |
PR tree-optimize/40556
* ipa-reference.c (has_proper_scope_for_analysis): Add fixme about global vars.
(check_call): Handle only indirect calls.
(propagate_bits): Update comment.
(write_node_summary_p): Turn bogus check to assert.
(ipa_reference_write_summary): Stream calls_read_all properly.
(ipa_reference_read_summary): Stream in calls_read_all properly.
(read_write_all_from_decl): New function.
(propagate): Handle OVERWRITABLE nodes and external calls here.
* ipa-pre-const.c (check_call): In IPA mode handle indirect calls
only.
(analyze_function): Do not check visibility here.
(add_new_function): We summary OVERWRITABLE too.
(generate_summary): Stream OVERWRITABLE nodes too.
(propagate): Handle external calls and OVERWRITABLE nodes here.
(local_pure_const): Check visibility here.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153450 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-reference.c')
-rw-r--r-- | gcc/ipa-reference.c | 155 |
1 files changed, 101 insertions, 54 deletions
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 2e062e45eaa..f0e8aa0aaed 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -318,6 +318,8 @@ has_proper_scope_for_analysis (tree t) if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) return false; + /* FIXME: for LTO we should include PUBLIC vars too. This is bit difficult + as summarie would need unsharing. */ if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) return false; @@ -413,31 +415,21 @@ check_call (ipa_reference_local_vars_info_t local, gimple stmt) { int flags = gimple_call_flags (stmt); tree callee_t = gimple_call_fndecl (stmt); - enum availability avail = AVAIL_NOT_AVAILABLE; - if (callee_t) + /* Process indirect calls. All direct calles are handled at propagation + time. */ + if (!callee_t) { - struct cgraph_node* callee = cgraph_node(callee_t); - avail = cgraph_function_body_availability (callee); - } - - if (avail <= AVAIL_OVERWRITABLE) - if (local) - { - if (flags & ECF_CONST) - ; - else if (flags & ECF_PURE) + if (flags & ECF_CONST) + ; + else if (flags & ECF_PURE) + local->calls_read_all = true; + else + { local->calls_read_all = true; - else - { - local->calls_read_all = true; - local->calls_write_all = true; - } - } - /* TODO: To be able to produce sane results, we should also handle - common builtins, in particular throw. - Indirect calls hsould be only counted and as inliner is replacing them - by direct calls, we can conclude if any indirect calls are left in body */ + local->calls_write_all = true; + } + } } /* TP is the part of the tree currently under the microscope. @@ -527,7 +519,7 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x { struct cgraph_node *y = e->callee; - /* Only look at the master nodes and skip external nodes. */ + /* Only look into nodes we can propagate something. */ if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE) { if (get_reference_vars_info (y)) @@ -1012,8 +1004,8 @@ generate_summary (void) static bool write_node_summary_p (struct cgraph_node *node) { + gcc_assert (node->global.inlined_to == NULL); return (node->analyzed - && node->global.inlined_to == NULL && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE && get_reference_vars_info (node) != NULL); } @@ -1053,18 +1045,28 @@ ipa_reference_write_summary (cgraph_node_set set) lto_output_uleb128_stream (ob->main_stream, node_ref); /* Stream out the statics read. */ - lto_output_uleb128_stream (ob->main_stream, - bitmap_count_bits (l->statics_read)); - EXECUTE_IF_SET_IN_BITMAP (l->statics_read, 0, index, bi) - lto_output_var_decl_index(ob->decl_state, ob->main_stream, - get_static_decl (index)); + if (l->calls_read_all) + lto_output_sleb128_stream (ob->main_stream, -1); + else + { + lto_output_sleb128_stream (ob->main_stream, + bitmap_count_bits (l->statics_read)); + EXECUTE_IF_SET_IN_BITMAP (l->statics_read, 0, index, bi) + lto_output_var_decl_index(ob->decl_state, ob->main_stream, + get_static_decl (index)); + } /* Stream out the statics written. */ - lto_output_uleb128_stream (ob->main_stream, - bitmap_count_bits (l->statics_written)); - EXECUTE_IF_SET_IN_BITMAP (l->statics_written, 0, index, bi) - lto_output_var_decl_index(ob->decl_state, ob->main_stream, - get_static_decl (index)); + if (l->calls_write_all) + lto_output_sleb128_stream (ob->main_stream, -1); + else + { + lto_output_sleb128_stream (ob->main_stream, + bitmap_count_bits (l->statics_written)); + EXECUTE_IF_SET_IN_BITMAP (l->statics_written, 0, index, bi) + lto_output_var_decl_index(ob->decl_state, ob->main_stream, + get_static_decl (index)); + } } } lto_destroy_simple_output_block (ob); @@ -1101,7 +1103,7 @@ ipa_reference_read_summary (void) unsigned int j, index; struct cgraph_node *node; ipa_reference_local_vars_info_t l; - unsigned int v_count; + int v_count; lto_cgraph_encoder_t encoder; index = lto_input_uleb128 (ib); @@ -1110,26 +1112,32 @@ ipa_reference_read_summary (void) l = init_function_info (node); /* Set the statics read. */ - v_count = lto_input_uleb128 (ib); - for (j = 0; j < v_count; j++) - { - unsigned int var_index = lto_input_uleb128 (ib); - tree v_decl = lto_file_decl_data_get_var_decl (file_data, - var_index); - add_static_var (v_decl); - bitmap_set_bit (l->statics_read, DECL_UID (v_decl)); - } + v_count = lto_input_sleb128 (ib); + if (v_count == -1) + l->calls_read_all = true; + else + for (j = 0; j < (unsigned int)v_count; j++) + { + unsigned int var_index = lto_input_uleb128 (ib); + tree v_decl = lto_file_decl_data_get_var_decl (file_data, + var_index); + add_static_var (v_decl); + bitmap_set_bit (l->statics_read, DECL_UID (v_decl)); + } /* Set the statics written. */ - v_count = lto_input_uleb128 (ib); - for (j = 0; j < v_count; j++) - { - unsigned int var_index = lto_input_uleb128 (ib); - tree v_decl = lto_file_decl_data_get_var_decl (file_data, - var_index); - add_static_var (v_decl); - bitmap_set_bit (l->statics_written, DECL_UID (v_decl)); - } + v_count = lto_input_sleb128 (ib); + if (v_count == -1) + l->calls_read_all = true; + else + for (j = 0; j < (unsigned int)v_count; j++) + { + unsigned int var_index = lto_input_uleb128 (ib); + tree v_decl = lto_file_decl_data_get_var_decl (file_data, + var_index); + add_static_var (v_decl); + bitmap_set_bit (l->statics_written, DECL_UID (v_decl)); + } } lto_destroy_simple_input_block (file_data, @@ -1141,6 +1149,26 @@ ipa_reference_read_summary (void) +/* Set READ_ALL/WRITE_ALL based on DECL flags. */ +static void +read_write_all_from_decl (tree decl, bool * read_all, bool * write_all) +{ + int flags = flags_from_decl_or_type (decl); + if (flags & ECF_CONST) + ; + else if (flags & ECF_PURE) + *read_all = true; + else + { + /* TODO: To be able to produce sane results, we should also handle + common builtins, in particular throw. + Indirect calls hsould be only counted and as inliner is replacing them + by direct calls, we can conclude if any indirect calls are left in body */ + *read_all = true; + *write_all = true; + } +} + /* Produce the global information by preforming a transitive closure on the local information that was produced by ipa_analyze_function and ipa_analyze_variable. */ @@ -1173,6 +1201,7 @@ propagate (void) ipa_reference_global_vars_info_t node_g = XCNEW (struct ipa_reference_global_vars_info_d); ipa_reference_local_vars_info_t node_l; + struct cgraph_edge *e; bool read_all; bool write_all; @@ -1193,6 +1222,15 @@ propagate (void) read_all = node_l->calls_read_all; write_all = node_l->calls_write_all; + /* When function is overwrittable, we can not assume anything. */ + if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) + read_write_all_from_decl (node->decl, &read_all, &write_all); + + for (e = node->callees; e; e = e->next_callee) + if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) + read_write_all_from_decl (e->callee->decl, &read_all, &write_all); + + /* If any node in a cycle is calls_read_all or calls_write_all they all are. */ w_info = (struct ipa_dfs_info *) node->aux; @@ -1201,6 +1239,15 @@ propagate (void) { ipa_reference_local_vars_info_t w_l = get_reference_vars_info (w)->local; + + /* When function is overwrittable, we can not assume anything. */ + if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE) + read_write_all_from_decl (w->decl, &read_all, &write_all); + + for (e = w->callees; e; e = e->next_callee) + if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE) + read_write_all_from_decl (e->callee->decl, &read_all, &write_all); + read_all |= w_l->calls_read_all; write_all |= w_l->calls_write_all; @@ -1208,6 +1255,7 @@ propagate (void) w = w_info->next_cycle; } + /* Initialized the bitmaps for the reduced nodes */ if (read_all) node_g->statics_read = all_module_statics; @@ -1217,7 +1265,6 @@ propagate (void) bitmap_copy (node_g->statics_read, node_l->statics_read); } - if (write_all) node_g->statics_written = all_module_statics; else |