aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-20 14:09:11 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-20 14:09:11 +0000
commit8efa224a4726b06afa27e17420cb0d5dd97b48d4 (patch)
tree2702c3a55f5c856b2b5eb0aafbdc79ca115c0691 /gcc/cgraphunit.c
parentdf3e5a6720533cd7fc68542e730168fc752cc698 (diff)
* lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags.
* cgraph.c (cgraph_add_thunk): Use mark_reachable_node. (cgraph_remove_node): Update. (cgraph_mark_needed_node): Remove. (cgraph_mark_force_output_node): New. (dump_cgraph_node): Do not dump needed flag. (cgraph_node_cannot_be_local_p_1): Update. (cgraph_can_remove_if_no_direct_calls_and_refs): Update. * cgraph.h (symtab_node_base): Add force_output flag. (cgraph_node): Remove needed flag. (varpool_node): Remove force_output flag. (cgraph_mark_needed_node): Remove. (cgraph_mark_force_output_node): New. (cgraph_only_called_directly_or_aliased_p, varpool_can_remove_if_no_refs, varpool_all_refs_explicit_p): Update. * ipa-cp.c (ipcp_generate_summary): Remove out of date assert. * cgraphunit.c (cgraph_decide_is_function_needed): rewrite. (cgraph_add_new_function); Update. (cgraph_mark_if_needed); Update. (verify_cgraph_node): Update. (cgraph_analyze_function): Alias target is reachable. (process_function_and_variable_attributes): Update: externally_visible flag makes function reachable. (cgraph_analyze_functions): Update dumping. * lto-cgraph.c (lto_output_node, lto_output_varpool_node, input_overwrite_node, input_varpool_node): Update streaming. * lto-streamer-out.c (produce_symtab): Use force_output. * ipa.c (process_references): Weakrefs must be processed. (cgraph_remove_unreachable_nodes): Likewise; update for new force_output flag. (varpool_externally_visible_p); Weakrefs are externally visible even if they are not. (function_and_variable_visibility): Update; when processing alias pair force the targets to be output. (whole_program_function_and_variable_visility): Use mark_reachable_node. * trans-mem.c (ipa_tm_mark_needed_node): Remove (ipa_tm_mark_force_output_node): New function. (ipa_tm_create_version_alias, ipa_tm_create_version): Update. * gimple-fold.c (can_refer_decl_in_current_unit_p): Be lax about aliases. * varasm.c (mark_decl_referenced): Update. (find_decl_and_mark_needed): Remove. (find_decl): New function. (weak_finish, finish_aliases_1, assemble_alias): Update; do not mark alias targets as needed. (dump_tm_clone_pairs): Update. * tree-inline.c (copy_bb): Update check. * symtab.c (dump_symtab_base): Dump force_output. * tree-ssa-structalias.c (ipa_pta_execute): Use force_output. * passes.c (execute_todo): Fix dumping. * varpool.c (decide_is_variable_needed, varpool_finalize_decl): Update. (varpool_analyze_pending_decls): Alias target is reachable. (varpool_create_variable_alias): Finalize weakrefs. * class.c (make_local_function_alias): Do not mark symbol referenced. * objc-acct.c (mark_referenced_methods); Use cgraph_mark_force_output_node. * gcc-interface/utils.c (gnat_write_global_declarations): Update for new force_output placement. * lto/lto-partition.c (partition_cgraph_node_p): Use force_output. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186624 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c116
1 files changed, 52 insertions, 64 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 9de423396c1..3e07e501013 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -156,56 +156,36 @@ FILE *cgraph_dump_file;
/* Used for vtable lookup in thunk adjusting. */
static GTY (()) tree vtable_entry_type;
-/* Determine if function DECL is needed. That is, visible to something
- either outside this translation unit, something magic in the system
- configury. */
+/* Determine if function DECL is trivially needed and should stay in the
+ compilation unit. This is used at the symbol table construction time
+ and differs from later logic removing unnecesary functions that can
+ take into account results of analysis, whole program info etc. */
bool
cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
{
/* If the user told us it is used, then it must be so. */
- if (node->symbol.externally_visible)
+ if (node->symbol.force_output)
return true;
- /* ??? If the assembler name is set by hand, it is possible to assemble
- the name later after finalizing the function and the fact is noticed
- in assemble_name then. This is arguably a bug. */
- if (DECL_ASSEMBLER_NAME_SET_P (decl)
- && (!node->thunk.thunk_p && !node->same_body_alias)
- && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- return true;
+ /* Double check that no one output the function into assembly file
+ early. */
+ gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl)
+ || (node->thunk.thunk_p || node->same_body_alias)
+ || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
- /* With -fkeep-inline-functions we are keeping all inline functions except
- for extern inline ones. */
- if (flag_keep_inline_functions
- && DECL_DECLARED_INLINE_P (decl)
- && !DECL_EXTERNAL (decl)
- && !DECL_DISREGARD_INLINE_LIMITS (decl))
- return true;
- /* If we decided it was needed before, but at the time we didn't have
- the body of the function available, then it's still needed. We have
- to go back and re-check its dependencies now. */
- if (node->needed)
- return true;
+ /* Keep constructors, destructors and virtual functions. */
+ if (DECL_STATIC_CONSTRUCTOR (decl)
+ || DECL_STATIC_DESTRUCTOR (decl)
+ || (DECL_VIRTUAL_P (decl)
+ && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
+ return true;
/* Externally visible functions must be output. The exception is
- COMDAT functions that must be output only when they are needed.
+ COMDAT functions that must be output only when they are needed. */
- When not optimizing, also output the static functions. (see
- PR24561), but don't do so for always_inline functions, functions
- declared inline and nested functions. These were optimized out
- in the original implementation and it is unclear whether we want
- to change the behavior here. */
- if (((TREE_PUBLIC (decl)
- || (!optimize
- && !node->same_body_alias
- && !DECL_DISREGARD_INLINE_LIMITS (decl)
- && !DECL_DECLARED_INLINE_P (decl)
- && !(DECL_CONTEXT (decl)
- && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)))
- && !flag_whole_program
- && !flag_lto)
+ if (TREE_PUBLIC (decl)
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
return true;
@@ -337,22 +317,29 @@ cgraph_finalize_function (tree decl, bool nested)
node->local.finalized = true;
node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
- if (cgraph_decide_is_function_needed (node, decl))
- cgraph_mark_needed_node (node);
+ /* With -fkeep-inline-functions we are keeping all inline functions except
+ for extern inline ones. */
+ if (flag_keep_inline_functions
+ && DECL_DECLARED_INLINE_P (decl)
+ && !DECL_EXTERNAL (decl)
+ && !DECL_DISREGARD_INLINE_LIMITS (decl))
+ node->symbol.force_output = 1;
- /* Since we reclaim unreachable nodes at the end of every language
- level unit, we need to be conservative about possible entry points
- there. */
- if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
- || DECL_STATIC_CONSTRUCTOR (decl)
- || DECL_STATIC_DESTRUCTOR (decl)
- /* COMDAT virtual functions may be referenced by vtable from
- other compilation unit. Still we want to devirtualize calls
- to those so we need to analyze them.
- FIXME: We should introduce may edges for this purpose and update
- their handling in unreachable function removal and inliner too. */
- || (DECL_VIRTUAL_P (decl)
- && optimize && (DECL_COMDAT (decl) || DECL_EXTERNAL (decl))))
+ /* When not optimizing, also output the static functions. (see
+ PR24561), but don't do so for always_inline functions, functions
+ declared inline and nested functions. These were optimized out
+ in the original implementation and it is unclear whether we want
+ to change the behavior here. */
+ if ((!optimize
+ && !node->same_body_alias
+ && !DECL_DISREGARD_INLINE_LIMITS (decl)
+ && !DECL_DECLARED_INLINE_P (decl)
+ && !(DECL_CONTEXT (decl)
+ && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))
+ && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+ node->symbol.force_output = 1;
+
+ if (cgraph_decide_is_function_needed (node, decl))
cgraph_mark_reachable_node (node);
/* If we've not yet emitted decl, tell the debug info about it. */
@@ -402,7 +389,7 @@ cgraph_add_new_function (tree fndecl, bool lowered)
node = cgraph_get_create_node (fndecl);
node->local.local = false;
node->local.finalized = true;
- node->reachable = node->needed = true;
+ node->reachable = node->symbol.force_output = true;
if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
{
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
@@ -462,7 +449,7 @@ cgraph_mark_if_needed (tree decl)
{
struct cgraph_node *node = cgraph_get_node (decl);
if (node->local.finalized && cgraph_decide_is_function_needed (node, decl))
- cgraph_mark_needed_node (node);
+ cgraph_mark_reachable_node (node);
}
/* Return TRUE if NODE2 is equivalent to NODE or its clone. */
@@ -601,9 +588,9 @@ verify_cgraph_node (struct cgraph_node *node)
error ("inline clone with address taken");
error_found = true;
}
- if (node->global.inlined_to && node->needed)
+ if (node->global.inlined_to && node->symbol.force_output)
{
- error ("inline clone is needed");
+ error ("inline clone is forced to output");
error_found = true;
}
for (e = node->indirect_calls; e; e = e->next_callee)
@@ -901,6 +888,7 @@ cgraph_analyze_function (struct cgraph_node *node)
if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
ipa_record_reference ((symtab_node)node, (symtab_node)tgt,
IPA_REF_ALIAS, NULL);
+ cgraph_mark_reachable_node (tgt);
if (node->same_body_alias)
{
DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias);
@@ -940,7 +928,7 @@ cgraph_analyze_function (struct cgraph_node *node)
if (node->symbol.address_taken)
cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
if (cgraph_decide_is_function_needed (node, node->symbol.decl))
- cgraph_mark_needed_node (node);
+ cgraph_mark_reachable_node (node);
}
else if (node->thunk.thunk_p)
{
@@ -1061,13 +1049,13 @@ process_function_and_variable_attributes (struct cgraph_node *first,
{
tree decl = node->symbol.decl;
if (DECL_PRESERVE_P (decl))
- cgraph_mark_needed_node (node);
+ cgraph_mark_force_output_node (node);
if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))
&& TREE_PUBLIC (node->symbol.decl))
{
if (node->local.finalized)
- cgraph_mark_needed_node (node);
+ cgraph_mark_reachable_node (node);
}
else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
{
@@ -1076,7 +1064,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
"%<externally_visible%>"
" attribute have effect only on public objects");
else if (node->local.finalized)
- cgraph_mark_needed_node (node);
+ cgraph_mark_reachable_node (node);
}
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
&& (node->local.finalized && !node->alias))
@@ -1104,7 +1092,7 @@ process_function_and_variable_attributes (struct cgraph_node *first,
tree decl = vnode->symbol.decl;
if (DECL_PRESERVE_P (decl))
{
- vnode->force_output = true;
+ vnode->symbol.force_output = true;
if (vnode->finalized)
varpool_mark_needed_node (vnode);
}
@@ -1165,7 +1153,7 @@ cgraph_analyze_functions (void)
fprintf (cgraph_dump_file, "Initial entry points:");
for (node = cgraph_first_function (); node != first_analyzed;
node = cgraph_next_function (node))
- if (node->needed)
+ if (cgraph_decide_is_function_needed (node, node->symbol.decl))
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n");
}
@@ -1241,7 +1229,7 @@ cgraph_analyze_functions (void)
fprintf (cgraph_dump_file, "Unit entry points:");
for (node = cgraph_first_function (); node != first_analyzed;
node = cgraph_next_function (node))
- if (node->needed)
+ if (cgraph_decide_is_function_needed (node, node->symbol.decl))
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n\nInitial ");
dump_symtab (cgraph_dump_file);