From ead84f73b0a0f39ea39aa0329b6da83e4a9e6e02 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 20 Apr 2012 16:09:11 +0200 Subject: [PATCH] lto-symtab.c (lto_cgraph_replace_node): Merge needed instead of force flags. * 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. From-SVN: r186624 --- gcc/ChangeLog | 55 ++++++++++++++++++++ gcc/ada/ChangeLog | 5 ++ gcc/ada/gcc-interface/utils.c | 2 +- gcc/cgraph.c | 14 +++-- gcc/cgraph.h | 23 ++++----- gcc/cgraphunit.c | 116 +++++++++++++++++++----------------------- gcc/gimple-fold.c | 1 + gcc/ipa-cp.c | 2 - gcc/ipa.c | 22 +++++--- gcc/java/ChangeLog | 4 ++ gcc/java/class.c | 1 - gcc/lto-cgraph.c | 8 +-- gcc/lto-streamer-out.c | 4 +- gcc/lto-symtab.c | 4 +- gcc/lto/ChangeLog | 4 ++ gcc/lto/lto-partition.c | 3 +- gcc/objc/ChangeLog | 5 ++ gcc/objc/objc-act.c | 4 +- gcc/passes.c | 2 +- gcc/symtab.c | 2 + gcc/trans-mem.c | 12 ++--- gcc/tree-inline.c | 2 +- gcc/tree-ssa-structalias.c | 2 +- gcc/varasm.c | 64 +++++++---------------- gcc/varpool.c | 8 +-- 25 files changed, 201 insertions(+), 168 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ff0cc2c..557968c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,58 @@ +2012-04-20 Jan Hubicka + + * 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. + 2012-04-20 Jakub Jelinek PR bootstrap/53021 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index ef1214a..8fd284a 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2012-04-20 Jan Hubicka + + * gcc-interface/utils.c (gnat_write_global_declarations): Update for new + force_output placement. + 2012-04-14 Jan Hubicka * gcc-interface/trans.c (finalize_nrv): Update field referenced for new diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 1460a43..e95e967 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -4859,7 +4859,7 @@ gnat_write_global_declarations (void) TREE_STATIC (dummy_global) = 1; TREE_ASM_WRITTEN (dummy_global) = 1; node = varpool_node (dummy_global); - node->force_output = 1; + node->symbol.force_output = 1; varpool_mark_needed_node (node); while (!VEC_empty (tree, types_used_by_cur_var_decl)) diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 8ba9c36..4588249 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -570,7 +570,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, node->local.finalized = true; if (cgraph_decide_is_function_needed (node, decl)) - cgraph_mark_needed_node (node); + cgraph_mark_reachable_node (node); if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) || (DECL_VIRTUAL_P (decl) @@ -1362,7 +1362,7 @@ cgraph_remove_node (struct cgraph_node *node) /* Incremental inlining access removed nodes stored in the postorder list. */ - node->needed = node->reachable = false; + node->symbol.force_output = node->reachable = false; for (n = node->nested; n; n = n->next_nested) n->origin = NULL; node->nested = NULL; @@ -1518,9 +1518,9 @@ cgraph_mark_reachable_node (struct cgraph_node *node) external means. */ void -cgraph_mark_needed_node (struct cgraph_node *node) +cgraph_mark_force_output_node (struct cgraph_node *node) { - node->needed = 1; + node->symbol.force_output = 1; gcc_assert (!node->global.inlined_to); cgraph_mark_reachable_node (node); } @@ -1642,8 +1642,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) (HOST_WIDEST_INT)node->count); if (node->origin) fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin)); - if (node->needed) - fprintf (f, " needed"); else if (node->reachable) fprintf (f, " reachable"); if (gimple_has_body_p (node->symbol.decl)) @@ -2134,7 +2132,7 @@ static bool cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { - return !(!node->needed + return !(!node->symbol.force_output && ((DECL_COMDAT (node->symbol.decl) && !node->symbol.same_comdat_group) || !node->symbol.externally_visible)); @@ -2570,7 +2568,7 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) if (DECL_EXTERNAL (node->symbol.decl)) return true; /* When function is needed, we can not remove it. */ - if (node->needed || node->symbol.used_from_other_partition) + if (node->symbol.force_output || node->symbol.used_from_other_partition) return false; if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl) || DECL_STATIC_DESTRUCTOR (node->symbol.decl)) diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 1fd42f1..5915a14 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -77,6 +77,9 @@ struct GTY(()) symtab_node_base unsigned in_other_partition : 1; /* Set when function is visible by other units. */ unsigned externally_visible : 1; + /* Needed variables might become dead by optimization. This flag + forces the variable to be output even if it appears dead otherwise. */ + unsigned force_output : 1; }; enum availability @@ -246,12 +249,6 @@ struct GTY(()) cgraph_node { /* Unique id of the node. */ int uid; - /* Set when function must be output for some reason. The primary - use of this flag is to mark functions needed to be output for - non-standard reason. Functions that are externally visible - or reachable from functions needed to be output are marked - by specialized flags. */ - unsigned needed : 1; /* Set when decl is an abstract function pointed to by the ABSTRACT_DECL_ORIGIN of a reachable function. */ unsigned abstract_and_needed : 1; @@ -433,9 +430,6 @@ struct GTY(()) varpool_node { /* Set when function must be output - it is externally visible or its address is taken. */ unsigned needed : 1; - /* Needed variables might become dead by optimization. This flag - forces the variable to be output even if it appears dead otherwise. */ - unsigned force_output : 1; /* Set once the variable has been instantiated and its callee lists created. */ unsigned analyzed : 1; @@ -610,7 +604,7 @@ void cgraph_mark_if_needed (tree); void cgraph_analyze_function (struct cgraph_node *); void cgraph_finalize_compilation_unit (void); void cgraph_optimize (void); -void cgraph_mark_needed_node (struct cgraph_node *); +void cgraph_mark_force_output_node (struct cgraph_node *); void cgraph_mark_address_taken_node (struct cgraph_node *); void cgraph_mark_reachable_node (struct cgraph_node *); bool cgraph_inline_p (struct cgraph_edge *, cgraph_inline_failed_t *reason); @@ -1118,7 +1112,7 @@ static inline bool cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node) { gcc_assert (!node->global.inlined_to); - return (!node->needed && !node->symbol.address_taken + return (!node->symbol.force_output && !node->symbol.address_taken && !node->symbol.used_from_other_partition && !DECL_STATIC_CONSTRUCTOR (node->symbol.decl) && !DECL_STATIC_DESTRUCTOR (node->symbol.decl) @@ -1131,9 +1125,10 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node) static inline bool varpool_can_remove_if_no_refs (struct varpool_node *node) { - return (!node->force_output && !node->symbol.used_from_other_partition + return (!node->symbol.force_output && !node->symbol.used_from_other_partition && (DECL_COMDAT (node->symbol.decl) - || !node->symbol.externally_visible)); + || !node->symbol.externally_visible + || DECL_EXTERNAL (node->symbol.decl))); } /* Return true when all references to VNODE must be visible in ipa_ref_list. @@ -1147,7 +1142,7 @@ varpool_all_refs_explicit_p (struct varpool_node *vnode) return (vnode->analyzed && !vnode->symbol.externally_visible && !vnode->symbol.used_from_other_partition - && !vnode->force_output); + && !vnode->symbol.force_output); } /* Constant pool accessor function. */ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 9de4233..3e07e50 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, "%" " 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); diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 049da57..49505ee 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -70,6 +70,7 @@ can_refer_decl_in_current_unit_p (tree decl) flags incorrectly. Those variables should never be finalized. */ gcc_checking_assert (!(vnode = varpool_get_node (decl)) + || vnode->alias || !vnode->finalized); return false; } diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index d0a6ee0..4826c58 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -2494,8 +2494,6 @@ ipcp_generate_summary (void) FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { - /* Unreachable nodes should have been eliminated before ipcp. */ - gcc_assert (node->needed || node->reachable); node->local.versionable = tree_versionable_function_p (node->symbol.decl); ipa_analyze_node (node); diff --git a/gcc/ipa.c b/gcc/ipa.c index 964b2b9..f4daf36 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -97,6 +97,7 @@ process_references (struct ipa_ref_list *list, if (!node->reachable && node->analyzed && (!DECL_EXTERNAL (node->symbol.decl) + || node->alias || before_inlining_p)) node->reachable = true; enqueue_cgraph_node (node, first); @@ -214,7 +215,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) { vnode->next_needed = NULL; vnode->prev_needed = NULL; - if ((vnode->analyzed || vnode->force_output) + if ((vnode->analyzed || vnode->symbol.force_output) && !varpool_can_remove_if_no_refs (vnode)) { vnode->needed = false; @@ -254,6 +255,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) && node->analyzed && (!e->inline_failed || !DECL_EXTERNAL (e->callee->symbol.decl) + || node->alias || before_inlining_p)) e->callee->reachable = true; enqueue_cgraph_node (e->callee, &first); @@ -659,6 +661,12 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool varpool_externally_visible_p (struct varpool_node *vnode, bool aliased) { + /* 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)) + return true; + if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl)) return false; @@ -700,7 +708,7 @@ varpool_externally_visible_p (struct varpool_node *vnode, bool aliased) is faster for dynamic linking. Also this match logic hidding vtables from LTO symbol tables. */ if ((in_lto_p || flag_whole_program) - && !vnode->force_output + && !vnode->symbol.force_output && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl)) return false; @@ -776,8 +784,7 @@ function_and_variable_visibility (bool whole_program) { if (!node->analyzed) continue; - cgraph_mark_needed_node (node); - gcc_assert (node->needed); + cgraph_mark_force_output_node (node); pointer_set_insert (aliased_nodes, node); if (dump_file) fprintf (dump_file, " node %s/%i", @@ -786,6 +793,7 @@ function_and_variable_visibility (bool whole_program) else if ((vnode = varpool_node_for_asm (p->target)) != NULL && !DECL_EXTERNAL (vnode->symbol.decl)) { + vnode->symbol.force_output = 1; varpool_mark_needed_node (vnode); gcc_assert (vnode->needed); pointer_set_insert (aliased_vnodes, vnode); @@ -813,9 +821,9 @@ function_and_variable_visibility (bool whole_program) /* Frontends and alias code marks nodes as needed before parsing is finished. We may end up marking as node external nodes where this flag is meaningless strip it. */ - if (node->needed + if (node->symbol.force_output && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed)) - node->needed = 0; + node->symbol.force_output = 0; /* C++ FE on lack of COMDAT support create local COMDAT functions (that ought to be shared but can not due to object format @@ -1017,7 +1025,7 @@ whole_program_function_and_variable_visibility (void) FOR_EACH_DEFINED_FUNCTION (node) if ((node->symbol.externally_visible && !DECL_COMDAT (node->symbol.decl)) && node->local.finalized) - cgraph_mark_needed_node (node); + cgraph_mark_reachable_node (node); FOR_EACH_DEFINED_VARIABLE (vnode) if (vnode->symbol.externally_visible && !DECL_COMDAT (vnode->symbol.decl)) varpool_mark_needed_node (vnode); diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 6f75740..14eb423 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,7 @@ +2012-04-20 Jan Hubicka + + * class.c (make_local_function_alias): Do not mark symbol referenced. + 2012-04-11 Rainer Orth * jcf-dump.c (print_constant): Cast JPOOL_USHORT2, JPOOL_USHORT1 diff --git a/gcc/java/class.c b/gcc/java/class.c index 3c34aba..145bb63 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -1407,7 +1407,6 @@ make_local_function_alias (tree method) DECL_INITIAL (alias) = error_mark_node; TREE_ADDRESSABLE (alias) = 1; TREE_USED (alias) = 1; - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1; if (!flag_syntax_only) assemble_alias (alias, DECL_ASSEMBLER_NAME (method)); return alias; diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 18152a8..c0398b4 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -503,7 +503,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp_pack_value (&bp, node->local.versionable, 1); bp_pack_value (&bp, node->local.can_change_signature, 1); bp_pack_value (&bp, node->local.redefined_extern_inline, 1); - bp_pack_value (&bp, node->needed, 1); + bp_pack_value (&bp, node->symbol.force_output, 1); bp_pack_value (&bp, node->symbol.address_taken, 1); bp_pack_value (&bp, node->abstract_and_needed, 1); bp_pack_value (&bp, tag == LTO_cgraph_analyzed_node @@ -566,7 +566,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl); bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, node->symbol.externally_visible, 1); - bp_pack_value (&bp, node->force_output, 1); + bp_pack_value (&bp, node->symbol.force_output, 1); bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->alias, 1); bp_pack_value (&bp, node->alias_of != NULL, 1); @@ -911,7 +911,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, node->local.versionable = bp_unpack_value (bp, 1); node->local.can_change_signature = bp_unpack_value (bp, 1); node->local.redefined_extern_inline = bp_unpack_value (bp, 1); - node->needed = bp_unpack_value (bp, 1); + node->symbol.force_output = bp_unpack_value (bp, 1); node->symbol.address_taken = bp_unpack_value (bp, 1); node->abstract_and_needed = bp_unpack_value (bp, 1); node->symbol.used_from_other_partition = bp_unpack_value (bp, 1); @@ -1075,7 +1075,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, bp = streamer_read_bitpack (ib); node->symbol.externally_visible = bp_unpack_value (&bp, 1); - node->force_output = bp_unpack_value (&bp, 1); + node->symbol.force_output = bp_unpack_value (&bp, 1); node->finalized = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1); non_null_aliasof = bp_unpack_value (&bp, 1); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index fa6a3dc..89850f0 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1456,7 +1456,7 @@ produce_symtab (struct output_block *ob, in the LTO symbol table to prevent linker from forcing them into the output. */ if (DECL_COMDAT (vnode->symbol.decl) - && !vnode->force_output + && !vnode->symbol.force_output && vnode->finalized && DECL_VIRTUAL_P (vnode->symbol.decl)) continue; @@ -1470,7 +1470,7 @@ produce_symtab (struct output_block *ob, if (!DECL_EXTERNAL (vnode->symbol.decl)) continue; if (DECL_COMDAT (vnode->symbol.decl) - && !vnode->force_output + && !vnode->symbol.force_output && vnode->finalized && DECL_VIRTUAL_P (vnode->symbol.decl)) continue; diff --git a/gcc/lto-symtab.c b/gcc/lto-symtab.c index bbb9d1b..ed8a651 100644 --- a/gcc/lto-symtab.c +++ b/gcc/lto-symtab.c @@ -223,8 +223,8 @@ lto_cgraph_replace_node (struct cgraph_node *node, } /* Merge node flags. */ - if (node->needed) - cgraph_mark_needed_node (prevailing_node); + if (node->symbol.force_output) + cgraph_mark_force_output_node (prevailing_node); if (node->reachable) cgraph_mark_reachable_node (prevailing_node); if (node->symbol.address_taken) diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 96a8c97..6b86475 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,7 @@ +2012-04-20 Jan Hubicka + + * lto-partition.c (partition_cgraph_node_p): Use force_output. + 2012-04-18 Jan Hubicka * lto-partition.c (add_references_to_partition, lto_balanced_map): diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index 6fe672f..8287f8f 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -269,6 +269,7 @@ partition_cgraph_node_p (struct cgraph_node *node) /* Extern inlines and comdat are always only in partitions they are needed. */ if (DECL_EXTERNAL (node->symbol.decl) || (DECL_COMDAT (node->symbol.decl) + && !node->symbol.force_output && !cgraph_used_from_object_file_p (node))) return false; if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))) @@ -287,7 +288,7 @@ partition_varpool_node_p (struct varpool_node *vnode) /* Constant pool and comdat are always only in partitions they are needed. */ if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl) || (DECL_COMDAT (vnode->symbol.decl) - && !vnode->force_output + && !vnode->symbol.force_output && !varpool_used_from_object_file_p (vnode))) return false; if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl))) diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 32f7b1a..6fed845 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2012-04-20 Jan Hubicka + + * objc-acct.c (mark_referenced_methods); Use + cgraph_mark_force_output_node. + 2012-03-21 Steven Bosscher * objc-act (objc_build_ivar_assignment): Do not call assemble_external. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 78a3cee..ec07971 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -4625,7 +4625,7 @@ mark_referenced_methods (void) chain = CLASS_CLS_METHODS (impent->imp_context); while (chain) { - cgraph_mark_needed_node ( + cgraph_mark_force_output_node ( cgraph_get_create_node (METHOD_DEFINITION (chain))); chain = DECL_CHAIN (chain); } @@ -4633,7 +4633,7 @@ mark_referenced_methods (void) chain = CLASS_NST_METHODS (impent->imp_context); while (chain) { - cgraph_mark_needed_node ( + cgraph_mark_force_output_node ( cgraph_get_create_node (METHOD_DEFINITION (chain))); chain = DECL_CHAIN (chain); } diff --git a/gcc/passes.c b/gcc/passes.c index fadb4d7..ed5da15 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1865,7 +1865,7 @@ execute_todo (unsigned int flags) if ((flags & TODO_dump_symtab) && dump_file && !current_function_decl) { gcc_assert (!cfun); - dump_cgraph (dump_file); + dump_symtab (dump_file); /* Flush the file. If verification fails, we won't be able to close the file before aborting. */ fflush (dump_file); diff --git a/gcc/symtab.c b/gcc/symtab.c index 458075c..75078b0 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -378,6 +378,8 @@ dump_symtab_base (FILE *f, symtab_node node) fprintf (f, " in_other_partition"); if (node->symbol.used_from_other_partition) fprintf (f, " used_from_other_partition"); + if (node->symbol.force_output) + fprintf (f, " force_output"); if (node->symbol.resolution != LDPR_UNKNOWN) fprintf (f, " %s", ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]); diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index 2a43585..b1dd2a0 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -4267,9 +4267,9 @@ tm_mangle (tree old_asm_id) } static inline void -ipa_tm_mark_needed_node (struct cgraph_node *node) +ipa_tm_mark_force_output_node (struct cgraph_node *node) { - cgraph_mark_needed_node (node); + cgraph_mark_force_output_node (node); /* ??? function_and_variable_visibility will reset the needed bit, without actually checking. */ node->analyzed = 1; @@ -4328,8 +4328,8 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data) record_tm_clone_pair (old_decl, new_decl); - if (info->old_node->needed) - ipa_tm_mark_needed_node (new_node); + if (info->old_node->symbol.force_output) + ipa_tm_mark_force_output_node (new_node); return false; } @@ -4381,8 +4381,8 @@ ipa_tm_create_version (struct cgraph_node *old_node) record_tm_clone_pair (old_decl, new_decl); cgraph_call_function_insertion_hooks (new_node); - if (old_node->needed) - ipa_tm_mark_needed_node (new_node); + if (old_node->symbol.force_output) + ipa_tm_mark_force_output_node (new_node); /* Do the same thing, but for any aliases of the original node. */ { diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index a385c21..d0710c0 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1755,7 +1755,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, producing dead clone (for further cloning). In all other cases we hit a bug (incorrect node sharing is the most common reason for missing edges). */ - gcc_assert (dest->needed || !dest->analyzed + gcc_assert (!dest->analyzed || dest->symbol.address_taken || !id->src_node->analyzed || !id->dst_node->analyzed); diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 28d2312..09642a0 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -6928,7 +6928,7 @@ ipa_pta_execute (void) constraints for parameters. */ if (node->symbol.used_from_other_partition || node->symbol.externally_visible - || node->needed) + || node->symbol.force_output) { intra_create_variable_infos (); diff --git a/gcc/varasm.c b/gcc/varasm.c index dbcb1bf..d506b31 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -2249,7 +2249,7 @@ mark_decl_referenced (tree decl) struct cgraph_node *node = cgraph_get_create_node (decl); if (!DECL_EXTERNAL (decl) && !node->local.finalized) - cgraph_mark_needed_node (node); + cgraph_mark_force_output_node (node); } else if (TREE_CODE (decl) == VAR_DECL) { @@ -2257,7 +2257,7 @@ mark_decl_referenced (tree decl) varpool_mark_needed_node (node); /* C++ frontend use mark_decl_references to force COMDAT variables to be output that might appear dead otherwise. */ - node->force_output = true; + node->symbol.force_output = true; } /* else do nothing - we can get various sorts of CST nodes here, which do not need to be marked. */ @@ -5271,13 +5271,20 @@ weak_finish_1 (tree decl) #endif } +/* Fiven an assembly name, find the decl it is associated with. */ +static tree +find_decl (tree target) +{ + symtab_node node = symtab_node_for_asm (target); + if (node) + return node->symbol.decl; + return NULL_TREE; +} + /* This TREE_LIST contains weakref targets. */ static GTY(()) tree weakref_targets; -/* Forward declaration. */ -static tree find_decl_and_mark_needed (tree decl, tree target); - /* Emit any pending weak declarations. */ void @@ -5303,7 +5310,7 @@ weak_finish (void) # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target)); # else - tree decl = find_decl_and_mark_needed (alias_decl, target); + tree decl = find_decl (target); if (! decl) { @@ -5406,43 +5413,6 @@ globalize_decl (tree decl) VEC(alias_pair,gc) *alias_pairs; -/* Given an assembly name, find the decl it is associated with. At the - same time, mark it needed for cgraph. */ - -static tree -find_decl_and_mark_needed (tree decl, tree target) -{ - struct cgraph_node *fnode = NULL; - struct varpool_node *vnode = NULL; - - if (TREE_CODE (decl) == FUNCTION_DECL) - { - fnode = cgraph_node_for_asm (target); - if (fnode == NULL) - vnode = varpool_node_for_asm (target); - } - else - { - vnode = varpool_node_for_asm (target); - if (vnode == NULL) - fnode = cgraph_node_for_asm (target); - } - - if (fnode) - { - cgraph_mark_needed_node (fnode); - return fnode->symbol.decl; - } - else if (vnode) - { - varpool_mark_needed_node (vnode); - vnode->force_output = 1; - return vnode->symbol.decl; - } - else - return NULL_TREE; -} - /* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF or ASM_OUTPUT_DEF_FROM_DECLS. The function defines the symbol whose tree node is DECL to have the value of the tree node TARGET. */ @@ -5748,7 +5718,7 @@ finish_aliases_1 (void) { tree target_decl; - target_decl = find_decl_and_mark_needed (p->decl, p->target); + target_decl = find_decl (p->target); if (target_decl == NULL) { if (symbol_alias_set_contains (defined, p->target)) @@ -5854,7 +5824,7 @@ assemble_alias (tree decl, tree target) /* If the target has already been emitted, we don't have to queue the alias. This saves a tad of memory. */ if (cgraph_global_info_ready) - target_decl = find_decl_and_mark_needed (decl, target); + target_decl = find_decl (target); else target_decl= NULL; if (target_decl && TREE_ASM_WRITTEN (target_decl)) @@ -5960,12 +5930,12 @@ dump_tm_clone_pairs (VEC(tm_alias_pair,heap) *tm_alias_pairs) TM_GETTMCLONE. If neither of these are true, we didn't generate a clone, and we didn't call it indirectly... no sense keeping it in the clone table. */ - if (!dst_n || !dst_n->needed) + if (!dst_n || !dst_n->analyzed) continue; /* This covers the case where we have optimized the original function away, and only access the transactional clone. */ - if (!src_n || !src_n->needed) + if (!src_n || !src_n->analyzed) continue; if (!switched) diff --git a/gcc/varpool.c b/gcc/varpool.c index 5748eff..2423ee8 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -214,7 +214,7 @@ bool decide_is_variable_needed (struct varpool_node *node, tree decl) { /* If the user told us it is used, then it must be so. */ - if (node->force_output) + if (node->symbol.force_output) return true; gcc_assert (!DECL_EXTERNAL (decl)); @@ -298,7 +298,7 @@ varpool_finalize_decl (tree decl) optimizing and when not doing toplevel reoder. */ || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl) && !DECL_ARTIFICIAL (node->symbol.decl))) - node->force_output = true; + node->symbol.force_output = true; if (decide_is_variable_needed (node, decl)) varpool_mark_needed_node (node); @@ -410,6 +410,7 @@ varpool_analyze_pending_decls (void) } } } + varpool_mark_needed_node (tgt); } else if (DECL_INITIAL (decl)) record_references_in_initializer (decl, analyzed); @@ -621,8 +622,7 @@ varpool_create_variable_alias (tree alias, tree decl) gcc_assert (TREE_CODE (alias) == VAR_DECL); alias_node = varpool_node (alias); alias_node->alias = 1; - if (!DECL_EXTERNAL (alias)) - alias_node->finalized = 1; + alias_node->finalized = 1; alias_node->alias_of = decl; if ((!DECL_EXTERNAL (alias) && decide_is_variable_needed (alias_node, alias)) -- 2.7.4