Patchwork Rewrite lto-symtab to work on symbol table

login
register
mail settings
Submitter Richard Guenther
Date Sept. 18, 2012, 2:43 p.m.
Message ID <alpine.LNX.2.00.1209181639310.28649@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/184748/
State New
Headers show

Comments

Richard Guenther - Sept. 18, 2012, 2:43 p.m.
On Tue, 18 Sep 2012, Jan Hubicka wrote:

> Hi,
> this patch reorganize lto-symtab to work across symtab's symbol table instead
> of building its own.  This simplifies things a bit and with the previous
> changes it is rather straighforward - i.e. replace all uses of
> lto_symtab_entry_t by symtab_node.
> 
> There are few differences in between the symtab as built by lto-symtab and
> our symbol table.  In one direction the declarations that are not going to be
> output to final assembly (i.e. are used by debug info and such) are not in 
> symbol table and consequentely they no longer get merged.  I think this is fine.

Yes, that sounds fine.

> Other difference is that symbol table contains some symbols that are not really
> symbols in classical definition - such as inline clones or functions held in
> table only for purposes of materialization.  I added symtab_real_symbol_p
> predicate for this.  It would make more sense to exclude those from the
> assembler name hash and drop checks I added to lto-symtab.c.

Yes indeed.  I also miss a function to compute said hash to be able
to travers the next/prev asm name alias chain.  Also the current
routine to do that computes assembler names for things that did not
have one ...

> I plan to work on
> this incrementally - it is not completely trivial. The symbol can become
> non-real in several ways and it will need bit of work to get this consistent.
> 
> Bootstrapped/regtested x86_64-linux, tested by building Mozilla, Qt and other
> stuff with LTO. OK?

I also have in my local tree:

seems that path is not exercised in the current tree ;)

Ok for trunk.

Thanks,
Richard.

