Rewrite lto-symtab to work on symbol table

Jan Hubicka hubicka@ucw.cz
Tue Sep 18 13:36:00 GMT 2012


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.

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.  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?

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));



More information about the Gcc-patches mailing list