aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-05-29 22:42:50 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2013-05-29 20:42:50 +0000
commite70670cf4db3759336199993451af2739723de87 (patch)
tree3c8fecbc03b258758055280236d0a5da8994b8cc /gcc/ipa.c
parent182802adcc315bbbc5a4e468d9a6817be6be5c08 (diff)
downloadgcc-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.c181
1 files changed, 89 insertions, 92 deletions
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 5613c26..254c09f 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -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;