> Honza
> 
> 	* symtab.c (insert_to_assembler_name_hash): Do not insert
> 	register vars.
> 	(unlink_from_assembler_name_hash): NULL out pointers of unlinked
> 	var.
> 	(symtab_prevail_in_asm_name_hash): New.
> 	(symtab_initialize_asm_name_hash): Break out from ...
> 	(symtab_node_for_asm): ... here.
> 	(dump_symtab_base): Dump LTO file data.
> 	(verify_symtab_base): Register vars are not in symtab.
> 	* cgraph.h (symtab_initialize_asm_name_hash,
> 	symtab_prevail_in_asm_name_hash): New functions.
> 	(symtab_real_symbol_p): New inline.
> 	* lto-symtab.c: Do not include gt-lto-symtab.h.
> 	(lto_symtab_entry_def): Remove.
> 	(lto_symtab_entry_t): Remove.
> 	(lto_symtab_identifiers): Remove.
> 	(lto_symtab_free): Remove.
> 	(lto_symtab_entry_hash): Remove.
> 	(lto_symtab_entry_eq): Remove.
> 	(lto_symtab_entry_marked_p): Remove.
> 	(lto_symtab_maybe_init_hash_table): Remove.
> 	(resolution_guessed_p, set_resolution_guessed): New functions.
> 	(lto_symtab_register_decl): Only set resolution info.
> 	(lto_symtab_get, lto_symtab_get_resolution): Remove.
> 	(lto_symtab_merge): Reorg to work across symtab; do nothing if decls
> 	are same.
> 	(lto_symtab_resolve_replaceable_p): Reorg to work on symtab.
> 	(lto_symtab_resolve_can_prevail_p): Likewise; only real symbols can
> 	prevail.
> 	(lto_symtab_resolve_symbols): Reorg to work on symtab.
> 	(lto_symtab_merge_decls_2): Likewise.
> 	(lto_symtab_merge_decls_1): Likewise; add debug dumps.
> 	(lto_symtab_merge_decls): Likewise; do not merge at ltrans stage.
> 	(lto_symtab_merge_cgraph_nodes_1): Reorg to work on symtab.
> 	(lto_symtab_merge_cgraph_nodes): Likewise; do not merge at ltrans stage.
> 	(lto_symtab_prevailing_decl): Rewrite to lookup into symtab.
> 	* lto-streaer.h (lto_symtab_free): Remove.
> 	* lto-cgraph.c (add_references): Cleanup.
> 	* varpool.c (varpool_assemble_decl): Skip hard regs.
> 
> 	* lto.c (lto_materialize_function): Update confused comment.
> 	(read_cgraph_and_symbols): Do not free symtab.
> Index: symtab.c
> ===================================================================
> *** symtab.c	(revision 191418)
> --- symtab.c	(working copy)
> *************** eq_assembler_name (const void *p1, const
> *** 104,109 ****
> --- 104,111 ----
>   static void
>   insert_to_assembler_name_hash (symtab_node node)
>   {
> +   if (symtab_variable_p (node) && DECL_HARD_REGISTER (node->symbol.decl))
> +     return;
>     gcc_checking_assert (!node->symbol.previous_sharing_asm_name
>   		       && !node->symbol.next_sharing_asm_name);
>     if (assembler_name_hash)
> *************** unlink_from_assembler_name_hash (symtab_
> *** 151,159 ****
> --- 153,172 ----
>   	  else
>   	    *slot = node->symbol.next_sharing_asm_name;
>   	}
> +       node->symbol.next_sharing_asm_name = NULL;
> +       node->symbol.previous_sharing_asm_name = NULL;
>       }
>   }
>   
> + /* Arrange node to be first in its entry of assembler_name_hash.  */
> + 
> + void
> + symtab_prevail_in_asm_name_hash (symtab_node node)
> + {
> +   unlink_from_assembler_name_hash (node);
> +   insert_to_assembler_name_hash (node);
> + }
> + 
>   
>   /* Add node into symbol table.  This function is not used directly, but via
>      cgraph/varpool node creation routines.  */
> *************** symtab_remove_node (symtab_node node)
> *** 287,301 ****
>       varpool_remove_node (varpool (node));
>   }
>   
> ! /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
> !    Return NULL if there's no such node.  */
>   
> ! symtab_node
> ! symtab_node_for_asm (const_tree asmname)
>   {
>     symtab_node node;
> -   void **slot;
> - 
>     if (!assembler_name_hash)
>       {
>         assembler_name_hash =
> --- 300,311 ----
>       varpool_remove_node (varpool (node));
>   }
>   
> ! /* Initalize asm name hash unless.  */
>   
> ! void
> ! symtab_initialize_asm_name_hash (void)
>   {
>     symtab_node node;
>     if (!assembler_name_hash)
>       {
>         assembler_name_hash =
> *************** symtab_node_for_asm (const_tree asmname)
> *** 304,310 ****
> --- 314,331 ----
>         FOR_EACH_SYMBOL (node)
>   	insert_to_assembler_name_hash (node);
>       }
> + }
>   
> + /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
> +    Return NULL if there's no such node.  */
> + 
> + symtab_node
> + symtab_node_for_asm (const_tree asmname)
> + {
> +   symtab_node node;
> +   void **slot;
> + 
> +   symtab_initialize_asm_name_hash ();
>     slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
>   				   decl_assembler_name_hash (asmname),
>   				   NO_INSERT);
> *************** dump_symtab_base (FILE *f, symtab_node n
> *** 507,512 ****
> --- 528,536 ----
>     ipa_dump_references (f, &node->symbol.ref_list);
>     fprintf (f, "  Referring: ");
>     ipa_dump_referring (f, &node->symbol.ref_list);
> +   if (node->symbol.lto_file_data)
> +     fprintf (f, "  Read from file: %s\n",
> + 	     node->symbol.lto_file_data->file_name);
>   }
>   
>   /* Dump symtab node.  */
> *************** verify_symtab_base (symtab_node node)
> *** 597,603 ****
>   	    break;
>   	  hashed_node = hashed_node->symbol.next_sharing_asm_name;
>   	}
> !       if (!hashed_node)
>   	{
>             error ("node not found in symtab assembler name hash");
>             error_found = true;
> --- 621,628 ----
>   	    break;
>   	  hashed_node = hashed_node->symbol.next_sharing_asm_name;
>   	}
> !       if (!hashed_node
> !           && !(symtab_variable_p (node) || DECL_HARD_REGISTER (node->symbol.decl)))
>   	{
>             error ("node not found in symtab assembler name hash");
>             error_found = true;
> *************** symtab_make_decl_local (tree decl)
> *** 733,738 ****
> --- 758,765 ----
>     DECL_COMDAT_GROUP (decl) = 0;
>     DECL_WEAK (decl) = 0;
>     DECL_EXTERNAL (decl) = 0;
> +   DECL_VISIBILITY_SPECIFIED (decl) = 0;
> +   DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
>     TREE_PUBLIC (decl) = 0;
>     DECL_VISIBILITY_SPECIFIED (decl) = 0;
>     DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
> Index: cgraph.h
> ===================================================================
> *** cgraph.h	(revision 191418)
> --- cgraph.h	(working copy)
> *************** bool varpool_for_node_and_aliases (struc
> *** 704,709 ****
> --- 704,711 ----
>   		                   bool (*) (struct varpool_node *, void *),
>   			           void *, bool);
>   void varpool_add_new_variable (tree);
> + void symtab_initialize_asm_name_hash (void);
> + void symtab_prevail_in_asm_name_hash (symtab_node node);
>   
>   /* Return true when NODE is function.  */
>   static inline bool
> *************** cgraph_mark_force_output_node (struct cg
> *** 1309,1312 ****
> --- 1311,1337 ----
>     gcc_checking_assert (!node->global.inlined_to);
>   }
>   
> + /* Return true when the symbol is real symbol, i.e. it is not inline clone
> +    or extern function kept around just for inlining.  */
> + 
> + static inline bool
> + symtab_real_symbol_p (symtab_node node)
> + {
> +   struct cgraph_node *cnode;
> +   struct ipa_ref *ref;
> + 
> +   if (!symtab_function_p (node))
> +     return true;
> +   cnode = cgraph (node);
> +   if (cnode->global.inlined_to)
> +     return false;
> +   if (cnode->abstract_and_needed)
> +     return false;
> +   /* We keep virtual clones in symtab.  */
> +   if (!cnode->analyzed
> +       || DECL_EXTERNAL (cnode->symbol.decl))
> +     return (cnode->callers
> + 	    || ipa_ref_list_referring_iterate (&cnode->symbol.ref_list, 0, ref));
> +   return true;
> + }
>   #endif  /* GCC_CGRAPH_H  */
> Index: lto-symtab.c
> ===================================================================
> *** lto-symtab.c	(revision 191418)
> --- lto-symtab.c	(working copy)
> *************** along with GCC; see the file COPYING3.
> *** 32,129 ****
>   /* Vector to keep track of external variables we've seen so far.  */
>   VEC(tree,gc) *lto_global_var_decls;
>   
> ! /* Symbol table entry.  */
> ! 
> ! struct GTY(()) lto_symtab_entry_def
> ! {
> !   /* The symbol table entry key, an IDENTIFIER.  */
> !   tree id;
> !   /* The symbol table entry, a DECL.  */
> !   tree decl;
> !   /* The cgraph node if decl is a function decl.  Filled in during the
> !      merging process.  */
> !   struct cgraph_node *node;
> !   /* The varpool node if decl is a variable decl.  Filled in during the
> !      merging process.  */
> !   struct varpool_node *vnode;
> !   /* LTO file-data and symbol resolution for this decl.  */
> !   struct lto_file_decl_data * GTY((skip (""))) file_data;
> !   enum ld_plugin_symbol_resolution resolution;
> !   /* True when resolution was guessed and not read from the file.  */
> !   bool guessed;
> !   /* Pointer to the next entry with the same key.  Before decl merging
> !      this links all symbols from the different TUs.  After decl merging
> !      this links merged but incompatible decls, thus all prevailing ones
> !      remaining.  */
> !   struct lto_symtab_entry_def *next;
> ! };
> ! typedef struct lto_symtab_entry_def *lto_symtab_entry_t;
> ! 
> ! /* A poor man's symbol table. This hashes identifier to prevailing DECL
> !    if there is one. */
> ! 
> ! static GTY ((if_marked ("lto_symtab_entry_marked_p"),
> ! 	     param_is (struct lto_symtab_entry_def)))
> !   htab_t lto_symtab_identifiers;
> ! 
> ! /* Free symtab hashtable.  */
> ! 
> ! void
> ! lto_symtab_free (void)
> ! {
> !   htab_delete (lto_symtab_identifiers);
> !   lto_symtab_identifiers = NULL;
> ! }
> ! 
> ! /* Return the hash value of an lto_symtab_entry_t object pointed to by P.  */
> ! 
> ! static hashval_t
> ! lto_symtab_entry_hash (const void *p)
>   {
> !   const struct lto_symtab_entry_def *base =
> !     (const struct lto_symtab_entry_def *) p;
> !   return IDENTIFIER_HASH_VALUE (base->id);
>   }
>   
> ! /* Return non-zero if P1 and P2 points to lto_symtab_entry_def structs
> !    corresponding to the same symbol.  */
> ! 
> ! static int
> ! lto_symtab_entry_eq (const void *p1, const void *p2)
> ! {
> !   const struct lto_symtab_entry_def *base1 =
> !      (const struct lto_symtab_entry_def *) p1;
> !   const struct lto_symtab_entry_def *base2 =
> !      (const struct lto_symtab_entry_def *) p2;
> !   return (base1->id == base2->id);
> ! }
> ! 
> ! /* Returns non-zero if P points to an lto_symtab_entry_def struct that needs
> !    to be marked for GC.  */
> ! 
> ! static int
> ! lto_symtab_entry_marked_p (const void *p)
>   {
> !   const struct lto_symtab_entry_def *base =
> !      (const struct lto_symtab_entry_def *) p;
> ! 
> !   /* Keep this only if the common IDENTIFIER_NODE of the symtab chain
> !      is marked which it will be if at least one of the DECLs in the
> !      chain is marked.  */
> !   return ggc_marked_p (base->id);
> ! }
> ! 
> ! /* Lazily initialize resolution hash tables.  */
> ! 
> ! static void
> ! lto_symtab_maybe_init_hash_table (void)
> ! {
> !   if (lto_symtab_identifiers)
> !     return;
> ! 
> !   lto_symtab_identifiers =
> !     htab_create_ggc (1021, lto_symtab_entry_hash,
> ! 		     lto_symtab_entry_eq, NULL);
>   }
>   
>   /* Registers DECL with the LTO symbol table as having resolution RESOLUTION
> --- 32,50 ----
>   /* Vector to keep track of external variables we've seen so far.  */
>   VEC(tree,gc) *lto_global_var_decls;
>   
> ! /* Return true if the resolution was guessed and not obtained from
> !    the file.  */
> ! static inline bool
> ! resolution_guessed_p (symtab_node node)
>   {
> !   return node->symbol.aux != NULL;
>   }
>   
> ! /* Set guessed flag for NODE.  */
> ! static inline void
> ! set_resolution_guessed (symtab_node node, bool value)
>   {
> !   node->symbol.aux = (void *)(size_t)value;
>   }
>   
>   /* Registers DECL with the LTO symbol table as having resolution RESOLUTION
> *************** lto_symtab_register_decl (tree decl,
> *** 134,141 ****
>   			  ld_plugin_symbol_resolution_t resolution,
>   			  struct lto_file_decl_data *file_data)
>   {
> !   lto_symtab_entry_t new_entry;
> !   void **slot;
>   
>     /* Check that declarations reaching this function do not have
>        properties inconsistent with having external linkage.  If any of
> --- 55,61 ----
>   			  ld_plugin_symbol_resolution_t resolution,
>   			  struct lto_file_decl_data *file_data)
>   {
> !   symtab_node node;
>   
>     /* Check that declarations reaching this function do not have
>        properties inconsistent with having external linkage.  If any of
> *************** lto_symtab_register_decl (tree decl,
> *** 153,206 ****
>     if (TREE_CODE (decl) == FUNCTION_DECL)
>       gcc_assert (!DECL_ABSTRACT (decl));
>   
> !   new_entry = ggc_alloc_cleared_lto_symtab_entry_def ();
> !   new_entry->id = (*targetm.asm_out.mangle_assembler_name)
> ! 		  (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
> !   new_entry->decl = decl;
> !   new_entry->resolution = resolution;
> !   new_entry->file_data = file_data;
> ! 
> !   lto_symtab_maybe_init_hash_table ();
> !   slot = htab_find_slot (lto_symtab_identifiers, new_entry, INSERT);
> !   new_entry->next = (lto_symtab_entry_t) *slot;
> !   *slot = new_entry;
> ! }
> ! 
> ! /* Get the lto_symtab_entry_def struct associated with ID
> !    if there is one.  */
> ! 
> ! static lto_symtab_entry_t
> ! lto_symtab_get (tree id)
> ! {
> !   struct lto_symtab_entry_def temp;
> !   void **slot;
> ! 
> !   lto_symtab_maybe_init_hash_table ();
> !   temp.id = id;
> !   slot = htab_find_slot (lto_symtab_identifiers, &temp, NO_INSERT);
> !   return slot ? (lto_symtab_entry_t) *slot : NULL;
> ! }
> ! 
> ! /* Get the linker resolution for DECL.  */
> ! 
> ! enum ld_plugin_symbol_resolution
> ! lto_symtab_get_resolution (tree decl)
> ! {
> !   lto_symtab_entry_t e;
> ! 
> !   gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
> ! 
> !   e = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
> ! 		      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
> !   while (e && e->decl != decl)
> !     e = e->next;
> !   if (!e)
> !     return LDPR_UNKNOWN;
> ! 
> !   return e->resolution;
>   }
>   
> - 
>   /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
>      all edges and removing the old node.  */
>   
> --- 73,87 ----
>     if (TREE_CODE (decl) == FUNCTION_DECL)
>       gcc_assert (!DECL_ABSTRACT (decl));
>   
> !   node = symtab_get_node (decl);
> !   if (node)
> !     {
> !       node->symbol.resolution = resolution;
> !       gcc_assert (node->symbol.lto_file_data == file_data);
> !       gcc_assert (!resolution_guessed_p (node));
> !     }
>   }
>   
>   /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging
>      all edges and removing the old node.  */
>   
> *************** lto_varpool_replace_node (struct varpool
> *** 277,288 ****
>      should be emitted.  */
>   
>   static bool
> ! lto_symtab_merge (lto_symtab_entry_t prevailing, lto_symtab_entry_t entry)
>   {
> !   tree prevailing_decl = prevailing->decl;
> !   tree decl = entry->decl;
>     tree prevailing_type, type;
>   
>     /* Merge decl state in both directions, we may still end up using
>        the new decl.  */
>     TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
> --- 158,172 ----
>      should be emitted.  */
>   
>   static bool
> ! lto_symtab_merge (symtab_node prevailing, symtab_node entry)
>   {
> !   tree prevailing_decl = prevailing->symbol.decl;
> !   tree decl = entry->symbol.decl;
>     tree prevailing_type, type;
>   
> +   if (prevailing_decl == decl)
> +     return true;
> + 
>     /* Merge decl state in both directions, we may still end up using
>        the new decl.  */
>     TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl);
> *************** lto_symtab_merge (lto_symtab_entry_t pre
> *** 377,393 ****
>      entry.  */
>   
>   static bool
> ! lto_symtab_resolve_replaceable_p (lto_symtab_entry_t e)
>   {
> !   if (DECL_EXTERNAL (e->decl)
> !       || DECL_COMDAT (e->decl)
> !       || DECL_ONE_ONLY (e->decl)
> !       || DECL_WEAK (e->decl))
>       return true;
>   
> !   if (TREE_CODE (e->decl) == VAR_DECL)
> !     return (DECL_COMMON (e->decl)
> ! 	    || (!flag_no_common && !DECL_INITIAL (e->decl)));
>   
>     return false;
>   }
> --- 261,277 ----
>      entry.  */
>   
>   static bool
> ! lto_symtab_resolve_replaceable_p (symtab_node e)
>   {
> !   if (DECL_EXTERNAL (e->symbol.decl)
> !       || DECL_COMDAT (e->symbol.decl)
> !       || DECL_ONE_ONLY (e->symbol.decl)
> !       || DECL_WEAK (e->symbol.decl))
>       return true;
>   
> !   if (TREE_CODE (e->symbol.decl) == VAR_DECL)
> !     return (DECL_COMMON (e->symbol.decl)
> ! 	    || (!flag_no_common && !DECL_INITIAL (e->symbol.decl)));
>   
>     return false;
>   }
> *************** lto_symtab_resolve_replaceable_p (lto_sy
> *** 395,418 ****
>   /* Return true if the symtab entry E can be the prevailing one.  */
>   
>   static bool
> ! lto_symtab_resolve_can_prevail_p (lto_symtab_entry_t e)
>   {
>     /* The C++ frontend ends up neither setting TREE_STATIC nor
>        DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
>        So do not reject !TREE_STATIC here but only DECL_EXTERNAL.  */
> !   if (DECL_EXTERNAL (e->decl))
>       return false;
>   
>     /* For functions we need a non-discarded body.  */
> !   if (TREE_CODE (e->decl) == FUNCTION_DECL)
> !     return (e->node && e->node->analyzed);
>   
> !   else if (TREE_CODE (e->decl) == VAR_DECL)
> !     {
> !       if (!e->vnode)
> ! 	return false;
> !       return e->vnode->finalized;
> !     }
>   
>     gcc_unreachable ();
>   }
> --- 279,301 ----
>   /* Return true if the symtab entry E can be the prevailing one.  */
>   
>   static bool
> ! lto_symtab_resolve_can_prevail_p (symtab_node e)
>   {
> +   if (!symtab_real_symbol_p (e))
> +     return false;
> + 
>     /* The C++ frontend ends up neither setting TREE_STATIC nor
>        DECL_EXTERNAL on virtual methods but only TREE_PUBLIC.
>        So do not reject !TREE_STATIC here but only DECL_EXTERNAL.  */
> !   if (DECL_EXTERNAL (e->symbol.decl))
>       return false;
>   
>     /* For functions we need a non-discarded body.  */
> !   if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
> !     return (cgraph (e)->analyzed);
>   
> !   else if (TREE_CODE (e->symbol.decl) == VAR_DECL)
> !     return varpool (e)->finalized;
>   
>     gcc_unreachable ();
>   }
> *************** lto_symtab_resolve_can_prevail_p (lto_sy
> *** 421,443 ****
>      their resolutions.  */
>   
>   static void
> ! lto_symtab_resolve_symbols (void **slot)
>   {
> !   lto_symtab_entry_t e;
> !   lto_symtab_entry_t prevailing = NULL;
>   
>     /* Always set e->node so that edges are updated to reflect decl merging. */
> !   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
> !     {
> !       if (TREE_CODE (e->decl) == FUNCTION_DECL)
> ! 	e->node = cgraph_get_node (e->decl);
> !       else if (TREE_CODE (e->decl) == VAR_DECL)
> ! 	e->vnode = varpool_get_node (e->decl);
> !       if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
> ! 	  || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> ! 	  || e->resolution == LDPR_PREVAILING_DEF)
> ! 	prevailing = e;
> !     }
>   
>     /* If the chain is already resolved there is nothing else to do.  */
>     if (prevailing)
> --- 304,321 ----
>      their resolutions.  */
>   
>   static void
> ! lto_symtab_resolve_symbols (symtab_node first)
>   {
> !   symtab_node e;
> !   symtab_node prevailing = NULL;
>   
>     /* Always set e->node so that edges are updated to reflect decl merging. */
> !   for (e = first; e; e = e->symbol.next_sharing_asm_name)
> !     if (symtab_real_symbol_p (e)
> ! 	&& (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
> ! 	    || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> ! 	    || e->symbol.resolution == LDPR_PREVAILING_DEF))
> !       prevailing = e;
>   
>     /* If the chain is already resolved there is nothing else to do.  */
>     if (prevailing)
> *************** lto_symtab_resolve_symbols (void **slot)
> *** 445,470 ****
>   
>     /* Find the single non-replaceable prevailing symbol and
>        diagnose ODR violations.  */
> !   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
>       {
>         if (!lto_symtab_resolve_can_prevail_p (e))
>   	{
> ! 	  e->resolution = LDPR_RESOLVED_IR;
> !           e->guessed = true;
>   	  continue;
>   	}
>   
>         /* Set a default resolution - the final prevailing one will get
>            adjusted later.  */
> !       e->resolution = LDPR_PREEMPTED_IR;
> !       e->guessed = true;
>         if (!lto_symtab_resolve_replaceable_p (e))
>   	{
>   	  if (prevailing)
>   	    {
> ! 	      error_at (DECL_SOURCE_LOCATION (e->decl),
> ! 			"%qD has already been defined", e->decl);
> ! 	      inform (DECL_SOURCE_LOCATION (prevailing->decl),
>   		      "previously defined here");
>   	    }
>   	  prevailing = e;
> --- 323,348 ----
>   
>     /* Find the single non-replaceable prevailing symbol and
>        diagnose ODR violations.  */
> !   for (e = first; e; e = e->symbol.next_sharing_asm_name)
>       {
>         if (!lto_symtab_resolve_can_prevail_p (e))
>   	{
> ! 	  e->symbol.resolution = LDPR_RESOLVED_IR;
> !           set_resolution_guessed (e, true);
>   	  continue;
>   	}
>   
>         /* Set a default resolution - the final prevailing one will get
>            adjusted later.  */
> !       e->symbol.resolution = LDPR_PREEMPTED_IR;
> !       set_resolution_guessed (e, true);
>         if (!lto_symtab_resolve_replaceable_p (e))
>   	{
>   	  if (prevailing)
>   	    {
> ! 	      error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
> ! 			"%qD has already been defined", e->symbol.decl);
> ! 	      inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
>   		      "previously defined here");
>   	    }
>   	  prevailing = e;
> *************** lto_symtab_resolve_symbols (void **slot)
> *** 474,486 ****
>       goto found;
>   
>     /* Do a second round choosing one from the replaceable prevailing decls.  */
> !   for (e = (lto_symtab_entry_t) *slot; e; e = e->next)
>       {
> !       if (e->resolution != LDPR_PREEMPTED_IR)
>   	continue;
>   
>         /* Choose the first function that can prevail as prevailing.  */
> !       if (TREE_CODE (e->decl) == FUNCTION_DECL)
>   	{
>   	  prevailing = e;
>   	  break;
> --- 352,365 ----
>       goto found;
>   
>     /* Do a second round choosing one from the replaceable prevailing decls.  */
> !   for (e = first; e; e = e->symbol.next_sharing_asm_name)
>       {
> !       if (e->symbol.resolution != LDPR_PREEMPTED_IR
> ! 	  || !symtab_real_symbol_p (e))
>   	continue;
>   
>         /* Choose the first function that can prevail as prevailing.  */
> !       if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL)
>   	{
>   	  prevailing = e;
>   	  break;
> *************** lto_symtab_resolve_symbols (void **slot)
> *** 488,495 ****
>   
>         /* From variables that can prevail choose the largest one.  */
>         if (!prevailing
> ! 	  || tree_int_cst_lt (DECL_SIZE (prevailing->decl),
> ! 			      DECL_SIZE (e->decl))
>   	  /* When variables are equivalent try to chose one that has useful
>   	     DECL_INITIAL.  This makes sense for keyed vtables that are
>   	     DECL_EXTERNAL but initialized.  In units that do not need them
> --- 367,374 ----
>   
>         /* From variables that can prevail choose the largest one.  */
>         if (!prevailing
> ! 	  || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl),
> ! 			      DECL_SIZE (e->symbol.decl))
>   	  /* When variables are equivalent try to chose one that has useful
>   	     DECL_INITIAL.  This makes sense for keyed vtables that are
>   	     DECL_EXTERNAL but initialized.  In units that do not need them
> *************** lto_symtab_resolve_symbols (void **slot)
> *** 499,509 ****
>   	     We know that the vtable is keyed outside the LTO unit - otherwise
>   	     the keyed instance would prevail.  We still can preserve useful
>   	     info in the initializer.  */
> ! 	  || (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl)
> ! 	      && (DECL_INITIAL (e->decl)
> ! 		  && DECL_INITIAL (e->decl) != error_mark_node)
> ! 	      && (!DECL_INITIAL (prevailing->decl)
> ! 		  || DECL_INITIAL (prevailing->decl) == error_mark_node)))
>   	prevailing = e;
>       }
>   
> --- 378,388 ----
>   	     We know that the vtable is keyed outside the LTO unit - otherwise
>   	     the keyed instance would prevail.  We still can preserve useful
>   	     info in the initializer.  */
> ! 	  || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl)
> ! 	      && (DECL_INITIAL (e->symbol.decl)
> ! 		  && DECL_INITIAL (e->symbol.decl) != error_mark_node)
> ! 	      && (!DECL_INITIAL (prevailing->symbol.decl)
> ! 		  || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node)))
>   	prevailing = e;
>       }
>   
> *************** found:
> *** 524,531 ****
>       variables IRONLY, which are indeed PREVAILING_DEF in
>       resolution file.  These variables still need manual
>       externally_visible attribute.  */
> !     prevailing->resolution = LDPR_PREVAILING_DEF_IRONLY;
> !     prevailing->guessed = true;
>   }
>   
>   /* Merge all decls in the symbol table chain to the prevailing decl and
> --- 403,410 ----
>       variables IRONLY, which are indeed PREVAILING_DEF in
>       resolution file.  These variables still need manual
>       externally_visible attribute.  */
> !     prevailing->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
> !     set_resolution_guessed (prevailing, true);
>   }
>   
>   /* Merge all decls in the symbol table chain to the prevailing decl and
> *************** found:
> *** 533,556 ****
>      do not issue further diagnostics.*/
>   
>   static void
> ! lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p)
>   {
> !   lto_symtab_entry_t prevailing, e;
>     VEC(tree, heap) *mismatches = NULL;
>     unsigned i;
>     tree decl;
>   
>     /* Nothing to do for a single entry.  */
> !   prevailing = (lto_symtab_entry_t) *slot;
> !   if (!prevailing->next)
>       return;
>   
>     /* Try to merge each entry with the prevailing one.  */
> !   for (e = prevailing->next; e; e = e->next)
>       {
>         if (!lto_symtab_merge (prevailing, e)
>   	  && !diagnosed_p)
> ! 	VEC_safe_push (tree, heap, mismatches, e->decl);
>       }
>     if (VEC_empty (tree, mismatches))
>       return;
> --- 412,436 ----
>      do not issue further diagnostics.*/
>   
>   static void
> ! lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p)
>   {
> !   symtab_node prevailing, e;
>     VEC(tree, heap) *mismatches = NULL;
>     unsigned i;
>     tree decl;
>   
>     /* Nothing to do for a single entry.  */
> !   prevailing = first;
> !   if (!prevailing->symbol.next_sharing_asm_name)
>       return;
>   
>     /* Try to merge each entry with the prevailing one.  */
> !   for (e = prevailing->symbol.next_sharing_asm_name;
> !        e; e = e->symbol.next_sharing_asm_name)
>       {
>         if (!lto_symtab_merge (prevailing, e)
>   	  && !diagnosed_p)
> ! 	VEC_safe_push (tree, heap, mismatches, e->symbol.decl);
>       }
>     if (VEC_empty (tree, mismatches))
>       return;
> *************** lto_symtab_merge_decls_2 (void **slot, b
> *** 558,570 ****
>     /* Diagnose all mismatched re-declarations.  */
>     FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
>       {
> !       if (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl)))
>   	diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
>   				   "type of %qD does not match original "
>   				   "declaration", decl);
>   
> !       else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl))
> ! 	       && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl))
>   	{
>   	  diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
>   				     "alignment of %qD is bigger than "
> --- 438,452 ----
>     /* Diagnose all mismatched re-declarations.  */
>     FOR_EACH_VEC_ELT (tree, mismatches, i, decl)
>       {
> !       if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl),
> ! 			       TREE_TYPE (decl)))
>   	diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
>   				   "type of %qD does not match original "
>   				   "declaration", decl);
>   
> !       else if ((DECL_USER_ALIGN (prevailing->symbol.decl)
> ! 	        && DECL_USER_ALIGN (decl))
> ! 	       && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl))
>   	{
>   	  diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0,
>   				     "alignment of %qD is bigger than "
> *************** lto_symtab_merge_decls_2 (void **slot, b
> *** 572,578 ****
>   	}
>       }
>     if (diagnosed_p)
> !     inform (DECL_SOURCE_LOCATION (prevailing->decl),
>   	    "previously declared here");
>   
>     VEC_free (tree, heap, mismatches);
> --- 454,460 ----
>   	}
>       }
>     if (diagnosed_p)
> !     inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
>   	    "previously declared here");
>   
>     VEC_free (tree, heap, mismatches);
> *************** lto_symtab_merge_decls_2 (void **slot, b
> *** 580,626 ****
>   
>   /* Helper to process the decl chain for the symbol table entry *SLOT.  */
>   
> ! static int
> ! lto_symtab_merge_decls_1 (void **slot, void *data ATTRIBUTE_UNUSED)
>   {
> !   lto_symtab_entry_t e, prevailing;
>     bool diagnosed_p = false;
>   
>     /* Compute the symbol resolutions.  This is a no-op when using the
> !      linker plugin.  */
> !   lto_symtab_resolve_symbols (slot);
>   
>     /* Find the prevailing decl.  */
> !   for (prevailing = (lto_symtab_entry_t) *slot;
>          prevailing
> !        && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY
> !        && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
> !        && prevailing->resolution != LDPR_PREVAILING_DEF;
> !        prevailing = prevailing->next)
>       ;
>   
>     /* Assert it's the only one.  */
>     if (prevailing)
> !     for (e = prevailing->next; e; e = e->next)
> !       {
> ! 	if (e->resolution == LDPR_PREVAILING_DEF_IRONLY
> ! 	    || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> ! 	    || e->resolution == LDPR_PREVAILING_DEF)
> ! 	  fatal_error ("multiple prevailing defs for %qE",
> ! 		       DECL_NAME (prevailing->decl));
> !       }
>   
>     /* If there's not a prevailing symbol yet it's an external reference.
>        Happens a lot during ltrans.  Choose the first symbol with a
>        cgraph or a varpool node.  */
>     if (!prevailing)
>       {
> !       prevailing = (lto_symtab_entry_t) *slot;
> !       /* For functions choose one with a cgraph node.  */
> !       if (TREE_CODE (prevailing->decl) == FUNCTION_DECL)
> ! 	while (!prevailing->node
> ! 	       && prevailing->next)
> ! 	  prevailing = prevailing->next;
>         /* For variables chose with a priority variant with vnode
>   	 attached (i.e. from unit where external declaration of
>   	 variable is actually used).
> --- 462,511 ----
>   
>   /* Helper to process the decl chain for the symbol table entry *SLOT.  */
>   
> ! static void
> ! lto_symtab_merge_decls_1 (symtab_node first)
>   {
> !   symtab_node e, prevailing;
>     bool diagnosed_p = false;
>   
> +   if (cgraph_dump_file)
> +     {
> +       fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n",
> + 	       symtab_node_asm_name (first));
> +       for (e = first; e; e = e->symbol.next_sharing_asm_name)
> + 	dump_symtab_node (cgraph_dump_file, e);
> +     }
> + 
>     /* Compute the symbol resolutions.  This is a no-op when using the
> !      linker plugin and resolution was decided by the linker.  */
> !   lto_symtab_resolve_symbols (first);
>   
>     /* Find the prevailing decl.  */
> !   for (prevailing = first;
>          prevailing
> !        && (!symtab_real_symbol_p (prevailing)
> ! 	   || (prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY
> ! 	       && prevailing->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY_EXP
> ! 	       && prevailing->symbol.resolution != LDPR_PREVAILING_DEF));
> !        prevailing = prevailing->symbol.next_sharing_asm_name)
>       ;
>   
>     /* Assert it's the only one.  */
>     if (prevailing)
> !     for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name)
> !       if (symtab_real_symbol_p (e)
> ! 	  && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
> ! 	      || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
> ! 	      || e->symbol.resolution == LDPR_PREVAILING_DEF))
> ! 	fatal_error ("multiple prevailing defs for %qE",
> ! 		     DECL_NAME (prevailing->symbol.decl));
>   
>     /* If there's not a prevailing symbol yet it's an external reference.
>        Happens a lot during ltrans.  Choose the first symbol with a
>        cgraph or a varpool node.  */
>     if (!prevailing)
>       {
> !       prevailing = first;
>         /* For variables chose with a priority variant with vnode
>   	 attached (i.e. from unit where external declaration of
>   	 variable is actually used).
> *************** lto_symtab_merge_decls_1 (void **slot, v
> *** 628,676 ****
>   	 This is needed for C++ typeinfos, for example in
>   	 lto/20081204-1 there are typeifos in both units, just
>   	 one of them do have size.  */
> !       if (TREE_CODE (prevailing->decl) == VAR_DECL)
>   	{
> ! 	  for (e = prevailing->next; e; e = e->next)
> ! 	    if ((!prevailing->vnode && e->vnode)
> ! 		|| ((prevailing->vnode != NULL) == (e->vnode != NULL)
> ! 		    && !COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl))
> ! 		    && COMPLETE_TYPE_P (TREE_TYPE (e->decl))))
>   	      prevailing = e;
>   	}
>       }
>   
> !   /* Move it first in the list.  */
> !   if ((lto_symtab_entry_t) *slot != prevailing)
> !     {
> !       for (e = (lto_symtab_entry_t) *slot; e->next != prevailing; e = e->next)
> ! 	;
> !       e->next = prevailing->next;
> !       prevailing->next = (lto_symtab_entry_t) *slot;
> !       *slot = (void *) prevailing;
> !     }
>   
>     /* Record the prevailing variable.  */
> !   if (TREE_CODE (prevailing->decl) == VAR_DECL)
> !     VEC_safe_push (tree, gc, lto_global_var_decls, prevailing->decl);
>   
>     /* Diagnose mismatched objects.  */
> !   for (e = prevailing->next; e; e = e->next)
>       {
> !       if (TREE_CODE (prevailing->decl) == TREE_CODE (e->decl))
>   	continue;
>   
> !       switch (TREE_CODE (prevailing->decl))
>   	{
>   	case VAR_DECL:
> ! 	  gcc_assert (TREE_CODE (e->decl) == FUNCTION_DECL);
> ! 	  error_at (DECL_SOURCE_LOCATION (e->decl),
> ! 		    "variable %qD redeclared as function", prevailing->decl);
>   	  break;
>   
>   	case FUNCTION_DECL:
> ! 	  gcc_assert (TREE_CODE (e->decl) == VAR_DECL);
> ! 	  error_at (DECL_SOURCE_LOCATION (e->decl),
> ! 		    "function %qD redeclared as variable", prevailing->decl);
>   	  break;
>   
>   	default:
> --- 513,557 ----
>   	 This is needed for C++ typeinfos, for example in
>   	 lto/20081204-1 there are typeifos in both units, just
>   	 one of them do have size.  */
> !       if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
>   	{
> ! 	  for (e = prevailing->symbol.next_sharing_asm_name;
> ! 	       e; e = e->symbol.next_sharing_asm_name)
> ! 	    if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl))
> ! 		&& COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl)))
>   	      prevailing = e;
>   	}
>       }
>   
> !   symtab_prevail_in_asm_name_hash (prevailing);
>   
>     /* Record the prevailing variable.  */
> !   if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL)
> !     VEC_safe_push (tree, gc, lto_global_var_decls,
> ! 		   prevailing->symbol.decl);
>   
>     /* Diagnose mismatched objects.  */
> !   for (e = prevailing->symbol.next_sharing_asm_name;
> !        e; e = e->symbol.next_sharing_asm_name)
>       {
> !       if (TREE_CODE (prevailing->symbol.decl)
> ! 	  == TREE_CODE (e->symbol.decl))
>   	continue;
>   
> !       switch (TREE_CODE (prevailing->symbol.decl))
>   	{
>   	case VAR_DECL:
> ! 	  gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL);
> ! 	  error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
> ! 		    "variable %qD redeclared as function",
> ! 		    prevailing->symbol.decl);
>   	  break;
>   
>   	case FUNCTION_DECL:
> ! 	  gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL);
> ! 	  error_at (DECL_SOURCE_LOCATION (e->symbol.decl),
> ! 		    "function %qD redeclared as variable",
> ! 		    prevailing->symbol.decl);
>   	  break;
>   
>   	default:
> *************** lto_symtab_merge_decls_1 (void **slot, v
> *** 680,691 ****
>         diagnosed_p = true;
>       }
>     if (diagnosed_p)
> !       inform (DECL_SOURCE_LOCATION (prevailing->decl),
>   	      "previously declared here");
>   
>     /* Merge the chain to the single prevailing decl and diagnose
>        mismatches.  */
> !   lto_symtab_merge_decls_2 (slot, diagnosed_p);
>   
>     /* Store resolution decision into the callgraph.  
>        In LTRANS don't overwrite information we stored into callgraph at
> --- 561,579 ----
>         diagnosed_p = true;
>       }
>     if (diagnosed_p)
> !       inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl),
>   	      "previously declared here");
>   
>     /* Merge the chain to the single prevailing decl and diagnose
>        mismatches.  */
> !   lto_symtab_merge_decls_2 (first, diagnosed_p);
> ! 
> !   if (cgraph_dump_file)
> !     {
> !       fprintf (cgraph_dump_file, "After resolution:\n");
> !       for (e = first; e; e = e->symbol.next_sharing_asm_name)
> ! 	dump_symtab_node (cgraph_dump_file, e);
> !     }
>   
>     /* Store resolution decision into the callgraph.  
>        In LTRANS don't overwrite information we stored into callgraph at
> *************** lto_symtab_merge_decls_1 (void **slot, v
> *** 698,708 ****
>        PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
>        First one would disable some whole program optimizations, while
>        ther second would imply to many whole program assumptions.  */
> !   if (prevailing->node && !flag_ltrans && !prevailing->guessed)
> !     prevailing->node->symbol.resolution = prevailing->resolution;
> !   else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed)
> !     prevailing->vnode->symbol.resolution = prevailing->resolution;
> !   return 1;
>   }
>   
>   /* Resolve and merge all symbol table chains to a prevailing decl.  */
> --- 586,594 ----
>        PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP.
>        First one would disable some whole program optimizations, while
>        ther second would imply to many whole program assumptions.  */
> !   if (resolution_guessed_p (prevailing))
> !     prevailing->symbol.resolution = LDPR_UNKNOWN;
> !   return;
>   }
>   
>   /* Resolve and merge all symbol table chains to a prevailing decl.  */
> *************** lto_symtab_merge_decls_1 (void **slot, v
> *** 710,759 ****
>   void
>   lto_symtab_merge_decls (void)
>   {
> !   lto_symtab_maybe_init_hash_table ();
> !   htab_traverse (lto_symtab_identifiers, lto_symtab_merge_decls_1, NULL);
>   }
>   
>   /* Helper to process the decl chain for the symbol table entry *SLOT.  */
>   
> ! static int
> ! lto_symtab_merge_cgraph_nodes_1 (void **slot, void *data ATTRIBUTE_UNUSED)
>   {
> !   lto_symtab_entry_t e, prevailing = (lto_symtab_entry_t) *slot;
> ! 
> !   if (!prevailing->next)
> !     return 1;
>   
>     /* Replace the cgraph node of each entry with the prevailing one.  */
> !   for (e = prevailing->next; e; e = e->next)
>       {
> !       if (e->node != NULL)
> ! 	{
> ! 	  /* In case we prevail funcion by an alias, we can run into case
> ! 	     that the alias has no cgraph node attached, since it was
> ! 	     previously unused.  Create the node.  */
> ! 	  if (!prevailing->node)
> ! 	    {
> ! 	      prevailing->node = cgraph_create_node (prevailing->decl);
> ! 	      prevailing->node->alias = true;
> ! 	    }
> ! 	  lto_cgraph_replace_node (e->node, prevailing->node);
> ! 	}
> !       if (e->vnode != NULL)
> ! 	{
> ! 	  if (!prevailing->vnode)
> ! 	    {
> ! 	      prevailing->vnode = varpool_node (prevailing->decl);
> ! 	      prevailing->vnode->alias = true;
> ! 	    }
> ! 	  lto_varpool_replace_node (e->vnode, prevailing->vnode);
> ! 	}
> !     }
>   
> !   /* Drop all but the prevailing decl from the symtab.  */
> !   prevailing->next = NULL;
>   
> !   return 1;
>   }
>   
>   /* Merge cgraph nodes according to the symbol merging done by
> --- 596,641 ----
>   void
>   lto_symtab_merge_decls (void)
>   {
> !   symtab_node node;
> ! 
> !   /* In ltrans mode we read merged cgraph, we do not really need to care
> !      about resolving symbols again, we only need to replace duplicated declarations
> !      read from the callgraph and from function sections.  */
> !   if (flag_ltrans)
> !     return;
> ! 
> !   /* Populate assembler name hash.   */
> !   symtab_initialize_asm_name_hash ();
> ! 
> !   FOR_EACH_SYMBOL (node)
> !     if (TREE_PUBLIC (node->symbol.decl)
> ! 	&& node->symbol.next_sharing_asm_name
> ! 	&& !node->symbol.previous_sharing_asm_name)
> !     lto_symtab_merge_decls_1 (node);
>   }
>   
>   /* Helper to process the decl chain for the symbol table entry *SLOT.  */
>   
> ! static void
> ! lto_symtab_merge_cgraph_nodes_1 (symtab_node prevailing)
>   {
> !   symtab_node e, next;
>   
>     /* Replace the cgraph node of each entry with the prevailing one.  */
> !   for (e = prevailing->symbol.next_sharing_asm_name; e;
> !        e = next)
>       {
> !       next = e->symbol.next_sharing_asm_name;
>   
> !       if (!symtab_real_symbol_p (e))
> ! 	continue;
> !       if (symtab_function_p (e))
> ! 	lto_cgraph_replace_node (cgraph (e), cgraph (prevailing));
> !       if (symtab_variable_p (e))
> ! 	lto_varpool_replace_node (varpool (e), varpool (prevailing));
> !     }
>   
> !   return;
>   }
>   
>   /* Merge cgraph nodes according to the symbol merging done by
> *************** lto_symtab_merge_cgraph_nodes_1 (void **
> *** 762,779 ****
>   void
>   lto_symtab_merge_cgraph_nodes (void)
>   {
> !   struct cgraph_node *node;
>     struct varpool_node *vnode;
> !   lto_symtab_maybe_init_hash_table ();
> !   htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL);
>   
> !   FOR_EACH_FUNCTION (node)
> !     if ((node->thunk.thunk_p || node->alias)
> ! 	&& node->thunk.alias)
> !       node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias);
>     FOR_EACH_VARIABLE (vnode)
> !     if (vnode->alias_of)
> !       vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
>   }
>   
>   /* Given the decl DECL, return the prevailing decl with the same name. */
> --- 644,676 ----
>   void
>   lto_symtab_merge_cgraph_nodes (void)
>   {
> !   struct cgraph_node *cnode;
>     struct varpool_node *vnode;
> !   symtab_node node;
> ! 
> !   /* Populate assembler name hash.   */
> !   symtab_initialize_asm_name_hash ();
>   
> !   if (!flag_ltrans)
> !     FOR_EACH_SYMBOL (node)
> !       if (TREE_PUBLIC (node->symbol.decl)
> ! 	  && node->symbol.next_sharing_asm_name
> ! 	  && !node->symbol.previous_sharing_asm_name)
> !         lto_symtab_merge_cgraph_nodes_1 (node);
> ! 
> !   FOR_EACH_FUNCTION (cnode)
> !     {
> !       if ((cnode->thunk.thunk_p || cnode->alias)
> ! 	  && cnode->thunk.alias)
> !         cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
> !       cnode->symbol.aux = NULL;
> !     }
>     FOR_EACH_VARIABLE (vnode)
> !     {
> !       if (vnode->alias_of)
> !         vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
> !       vnode->symbol.aux = NULL;
> !     }
>   }
>   
>   /* Given the decl DECL, return the prevailing decl with the same name. */
> *************** lto_symtab_merge_cgraph_nodes (void)
> *** 781,787 ****
>   tree
>   lto_symtab_prevailing_decl (tree decl)
>   {
> !   lto_symtab_entry_t ret;
>   
>     /* Builtins and local symbols are their own prevailing decl.  */
>     if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
> --- 678,684 ----
>   tree
>   lto_symtab_prevailing_decl (tree decl)
>   {
> !   symtab_node ret;
>   
>     /* Builtins and local symbols are their own prevailing decl.  */
>     if (!TREE_PUBLIC (decl) || is_builtin_fn (decl))
> *************** lto_symtab_prevailing_decl (tree decl)
> *** 795,806 ****
>     gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
>   
>     /* Walk through the list of candidates and return the one we merged to.  */
> !   ret = lto_symtab_get ((*targetm.asm_out.mangle_assembler_name)
> ! 			(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
>     if (!ret)
> !     return NULL_TREE;
>   
> !   return ret->decl;
>   }
> - 
> - #include "gt-lto-symtab.h"
> --- 692,700 ----
>     gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
>   
>     /* Walk through the list of candidates and return the one we merged to.  */
> !   ret = symtab_node_for_asm (DECL_ASSEMBLER_NAME (decl));
>     if (!ret)
> !     return decl;
>   
> !   return ret->symbol.decl;
>   }
> Index: lto/lto.c
> ===================================================================
> *** lto/lto.c	(revision 191418)
> --- lto/lto.c	(working copy)
> *************** lto_materialize_function (struct cgraph_
> *** 198,204 ****
>        and also functions that are needed to produce virtual clones.  */
>     if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node))
>       {
> !       /* Clones and thunks don't need to be read.  */
>         if (node->clone_of)
>   	return;
>   
> --- 198,204 ----
>        and also functions that are needed to produce virtual clones.  */
>     if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node))
>       {
> !       /* Clones don't need to be read.  */
>         if (node->clone_of)
>   	return;
>   
> *************** read_cgraph_and_symbols (unsigned nfiles
> *** 3006,3012 ****
>         VEC_safe_push (ipa_opt_pass, heap,
>   		     node->ipa_transforms_to_apply,
>   		     (ipa_opt_pass)&pass_ipa_inline);
> -   lto_symtab_free ();
>   
>     timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
>   
> --- 3006,3011 ----
> *************** materialize_cgraph (void)
> *** 3035,3041 ****
>       fprintf (stderr,
>   	     flag_wpa ? "Materializing decls:" : "Reading function bodies:");
>   
> - 
>     /* Now that we have input the cgraph, we need to clear all of the aux
>        nodes and read the functions if we are not running in WPA mode.  */
>     timevar_push (TV_IPA_LTO_GIMPLE_IN);
> --- 3034,3039 ----
> Index: lto-streamer.h
> ===================================================================
> *** lto-streamer.h	(revision 191418)
> --- lto-streamer.h	(working copy)
> *************** extern void lto_symtab_merge_decls (void
> *** 866,872 ****
>   extern void lto_symtab_merge_cgraph_nodes (void);
>   extern tree lto_symtab_prevailing_decl (tree decl);
>   extern enum ld_plugin_symbol_resolution lto_symtab_get_resolution (tree decl);
> - extern void lto_symtab_free (void);
>   extern GTY(()) VEC(tree,gc) *lto_global_var_decls;
>   
>   
> --- 866,871 ----
> Index: lto-cgraph.c
> ===================================================================
> *** lto-cgraph.c	(revision 191418)
> --- lto-cgraph.c	(working copy)
> *************** add_references (lto_symtab_encoder_t enc
> *** 668,677 ****
>       if (symtab_function_p (ref->referred))
>         add_node_to (encoder, ipa_ref_node (ref), false);
>       else
> !       {
> ! 	struct varpool_node *vnode = ipa_ref_varpool_node (ref);
> !         lto_symtab_encoder_encode (encoder, (symtab_node)vnode);
> !       }
>   }
>   
>   /* Find all symbols we want to stream into given partition and insert them
> --- 668,674 ----
>       if (symtab_function_p (ref->referred))
>         add_node_to (encoder, ipa_ref_node (ref), false);
>       else
> !       lto_symtab_encoder_encode (encoder, ref->referred);
>   }
>   
>   /* Find all symbols we want to stream into given partition and insert them
> Index: varpool.c
> ===================================================================
> *** varpool.c	(revision 191418)
> --- varpool.c	(working copy)
> *************** varpool_assemble_decl (struct varpool_no
> *** 301,306 ****
> --- 301,310 ----
>         && !targetm.have_tls)
>       return false;
>   
> +   /* Hard register vars do not need to be output.  */
> +   if (DECL_HARD_REGISTER (decl))
> +     return false;
> + 
>     gcc_checking_assert (!TREE_ASM_WRITTEN (decl)
>   		       && TREE_CODE (decl) == VAR_DECL
>   		       && !DECL_HAS_VALUE_EXPR_P (decl));
> 
>

Patch

Index: gcc/symtab.c
===================================================================
--- gcc/symtab.c        (revision 191415)
+++ gcc/symtab.c        (working copy)
@@ -151,6 +151,8 @@  unlink_from_assembler_name_hash (symtab_
          else
            *slot = node->symbol.next_sharing_asm_name;
        }
+      node->symbol.next_sharing_asm_name = NULL;
+      node->symbol.previous_sharing_asm_name = NULL;
     }
 }