Hi, I went through the visibility code and update it for incremental linking. On few places we now need to take into account the fact that next round of static linking may remove whole sections, common symbols and comdats. Also we can't assume that hidden symbols have unique name as we do not know what extra hidden symbols will be introduced later.
Bootstrapped/regtested x86_64-linux, will commit it shortly. Honza * cgraph.c (cgraph_node::make_local): No name is unique during incremental linking. * cgraph.h (can_be_discarded_p): Update comment; also common and WEAK in named sections can be discarded; when doing incremental link do not rely on resolution being the final one. * varasm.c (default_binds_local_p_3, decl_binds_to_current_def_p): When symbol can be discarded, do not rely on resolution info. * symtab.c (symtab_node::nonzero_address): Take into account that symbol can be discarded. * ipa-visibility.c (update_visibility_by_resolution_info): Handle definition correctly. (function_and_variable_visibility): Do not set unique_name when incrementally linking. Index: varasm.c =================================================================== --- varasm.c (revision 231020) +++ varasm.c (working copy) @@ -6837,7 +6837,9 @@ default_binds_local_p_3 (const_tree exp, { if (node->in_other_partition) defined_locally = true; - if (resolution_to_local_definition_p (node->resolution)) + if (flag_incremental_link && node->can_be_discarded_p ()) + ; + else if (resolution_to_local_definition_p (node->resolution)) defined_locally = resolved_locally = true; else if (resolution_local_p (node->resolution)) resolved_locally = true; @@ -6930,7 +6932,8 @@ decl_binds_to_current_def_p (const_tree /* When resolution is available, just use it. */ if (symtab_node *node = symtab_node::get (decl)) { - if (node->resolution != LDPR_UNKNOWN) + if (node->resolution != LDPR_UNKNOWN + && (!flag_incremental_link || !node->can_be_discarded_p ())) return resolution_to_local_definition_p (node->resolution); } Index: symtab.c =================================================================== --- symtab.c (revision 231020) +++ symtab.c (working copy) @@ -1713,6 +1713,7 @@ symtab_node::nonzero_address () return true; if (target->resolution != LDPR_UNKNOWN && target->resolution != LDPR_UNDEF + && !target->can_be_discarded_p () && flag_delete_null_pointer_checks) return true; return false; @@ -1751,6 +1752,7 @@ symtab_node::nonzero_address () /* As the last resort, check the resolution info. */ if (resolution != LDPR_UNKNOWN && resolution != LDPR_UNDEF + && !can_be_discarded_p () && flag_delete_null_pointer_checks) return true; return false; Index: ipa-visibility.c =================================================================== --- ipa-visibility.c (revision 231020) +++ ipa-visibility.c (working copy) @@ -413,10 +413,10 @@ update_visibility_by_resolution_info (sy DECL_WEAK (next->decl) = false; next->set_comdat_group (NULL); } - if (next->externally_visible - && !define) + if (!define) { - DECL_EXTERNAL (next->decl) = true; + if (next->externally_visible) + DECL_EXTERNAL (next->decl) = true; next->set_comdat_group (NULL); } } @@ -513,10 +513,10 @@ function_and_variable_visibility (bool w { gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl)); - node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY - || node->unique_name - || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) - && TREE_PUBLIC (node->decl)); + node->unique_name |= ((node->resolution == LDPR_PREVAILING_DEF_IRONLY + || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + && TREE_PUBLIC (node->decl) + && !flag_incremental_link); node->resolution = LDPR_PREVAILING_DEF_IRONLY; if (node->same_comdat_group && TREE_PUBLIC (node->decl)) { @@ -532,10 +532,10 @@ function_and_variable_visibility (bool w if (!next->alias) next->set_section (NULL); next->make_decl_local (); - next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY - || next->unique_name - || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) - && TREE_PUBLIC (next->decl)); + next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY + || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + && TREE_PUBLIC (next->decl) + && !flag_incremental_link); } /* cgraph_externally_visible_p has already checked all other nodes in the group and they will all be made local. We need to @@ -657,10 +657,11 @@ function_and_variable_visibility (bool w && !vnode->weakref) { gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl)); - vnode->unique_name = ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY - || vnode->resolution + vnode->unique_name |= ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY + || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) - && TREE_PUBLIC (vnode->decl)); + && TREE_PUBLIC (vnode->decl) + && !flag_incremental_link); if (vnode->same_comdat_group && TREE_PUBLIC (vnode->decl)) { symtab_node *next = vnode; @@ -675,10 +676,10 @@ function_and_variable_visibility (bool w if (!next->alias) next->set_section (NULL); next->make_decl_local (); - next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY - || next->unique_name - || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) - && TREE_PUBLIC (next->decl)); + next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY + || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + && TREE_PUBLIC (next->decl) + && !flag_incremental_link); } vnode->dissolve_same_comdat_group_list (); } Index: cgraph.c =================================================================== --- cgraph.c (revision 231020) +++ cgraph.c (working copy) @@ -2253,8 +2253,9 @@ cgraph_node::make_local (cgraph_node *no node->forced_by_abi = false; node->local.local = true; node->set_section (NULL); - node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY - || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); + node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY + || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + && !flag_incremental_link); node->resolution = LDPR_PREVAILING_DEF_IRONLY; gcc_assert (node->get_availability () == AVAIL_LOCAL); } Index: cgraph.h =================================================================== --- cgraph.h (revision 231020) +++ cgraph.h (working copy) @@ -319,15 +319,23 @@ public: /* Return true when there are references to the node. */ bool referred_to_p (bool include_self = true); - /* Return true if NODE can be discarded by linker from the binary. */ + /* Return true if symbol can be discarded by linker from the binary. + Assume that symbol is used (so there is no need to take into account + garbage collecting linkers) + + This can happen for comdats, commons and weaks when they are previaled + by other definition at static linking time. */ inline bool can_be_discarded_p (void) { return (DECL_EXTERNAL (decl) - || (get_comdat_group () - && resolution != LDPR_PREVAILING_DEF - && resolution != LDPR_PREVAILING_DEF_IRONLY - && resolution != LDPR_PREVAILING_DEF_IRONLY_EXP)); + || ((get_comdat_group () + || DECL_COMMON (decl) + || (DECL_SECTION_NAME (decl) && DECL_WEAK (decl))) + && ((resolution != LDPR_PREVAILING_DEF + && resolution != LDPR_PREVAILING_DEF_IRONLY_EXP) + || flag_incremental_link) + && resolution != LDPR_PREVAILING_DEF_IRONLY)); } /* Return true if NODE is local to a particular COMDAT group, and must not