diff options
author | Jan Hubicka <jh@suse.cz> | 2013-05-29 22:42:50 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2013-05-29 20:42:50 +0000 |
commit | e70670cf4db3759336199993451af2739723de87 (patch) | |
tree | 3c8fecbc03b258758055280236d0a5da8994b8cc /gcc/ipa.c | |
parent | 182802adcc315bbbc5a4e468d9a6817be6be5c08 (diff) | |
download | gcc-e70670cf4db3759336199993451af2739723de87.zip gcc-e70670cf4db3759336199993451af2739723de87.tar.gz gcc-e70670cf4db3759336199993451af2739723de87.tar.bz2 |
cgraph.h (symtab_node_base): Add definition, alias and analyzed flags...
* cgraph.h (symtab_node_base): Add definition, alias and analyzed
flags; reorder rest of fields in more consistent way.
(varpool_node): Remove analyzed, finalized and alias.
(cgraph_ndoe): Likewise.
(symtab_alias_ultimate_target): New function.
(cgraph_function_node): Move offline.
(cgraph_reset_node): Declare.
(cgraph_comdat_can_be_unshared_p): Remove.
(varpool_remove_initializer): Declare.
(varpool_first_defined_variable, varpool_next_defined_variable
cgraph_first_defined_function, cgraph_next_defined_function): Update.
(cgraph_function_with_gimple_body_p): Update.
(varpool_all_refs_explicit_p): Update.
(symtab_alias_target): New function.
(cgraph_alias_aliased_node, varpool_alias_aliased_node): Rename to ...
(cgraph_alias_target, varpool_alias_target): .. this one; simplify.
(cgraph_function_or_thunk_node): Simplify using symtab_alias_ultimate_target.
(varpool_variable_node): Likewise.
* cgraph.c (cgraph_create_function_alias): Update.
(cgraph_add_thunk): Update.
(cgraph_remove_node): Update.
(dump_cgraph_node): Do not dump removed flags.
(cgraph_function_body_availability): Update.
(cgraph_propagate_frequency): Update.
(verify_cgraph_node): Check sanity of local flag.
(cgraph_function_node): Move here from cgraph.h; revamp for
cgraph_function_or_thunk_node.
* lto-symtab.c (lto_varpool_replace_node): Update.
(lto_symtab_resolve_can_prevail_p): Update.
(lto_symtab_merge_cgraph_nodes): Update.
* ipa-cp.c (determine_versionability, initialize_node_lattices,
propagate_constants_accross_call, devirtualization_time_bonus,
ipcp_propagate_stage): Update.
* tree-emutls.c (create_emultls_var, ipa_lower_emutls): Update.
* ipa-inline-transform.c (clone_inlined_nodes, preserve_function_body_p): Update.
* ipa-reference.c (propagate): Update.
(write_node_summary_p): Update.
* toplev.c (wrapup_global_declaration_2): Update.
* cgraphunit.c (cgraph_analyze_function): Rename to ...
(analyze_function) ... this one.
(cgraph_process_new_functions): Update.
(cgraph_reset_node): Export.
(cgraph_finalize_function): Update.
(cgraph_add_new_function): Update.
(process_function_and_variable_attributes): Update.
(varpool_finalize_decl): Update.
(symbol_finalized): Remove.
(symbol_finalized_and_needed): Rename to ...
(symbol_defined_and_needed): ... update.
(cgraph_analyze_functions): Update.
(handle_alias_pairs): Update.
(mark_functions_to_output): Update.
(assemble_thunk): Update.
(output_in_order): Update.
(output_weakrefs): Update.
(finalize_compilation_unit): Update.
* lto-cgraph.c (reachable_from_other_partition_p, lto_output_node,
lto_output_varpool_node, compute_ltrans_boundary, input_overwrite_node,
input_node, input_varpool_node): Update.
* dbxout.c (dbxout_expand_expr): Update.
* cgraphclones.c (cgraph_clone_node): Update.
(cgraph_copy_node_for_versioning): Update.
(cgraph_materialize_clone): Update.
(cgraph_materialize_all_clones): Update.
* ipa-pure-const.c (analyze_function, pure_const_write_summary,
propagate_pure_const, propagate_nothrow): Update.
* lto-streamer-out.c (lto_output, write_symbol): Update.
* ipa-utils.c (ipa_reverse_postorder): Update.
* ipa-inline.c (can_inline_edge_p): Update.
(update_caller_keys, ipa_inline): Update.
* dwarf2out.c (reference_to_unused,
premark_types_used_by_global_vars_helper): Update.
* tree-eh.c (tree_could_trap_p): Update.
* ipa-split.c (consider_split, execute_split_functions): Update.
* ipa.c (cgraph_non_local_node_p_1, cgraph_local_node_p,
has_addr_references_p): Update;
move ahead in file for better readability.
(process_references): Simplify.
(symtab_remove_unreachable_nodes): Update; cleanup way function/var
bodies are removed.
(cgraph_comdat_can_be_unshared_p): Make static.
(cgraph_externally_visible_p): Update.
(varpool_externally_visible_p): Update.
(function_and_variable_visibility): Update.
* trans-mem.c (get_cg_data, ipa_tm_mayenterirr_function,
ipa_tm_mark_force_output_node): Update.
* ipa-inline-analysis.c (dump_inline_summary, initialize_inline_failed,
estimate_edge_devirt_benefit, inline_generate_summary,
inline_write_summary): Update.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
* ipa-prop.c (ipa_compute_jump_functions): Update.
(ipa_print_node_params, ipa_prop_read_section, ipa_update_after_lto_read,
read_replacements_section): Update.
* varasm.c (mark_decl_referenced): Update.
(assemble_alias, dump_tm_clone_pairs): Update.
* tree-inline.c (copy_bb): Update.
(estimate_num_insns, optimize_inline_calls, tree_function_versioning):
Update.
* symtab.c (dump_symtab_base): Print new flags.
(verify_symtab_base): Verify new flags.
(symtab_alias_ultimate_target): New function.
* tree-ssa-structalias.c (get_constraint_for_ssa_var,
create_variable_info_for, associate_varinfo_to_alias, ipa_pta_execute):
Update.
* passes.c (ipa_write_summaries, ipa_write_optimization_summaries): Update.
* i386.c (ix86_get_function_versions_dispatcher,
ix86_generate_version_dispatcher_body): Update.
(fold_builtin_cpu): Use varpool_add_new_variable.
* varpool.c (varpool_remove_initializer): Break out from ...
(varpool_remove_node): ... this one.
(dump_varpool_node, varpool_node_for_asm,
cgraph_variable_initializer_availability, varpool_analyze_node,
varpool_assemble_decl, varpool_remove_unreferenced_decls,
varpool_finalize_named_section_flags, varpool_create_variable_alias): Update
* decl.c (java_mark_decl_local): Update for new symtab flags.
* tree.c (cp_fix_function_decl_p): Update for new symtab flags.
* decl2.c )var_finalized_p, cp_write_global_declarations): Likewise.
* lto.c (has_analyzed_clone_p, lto_materialize_function): Update for new symtab
flags.
* lto-partition.c (get_symbol_class, lto_balanced_map): Likewise.
From-SVN: r199422
Diffstat (limited to 'gcc/ipa.c')
-rw-r--r-- | gcc/ipa.c | 181 |
1 files changed, 89 insertions, 92 deletions
@@ -39,6 +39,53 @@ along with GCC; see the file COPYING3. If not see #include "lto-streamer.h" #include "data-streamer.h" +/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */ + +static bool +cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) +{ + /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */ + return !(cgraph_only_called_directly_or_aliased_p (node) + && !ipa_ref_has_aliases_p (&node->symbol.ref_list) + && node->symbol.definition + && !DECL_EXTERNAL (node->symbol.decl) + && !node->symbol.externally_visible + && !node->symbol.used_from_other_partition + && !node->symbol.in_other_partition); +} + +/* Return true when function can be marked local. */ + +static bool +cgraph_local_node_p (struct cgraph_node *node) +{ + struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL); + + /* FIXME: thunks can be considered local, but we need prevent i386 + from attempting to change calling convention of them. */ + if (n->thunk.thunk_p) + return false; + return !cgraph_for_node_and_aliases (n, + cgraph_non_local_node_p_1, NULL, true); + +} + +/* Return true when NODE has ADDR reference. */ + +static bool +has_addr_references_p (struct cgraph_node *node, + void *data ATTRIBUTE_UNUSED) +{ + int i; + struct ipa_ref *ref; + + for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, + i, ref); i++) + if (ref->use == IPA_REF_ADDR) + return true; + return false; +} + /* Look for all functions inlined to NODE and update their inlined_to pointers to INLINED_TO. */ @@ -89,79 +136,23 @@ process_references (struct ipa_ref_list *list, struct ipa_ref *ref; for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) { - if (is_a <cgraph_node> (ref->referred)) - { - struct cgraph_node *node = ipa_ref_node (ref); - - if (node->analyzed - && (!DECL_EXTERNAL (node->symbol.decl) - || node->alias - || before_inlining_p)) - pointer_set_insert (reachable, node); - enqueue_node ((symtab_node) node, first, reachable); - } - else - { - struct varpool_node *node = ipa_ref_varpool_node (ref); - - if (node->analyzed - && (!DECL_EXTERNAL (node->symbol.decl) - || node->alias - || before_inlining_p)) - pointer_set_insert (reachable, node); - enqueue_node ((symtab_node) node, first, reachable); - } + symtab_node node = ref->referred; + + if (node->symbol.definition + && (!DECL_EXTERNAL (node->symbol.decl) + || node->symbol.alias + || (before_inlining_p + /* We use variable constructors during late complation for + constant folding. Keep references alive so partitioning + knows about potential references. */ + || (TREE_CODE (node->symbol.decl) == VAR_DECL + && flag_wpa && const_value_known_p (node->symbol.decl))))) + pointer_set_insert (reachable, node); + enqueue_node ((symtab_node) node, first, reachable); } } -/* Return true when NODE can not be local. Worker for cgraph_local_node_p. */ - -static bool -cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) -{ - /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */ - return !(cgraph_only_called_directly_or_aliased_p (node) - && !ipa_ref_has_aliases_p (&node->symbol.ref_list) - && node->analyzed - && !DECL_EXTERNAL (node->symbol.decl) - && !node->symbol.externally_visible - && !node->symbol.used_from_other_partition - && !node->symbol.in_other_partition); -} - -/* Return true when function can be marked local. */ - -static bool -cgraph_local_node_p (struct cgraph_node *node) -{ - struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL); - - /* FIXME: thunks can be considered local, but we need prevent i386 - from attempting to change calling convention of them. */ - if (n->thunk.thunk_p) - return false; - return !cgraph_for_node_and_aliases (n, - cgraph_non_local_node_p_1, NULL, true); - -} - -/* Return true when NODE has ADDR reference. */ - -static bool -has_addr_references_p (struct cgraph_node *node, - void *data ATTRIBUTE_UNUSED) -{ - int i; - struct ipa_ref *ref; - - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, - i, ref); i++) - if (ref->use == IPA_REF_ADDR) - return true; - return false; -} - /* Perform reachability analysis and reclaim all unreachable nodes. The algorithm is basically mark&sweep but with some extra refinements: @@ -303,10 +294,10 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) struct cgraph_edge *e; for (e = cnode->callees; e; e = e->next_callee) { - if (e->callee->analyzed + if (e->callee->symbol.definition && (!e->inline_failed || !DECL_EXTERNAL (e->callee->symbol.decl) - || cnode->alias + || cnode->symbol.alias || before_inlining_p)) pointer_set_insert (reachable, e->callee); enqueue_node ((symtab_node) e->callee, &first, reachable); @@ -314,7 +305,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) /* When inline clone exists, mark body to be preserved so when removing offline copy of the function we don't kill it. */ - if (!cnode->alias && cnode->global.inlined_to) + if (!cnode->symbol.alias && cnode->global.inlined_to) pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl); } @@ -339,7 +330,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) varpool_node *vnode = dyn_cast <varpool_node> (node); if (vnode && DECL_EXTERNAL (node->symbol.decl) - && !vnode->alias + && !vnode->symbol.alias && in_boundary_p) { struct ipa_ref *ref; @@ -352,6 +343,8 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) for (node = cgraph_first_function (); node; node = next) { next = cgraph_next_function (node); + + /* If node is not needed at all, remove it. */ if (!node->symbol.aux) { if (file) @@ -359,20 +352,18 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) cgraph_remove_node (node); changed = true; } + /* If node is unreachable, remove its body. */ else if (!pointer_set_contains (reachable, node)) { - if (node->analyzed) + if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)) + cgraph_release_function_body (node); + if (node->symbol.definition) { if (file) fprintf (file, " %s", cgraph_node_name (node)); - cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + cgraph_reset_node (node); changed = true; } - if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl) - && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl))) - cgraph_release_function_body (node); - node->analyzed = false; } } @@ -406,14 +397,20 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) } else if (!pointer_set_contains (reachable, vnode)) { - if (vnode->analyzed) + if (vnode->symbol.definition) { if (file) fprintf (file, " %s", varpool_node_name (vnode)); changed = true; } - vnode->analyzed = false; + vnode->symbol.definition = false; + vnode->symbol.analyzed = false; vnode->symbol.aux = NULL; + + /* Keep body if it may be useful for constant folding. */ + if (!const_value_known_p (vnode->symbol.decl)) + varpool_remove_initializer (vnode); + ipa_remove_all_references (&vnode->symbol.ref_list); } else vnode->symbol.aux = NULL; @@ -474,7 +471,7 @@ ipa_discover_readonly_nonaddressable_vars (void) if (dump_file) fprintf (dump_file, "Clearing variable flags:"); FOR_EACH_VARIABLE (vnode) - if (vnode->finalized && varpool_all_refs_explicit_p (vnode) + if (vnode->symbol.definition && varpool_all_refs_explicit_p (vnode) && (TREE_ADDRESSABLE (vnode->symbol.decl) || !TREE_READONLY (vnode->symbol.decl))) { @@ -546,12 +543,12 @@ cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node) Virtual functions do have their addresses taken from the vtables, but in C++ there is no way to compare their addresses for equality. */ -bool +static bool cgraph_comdat_can_be_unshared_p (struct cgraph_node *node) { if ((cgraph_address_taken_from_non_vtable_p (node) && !DECL_VIRTUAL_P (node->symbol.decl)) - || !node->analyzed) + || !node->symbol.definition) return false; if (node->symbol.same_comdat_group) { @@ -575,7 +572,7 @@ static bool cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program) { - if (!node->local.finalized) + if (!node->symbol.definition) return false; if (!DECL_COMDAT (node->symbol.decl) && (!TREE_PUBLIC (node->symbol.decl) @@ -619,7 +616,7 @@ cgraph_externally_visible_p (struct cgraph_node *node, || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL) /* Be sure that node is defined in IR file, not in other object file. In that case we don't set used_from_other_object_file. */ - && node->analyzed) + && node->symbol.definition) ; else if (!whole_program) return true; @@ -638,7 +635,7 @@ varpool_externally_visible_p (struct varpool_node *vnode) /* Do not touch weakrefs; while they are not externally visible, dropping their DECL_EXTERNAL flags confuse most of code handling them. */ - if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl)) + if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl)) return true; if (DECL_EXTERNAL (vnode->symbol.decl)) @@ -690,7 +687,7 @@ varpool_externally_visible_p (struct varpool_node *vnode) || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL) /* Be sure that node is defined in IR file, not in other object file. In that case we don't set used_from_other_object_file. */ - && vnode->finalized) + && vnode->symbol.definition) ; else if (!flag_whole_program) return true; @@ -744,7 +741,7 @@ function_and_variable_visibility (bool whole_program) We may end up marking as node external nodes where this flag is meaningless strip it. */ if (node->symbol.force_output - && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed)) + && (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition)) node->symbol.force_output = 0; /* C++ FE on lack of COMDAT support create local COMDAT functions @@ -781,7 +778,7 @@ function_and_variable_visibility (bool whole_program) } else node->symbol.externally_visible = false; - if (!node->symbol.externally_visible && node->analyzed + if (!node->symbol.externally_visible && node->symbol.definition && !DECL_EXTERNAL (node->symbol.decl)) { gcc_assert (whole_program || in_lto_p @@ -854,7 +851,7 @@ function_and_variable_visibility (bool whole_program) } FOR_EACH_DEFINED_VARIABLE (vnode) { - if (!vnode->finalized) + if (!vnode->symbol.definition) continue; if (varpool_externally_visible_p (vnode)) vnode->symbol.externally_visible = true; |