Hi, this patch fixes ICE seen when compiling libreoffice with LTO at 4.9 release tree. The problem is that we now use comdat locals for decloned constructors and symtab_remove_unreachable_nodes sometimes remove their bodies but keeps their nodes around.
In this case the nodes needs to be brought out of comdat groups or LTO streaming will mess up the linked list holding them. Bootstrapped/regtested x86_64-linux and tested with libreoffice LTO build will commit it to mainline and release branch shortly. Honza * ipa.c (symtab_remove_unreachable_nodes): Remove symbol from comdat group if its body was eliminated. (comdat_can_be_unshared_p_1): Static symbols can always be privatized. * symtab.c (symtab_remove_from_same_comdat_group): Break out from ... (symtab_unregister_node): ... this one. (verify_symtab_base): More strict checking of comdats. * cgraph.h (symtab_remove_from_same_comdat_group): Declare. Index: ipa.c =================================================================== --- ipa.c (revision 210563) +++ ipa.c (working copy) @@ -517,6 +517,7 @@ symtab_remove_unreachable_nodes (bool be if (!node->in_other_partition) node->local.local = false; cgraph_node_remove_callees (node); + symtab_remove_from_same_comdat_group (node); ipa_remove_all_references (&node->ref_list); changed = true; } @@ -572,6 +573,8 @@ symtab_remove_unreachable_nodes (bool be vnode->analyzed = false; vnode->aux = NULL; + symtab_remove_from_same_comdat_group (vnode); + /* Keep body if it may be useful for constant folding. */ if ((init = ctor_for_folding (vnode->decl)) == error_mark_node) varpool_remove_initializer (vnode); @@ -708,6 +711,8 @@ address_taken_from_non_vtable_p (symtab_ static bool comdat_can_be_unshared_p_1 (symtab_node *node) { + if (!node->externally_visible) + return true; /* When address is taken, we don't know if equality comparison won't break eventually. Exception are virutal functions, C++ constructors/destructors and vtables, where this is not possible by Index: symtab.c =================================================================== --- symtab.c (revision 210563) +++ symtab.c (working copy) @@ -323,16 +323,11 @@ symtab_insert_node_to_hashtable (symtab_ *slot = node; } -/* Remove node from symbol table. This function is not used directly, but via - cgraph/varpool node removal routines. */ +/* Remove NODE from same comdat group. */ void -symtab_unregister_node (symtab_node *node) +symtab_remove_from_same_comdat_group (symtab_node *node) { - void **slot; - ipa_remove_all_references (&node->ref_list); - ipa_remove_all_referring (&node->ref_list); - if (node->same_comdat_group) { symtab_node *prev; @@ -346,6 +341,19 @@ symtab_unregister_node (symtab_node *nod prev->same_comdat_group = node->same_comdat_group; node->same_comdat_group = NULL; } +} + +/* Remove node from symbol table. This function is not used directly, but via + cgraph/varpool node removal routines. */ + +void +symtab_unregister_node (symtab_node *node) +{ + void **slot; + ipa_remove_all_references (&node->ref_list); + ipa_remove_all_referring (&node->ref_list); + + symtab_remove_from_same_comdat_group (node); if (node->previous) node->previous->next = node->next; @@ -829,6 +837,16 @@ verify_symtab_base (symtab_node *node) error ("non-DECL_ONE_ONLY node in a same_comdat_group list"); error_found = true; } + if (DECL_COMDAT_GROUP (n->decl) != DECL_COMDAT_GROUP (node->same_comdat_group->decl)) + { + error ("same_comdat_group list across different groups"); + error_found = true; + } + if (!n->definition) + { + error ("Node has same_comdat_group but it is not a definition"); + error_found = true; + } if (n->type != node->type) { error ("mixing different types of symbol in same comdat groups is not supported"); Index: cgraph.h =================================================================== --- cgraph.h (revision 210563) +++ cgraph.h (working copy) @@ -723,6 +723,7 @@ enum symbol_partitioning_class /* In symtab.c */ void symtab_register_node (symtab_node *); void symtab_unregister_node (symtab_node *); +void symtab_remove_from_same_comdat_group (symtab_node *); void symtab_remove_node (symtab_node *); symtab_node *symtab_get_node (const_tree); symtab_node *symtab_node_for_asm (const_tree asmname); Index: gimple-fold.c =================================================================== --- gimple-fold.c (revision 210563) +++ gimple-fold.c (working copy) @@ -105,7 +105,9 @@ can_refer_decl_in_current_unit_p (tree d external var. */ if (!from_decl || TREE_CODE (from_decl) != VAR_DECL - || !DECL_EXTERNAL (from_decl) + || (!DECL_EXTERNAL (from_decl) + && (vnode = varpool_get_node (from_decl)) != NULL + && vnode->definition) || (flag_ltrans && symtab_get_node (from_decl)->in_other_partition)) return true;