diff options
author | Jan Hubicka <jh@suse.cz> | 2010-04-29 09:10:38 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2010-04-29 07:10:38 +0000 |
commit | 2942c502ee147819b7e57dca78f7a2cf4831279f (patch) | |
tree | 517f6bc2231e5c3e319637f9c9277e4cc2e99ffb /gcc/lto | |
parent | 74ca33936f5a1c543a71033f32d59b8d2e0957a4 (diff) | |
download | gcc-2942c502ee147819b7e57dca78f7a2cf4831279f.zip gcc-2942c502ee147819b7e57dca78f7a2cf4831279f.tar.gz gcc-2942c502ee147819b7e57dca78f7a2cf4831279f.tar.bz2 |
* lto-symtab.c (lto_symtab_entry_def) Add vnode.
(lto_varpool_replace_node): New.
(lto_symtab_resolve_symbols): Resolve varpool nodes.
(lto_symtab_merge_decls_1): Prefer decls with varpool node.
(lto_symtab_merge_cgraph_nodes_1): Merge varpools.
* cgraph.h (varpool_node_ptr): New type.
(varpool_node_ptr): New vector.
(varpool_node_set_def): New structure.
(varpool_node_set): New type.
(varpool_node_set): New vector.
(varpool_node_set_element_def): New structure.
(varpool_node_set_element, const_varpool_node_set_element): New types.
(varpool_node_set_iterator): New type.
(varpool_node): Add prev pointers, add used_from_other_partition,
in_other_partition.
(varpool_node_set_new, varpool_node_set_find, varpool_node_set_add,
varpool_node_set_remove, dump_varpool_node_set, debug_varpool_node_set,
varpool_get_node, varpool_remove_node): Declare.
(vsi_end_p, vsi_next, vsi_node, vsi_start, varpool_node_in_set_p,
varpool_node_set_size): New inlines.
* cgraph.c (dump_cgraph_node): Dump asm names of aliases.
* tree-pass.h (varpool_node_set_def): Forward declare.
(ipa_opt_pass_d): Summary writting takes vnode sets too.
(ipa_write_optimization_summaries): Update prototype.
* ipa-cp.c (ipcp_write_summary): Update.
* ipa-reference.c (ipa_reference_write_summary): Update.
* lto-cgraph.c (lto_output_varpool_node): New static function.
(output_varpool): New function.
(input_varpool_node): New static function.
(input_varpool_1): New function.
(input_cgraph): Input varpool.
* ipa-pure-const.c (pure_const_write_summary): Update.
* lto-streamer-out.c (lto_output): Update, output varpool too.
(write_global_stream): Kill WPA hack.
(produce_asm_for_decls): Update.
(output_alias_pair_p): Handle variables.
(output_unreferenced_globals): Output only needed partition of varpool.
* ipa-inline.c (inline_write_summary): Update.
* lto-streamer-in.c (lto_input_tree_ref, lto_input_tree): Do not build cgraph.
* lto-section-in.c (lto_section_name): Add varpool and jump funcs.
* ipa.c (hash_varpool_node_set_element, eq_varpool_node_set_element,
varpool_node_set_new, varpool_node_set_add,
varpool_node_set_remove, varpool_node_set_find, dump_varpool_node_set,
debug_varpool_node_set): New functions.
* passes.c (rest_of_decl_compilation): when in LTO do not finalize.
(execute_one_pass): Process new decls too.
(ipa_write_summaries_2): Pass around vsets.
(ipa_write_summaries_1): Likewise.
(ipa_write_summaries): Build vset; be more selective about cgraph nodes
to add.
(ipa_write_optimization_summaries_1): Pass around vsets.
(ipa_write_optimization_summaries): Likewise.
* varpool.c (varpool_get_node): New.
(varpool_node): Update doubly linked lists.
(varpool_remove_node): New.
(dump_varpool_node): More dumping.
(varpool_enqueue_needed_node): Update doubly linked lists.
(decide_is_variable_needed): Kill ltrans hack.
(varpool_finalize_decl): Kill lto hack.
(varpool_assemble_decl): Skip decls in other partitions.
(varpool_assemble_pending_decls): Update doubly linkes lists.
(varpool_empty_needed_queue): Likewise.
(varpool_extra_name_alias): Likewise.
* lto-streamer.c (lto_get_section_name): Add vars section.
* lto-streamer.h (lto_section_type): Update.
(output_varpool, input_varpool): Declare.
* lto.c (lto_varpool_node_sets): New.
(lto_1_to_1_map): Partition varpool too.
(globalize_context_t, globalize_cross_file_statics,
lto_scan_statics_in_ref_table, lto_scan_statics_in_cgraph_node,
lto_scan_statics_in_remaining_global_vars): Remove.
(lto_promote_cross_file_statics): Rewrite.
(get_filename_for_set): Take vset argument.
(lto_wpa_write_files): Pass around vsets.
From-SVN: r158854
Diffstat (limited to 'gcc/lto')
-rw-r--r-- | gcc/lto/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/lto/lto.c | 290 |
2 files changed, 102 insertions, 199 deletions
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index b757655..5bf7a29 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,14 @@ +2010-04-28 Jan Hubicka <jh@suse.cz> + + * lto.c (lto_varpool_node_sets): New. + (lto_1_to_1_map): Partition varpool too. + (globalize_context_t, globalize_cross_file_statics, + lto_scan_statics_in_ref_table, lto_scan_statics_in_cgraph_node, + lto_scan_statics_in_remaining_global_vars): Remove. + (lto_promote_cross_file_statics): Rewrite. + (get_filename_for_set): Take vset argument. + (lto_wpa_write_files): Pass around vsets. + 2010-04-27 Dave Korn <dave.korn.cygwin@gmail.com> PR lto/42776 diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 9002686..7aa1f3e 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -523,6 +523,7 @@ free_section_data (struct lto_file_decl_data *file_data ATTRIBUTE_UNUSED, /* Vector of all cgraph node sets. */ static GTY (()) VEC(cgraph_node_set, gc) *lto_cgraph_node_sets; +static GTY (()) VEC(varpool_node_set, gc) *lto_varpool_node_sets; /* Group cgrah nodes by input files. This is used mainly for testing @@ -532,25 +533,21 @@ static void lto_1_to_1_map (void) { struct cgraph_node *node; + struct varpool_node *vnode; struct lto_file_decl_data *file_data; struct pointer_map_t *pmap; + struct pointer_map_t *vpmap; cgraph_node_set set; + varpool_node_set vset; void **slot; timevar_push (TV_WHOPR_WPA); lto_cgraph_node_sets = VEC_alloc (cgraph_node_set, gc, 1); - - /* If the cgraph is empty, create one cgraph node set so that there is still - an output file for any variables that need to be exported in a DSO. */ - if (!cgraph_nodes) - { - set = cgraph_node_set_new (); - VEC_safe_push (cgraph_node_set, gc, lto_cgraph_node_sets, set); - goto finish; - } + lto_varpool_node_sets = VEC_alloc (varpool_node_set, gc, 1); pmap = pointer_map_create (); + vpmap = pointer_map_create (); for (node = cgraph_nodes; node; node = node->next) { @@ -558,6 +555,9 @@ lto_1_to_1_map (void) cloned from. */ if (node->global.inlined_to || node->clone_of) continue; + /* Nodes without a body do not need partitioning. */ + if (!node->analyzed || node->same_body_alias) + continue; /* We only need to partition the nodes that we read from the gimple bytecode files. */ file_data = node->local.lto_file_data; @@ -573,14 +573,50 @@ lto_1_to_1_map (void) slot = pointer_map_insert (pmap, file_data); *slot = set; VEC_safe_push (cgraph_node_set, gc, lto_cgraph_node_sets, set); + vset = varpool_node_set_new (); + slot = pointer_map_insert (vpmap, file_data); + *slot = vset; + VEC_safe_push (varpool_node_set, gc, lto_varpool_node_sets, vset); } cgraph_node_set_add (set, node); } + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + { + if (vnode->alias) + continue; + slot = pointer_map_contains (vpmap, file_data); + if (slot) + vset = (varpool_node_set) *slot; + else + { + set = cgraph_node_set_new (); + slot = pointer_map_insert (pmap, file_data); + *slot = set; + VEC_safe_push (cgraph_node_set, gc, lto_cgraph_node_sets, set); + vset = varpool_node_set_new (); + slot = pointer_map_insert (vpmap, file_data); + *slot = vset; + VEC_safe_push (varpool_node_set, gc, lto_varpool_node_sets, vset); + } + + varpool_node_set_add (vset, vnode); + } + + /* If the cgraph is empty, create one cgraph node set so that there is still + an output file for any variables that need to be exported in a DSO. */ + if (!lto_cgraph_node_sets) + { + set = cgraph_node_set_new (); + VEC_safe_push (cgraph_node_set, gc, lto_cgraph_node_sets, set); + vset = varpool_node_set_new (); + VEC_safe_push (varpool_node_set, gc, lto_varpool_node_sets, vset); + } + pointer_map_destroy (pmap); + pointer_map_destroy (vpmap); -finish: timevar_pop (TV_WHOPR_WPA); lto_stats.num_cgraph_partitions += VEC_length (cgraph_node_set, @@ -672,174 +708,6 @@ lto_add_all_inlinees (cgraph_node_set set) lto_bitmap_free (original_decls); } -/* Owing to inlining, we may need to promote a file-scope variable - to a global variable. Consider this case: - - a.c: - static int var; - - void - foo (void) - { - var++; - } - - b.c: - - extern void foo (void); - - void - bar (void) - { - foo (); - } - - If WPA inlines FOO inside BAR, then the static variable VAR needs to - be promoted to global because BAR and VAR may be in different LTRANS - files. */ - -/* This struct keeps track of states used in globalization. */ - -typedef struct -{ - /* Current cgraph node set. */ - cgraph_node_set set; - - /* Function DECLs of cgraph nodes seen. */ - bitmap seen_node_decls; - - /* Use in walk_tree to avoid multiple visits of a node. */ - struct pointer_set_t *visited; - - /* static vars in this set. */ - bitmap static_vars_in_set; - - /* static vars in all previous set. */ - bitmap all_static_vars; - - /* all vars in all previous set. */ - bitmap all_vars; -} globalize_context_t; - -/* Callback for walk_tree. Examine the tree pointer to by TP and see if - if its a file-scope static variable of function that need to be turned - into a global. */ - -static tree -globalize_cross_file_statics (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - globalize_context_t *context = (globalize_context_t *) data; - tree t = *tp; - - if (t == NULL_TREE) - return NULL; - - /* The logic for globalization of VAR_DECLs and FUNCTION_DECLs are - different. For functions, we can simply look at the cgraph node sets - to tell if there are references to static functions outside the set. - The cgraph node sets do not keep track of vars, we need to traverse - the trees to determine what vars need to be globalized. */ - if (TREE_CODE (t) == VAR_DECL) - { - if (!TREE_PUBLIC (t)) - { - /* This file-scope static variable is reachable from more - that one set. Make it global but with hidden visibility - so that we do not export it in dynamic linking. */ - if (bitmap_bit_p (context->all_static_vars, DECL_UID (t))) - { - TREE_PUBLIC (t) = 1; - DECL_VISIBILITY (t) = VISIBILITY_HIDDEN; - } - bitmap_set_bit (context->static_vars_in_set, DECL_UID (t)); - } - bitmap_set_bit (context->all_vars, DECL_UID (t)); - walk_tree (&DECL_INITIAL (t), globalize_cross_file_statics, context, - context->visited); - } - else if (TREE_CODE (t) == FUNCTION_DECL && !TREE_PUBLIC (t)) - { - if (!cgraph_node_in_set_p (cgraph_node (t), context->set) - || cgraph_node (t)->address_taken) - { - /* This file-scope static function is reachable from a set - which does not contain the function DECL. Make it global - but with hidden visibility. */ - TREE_PUBLIC (t) = 1; - DECL_VISIBILITY (t) = VISIBILITY_HIDDEN; - } - } - - return NULL; -} - -/* Helper of lto_scan_statics_in_cgraph_node below. Scan TABLE for - static decls that may be used in more than one LTRANS file. - CONTEXT is a globalize_context_t for storing scanning states. */ - -static void -lto_scan_statics_in_ref_table (struct lto_tree_ref_table *table, - globalize_context_t *context) -{ - unsigned i; - - for (i = 0; i < table->size; i++) - walk_tree (&table->trees[i], globalize_cross_file_statics, context, - context->visited); -} - -/* Promote file-scope decl reachable from NODE if necessary to global. - CONTEXT is a globalize_context_t storing scanning states. */ - -static void -lto_scan_statics_in_cgraph_node (struct cgraph_node *node, - globalize_context_t *context) -{ - struct lto_in_decl_state *state; - - /* Do nothing if NODE has no function body. */ - if (!node->analyzed) - return; - - /* Return if the DECL of nodes has been visited before. */ - if (bitmap_bit_p (context->seen_node_decls, DECL_UID (node->decl))) - return; - - bitmap_set_bit (context->seen_node_decls, DECL_UID (node->decl)); - - state = lto_get_function_in_decl_state (node->local.lto_file_data, - node->decl); - gcc_assert (state); - - lto_scan_statics_in_ref_table (&state->streams[LTO_DECL_STREAM_VAR_DECL], - context); - lto_scan_statics_in_ref_table (&state->streams[LTO_DECL_STREAM_FN_DECL], - context); -} - -/* Scan all global variables that we have not yet seen so far. CONTEXT - is a globalize_context_t storing scanning states. */ - -static void -lto_scan_statics_in_remaining_global_vars (globalize_context_t *context) -{ - tree var, var_context; - struct varpool_node *vnode; - - FOR_EACH_STATIC_VARIABLE (vnode) - { - var = vnode->decl; - var_context = DECL_CONTEXT (var); - if (TREE_STATIC (var) - && TREE_PUBLIC (var) - && (!var_context || TREE_CODE (var_context) != FUNCTION_DECL) - && !bitmap_bit_p (context->all_vars, DECL_UID (var))) - walk_tree (&var, globalize_cross_file_statics, context, - context->visited); - } -} - /* Find out all static decls that need to be promoted to global because of cross file sharing. This function must be run in the WPA mode after all inlinees are added. */ @@ -847,39 +715,61 @@ lto_scan_statics_in_remaining_global_vars (globalize_context_t *context) static void lto_promote_cross_file_statics (void) { + struct varpool_node *vnode; unsigned i, n_sets; cgraph_node_set set; cgraph_node_set_iterator csi; - globalize_context_t context; - memset (&context, 0, sizeof (context)); - context.all_vars = lto_bitmap_alloc (); - context.all_static_vars = lto_bitmap_alloc (); + gcc_assert (flag_wpa); + /* At moment we make no attempt to figure out who is refering the variables, + so all must become global. */ + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + if (!vnode->externally_visible && vnode->analyzed) + { + TREE_PUBLIC (vnode->decl) = 1; + DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN; + } n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets); for (i = 0; i < n_sets; i++) { set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i); - context.set = set; - context.visited = pointer_set_create (); - context.static_vars_in_set = lto_bitmap_alloc (); - context.seen_node_decls = lto_bitmap_alloc (); + /* If node has either address taken (and we have no clue from where) + or it is called from other partition, it needs to be globalized. */ for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) - lto_scan_statics_in_cgraph_node (csi_node (csi), &context); - - if (i == n_sets - 1) - lto_scan_statics_in_remaining_global_vars (&context); - - bitmap_ior_into (context.all_static_vars, context.static_vars_in_set); + { + struct cgraph_node *node = csi_node (csi); + bool globalize = node->address_taken || node->local.vtable_method; + struct cgraph_edge *e; + if (node->local.externally_visible) + continue; + for (e = node->callers; e && !globalize; e = e->next_caller) + { + struct cgraph_node *caller = e->caller; + if (caller->global.inlined_to) + caller = caller->global.inlined_to; + if (!cgraph_node_in_set_p (caller, set)) + globalize = true; + } + if (globalize) + { + TREE_PUBLIC (node->decl) = 1; + DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; + if (node->same_body) + { + struct cgraph_node *alias; + for (alias = node->same_body; + alias; alias = alias->next) + { + TREE_PUBLIC (alias->decl) = 1; + DECL_VISIBILITY (alias->decl) = VISIBILITY_HIDDEN; + } + } + } + } - pointer_set_destroy (context.visited); - lto_bitmap_free (context.static_vars_in_set); - lto_bitmap_free (context.seen_node_decls); } - - lto_bitmap_free (context.all_vars); - lto_bitmap_free (context.all_static_vars); } @@ -999,6 +889,7 @@ lto_wpa_write_files (void) unsigned i, n_sets, last_out_file_ix, num_out_files; lto_file *file; cgraph_node_set set; + varpool_node_set vset; timevar_push (TV_WHOPR_WPA); @@ -1034,6 +925,7 @@ lto_wpa_write_files (void) char *temp_filename; set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i); + vset = VEC_index (varpool_node_set, lto_varpool_node_sets, i); temp_filename = get_filename_for_set (set); output_files[i] = temp_filename; @@ -1046,7 +938,7 @@ lto_wpa_write_files (void) lto_set_current_out_file (file); - ipa_write_optimization_summaries (set); + ipa_write_optimization_summaries (set, vset); lto_set_current_out_file (NULL); lto_obj_file_close (file); |