This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Symbol table 17/many


Hi,
this patch cleanups interface of cgraph.c.  Moves stuff that is not strictly
cgraph related into appropriate places and commonizes some more code with
varpool (in particular same comdat group handling).
It also cleans up a bit interface of cgraphunit and drops cgraph prefixes
on stuff that is not cgraph related - asm nodes and finalize_compilation_unit.
The idea is to move most of cgraph related stuff from cgraphunit.c and keep there
the main driver of optimization phase that can then perhaps be folded
into passes.c or toplev.c or stay as separate compile.c/optimize.c

Bootstrapped/regtested x86_64-linux, comitted.

Honza

	* cgraph.c (ld_plugin_symbol_resolution_names): Move to symtab.c
	(cgraph_asm_nodes, cgraph_asm_last_node): Move to cgraphunit.c
	(cgraph_add_to_same_comdat_group): Remove.
	(cgraph_add_asm_node): Move to cgraphunit.c.
	(cgraph_make_decl_local): Move to symtab.c
	(cgraph_make_node_local_1): Update.
	(cgraph_can_remove_if_no_direct_calls_and): Update.
	(used_from_object_file_p): Update.
	(resolution_used_from_other_file_p): Move to symtab.c
	(cgraph_used_from_object_file_p): move to symtab.c
	(verify_cgraph_node): Verify same comdat groups.
	* cgraph.h (cgraph_asm_node): Rename to ...
	(asm_node): ... this one.
	(cgraph_asm_nodes): Rename to ...
	(asm_nodes): ... this one.
	(symtab_add_to_same_comdat_group): New function.
	(symtab_dissolve_same_comdat_group_list): New function.
	(symtab_used_from_object_file_p): Declare.
	(symtab_make_decl_local): Declare.
	(cgraph_add_to_same_comdat_group): Remove.
	(cgraph_add_asm_node): Remove.
	(cgraph_used_from_object_file_p, varpool_used_from_object_file_p):
	Remove.
	(cgraph_finalize_compilation_unit): Rename to ...
	(finalize_compilation_unit): ... this one.
	(cgraph_optimize): Rename to ....
	(compile): ... this one.
	(add_asm_node): Declare.
	(fixup_same_cpp_alias_visibility): Declare.
	(cgraph_make_decl_local): Remove.
	(varpool_assemble_pending_decls): Rename to ...
	(varpool_output_variables): ... this one.
	(varpool_remove_unreferenced_decls): Remove.
	* ipa-inline-transform.c (clone_inlined_nodes): Dissolve comdat groups.
	(preserve_function_body_p): Make static.
	* toplev.c (compile_file): Update comments;
	update.
	* cgraphunit.c: Update comments.
	(cgraph_expand_all_functions): Rename to ...
	(expand_all_functions): ... this one; update.
	(cgraph_mark_functions_to_output): Rename to ...
	(mark_functions_to_output): ... this one; cleanup.
	(cgraph_output_pending_asms): Remove prototype.
	(asm_nodes, asm_last_node): New static vars.
	(cgraph_process_new_functions): Update.
	(cgraph_reset_node): Cleanup; add comment.
	(cgraph_add_new_function): Update.
	(cgraph_output_pending_asms): Rename to ...
	(output_asm_statements): ... this one.
	(add_asm_node): New function.
	(fixup_same_cpp_alias_visibility): New function based on code
	in cgraph_analyze_function.
	(cgraph_analyze_function): Use it.
	(cgraph_order_sort): Update.
	(cgraph_output_in_order): Update.
	(cgraph_function_versioning): Update.
	(cgraph_optimize): Rename to ...
	(compile): ... this one; initialize streamer hooks here.
	(cgraph_finalize_compilation_unit): Rename to ...
	(finalize_compilation_unit): ... this one; do not initialize streamer
	hook here.
	* lto-streamer-out.c (lto_output_toplevel_asms): Update.
	* dwarf2out.c: Update ocmment.
	* optimize.c (maybe_clone_body): Use symtab_add_to_same_comdat_group.
	* method.c (use_thunk): Likewise.
	* semantics.c (maybe_add_lambda_conv_op): Likewise.
	* decl2.c (maybe_emit_vtables): Likewise.	
	(cp_write_global_declarations): Use finalize_compilation_unit.
	* parser.c (cp_parser_asm_definition): Use add_asm_node.
	* lto-streamer-in.c (lto_input_toplevel_asms): Use add_asm_node
	* c-decl.c (c_write_global_declarations): Use finalize_compilation_unit.
	* langhooks.c (write_global_declarations): Update.
	* ipa.c (cgraph_externally_visible_p): Update.
	(dissolve_same_comdat_group_list): Remove.
	(function_and_variable_visibility): Update.
	* symtab.c: Inlcude lto-streamer.h and rtl.h
	(ld_plugin_symbol_resolution_names): New.
	(symtab_add_to_same_comdat_group): New.
	(symtab_dissolve_same_comdat_group_list): New.
	(resolution_used_from_other_file_p): Move here from cgraph.c
	(symtab_used_from_object_file_p): New.
	(symtab_make_decl_local): New.
	* passes.c (register_pass): Update comments.
	* c-parser.c (c_parser_asm_definition): Update.
	* varpool.c (varpool_analyze_node): Use fixup_same_cpp_alias_visibility.
	(varpool_remove_unreferenced_decls): Make static.
	(varpool_assemble_pending_decls): Rename to ...
	(varpool_output_variables): ... this one; call
	varpool_remove_unreferenced_decls.
	(varpool_used_from_object_file_p): Remove.

	* gogo-tree.cc (Gogo::write_globals): Use finalize_compilation_unit.

	* gcc-interface/utils.c (rest_of_subprog_body_compilation): Update
	comment.
	(gnat_write_global_declarations): Use finalize_compilation_unit.

	* f95-lang.c (gfc_finish): Update comments.

	* lto.c (lto_main): Use compile ().
	* lto-partition.c (partition_cgraph_node_p): Use symtab_used_from_object_file_p.
	(partition_varpool_node_p): Likewise.

Index: cgraph.c
===================================================================
*** cgraph.c	(revision 186961)
--- cgraph.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 54,73 ****
  #include "cfgloop.h"
  #include "gimple-pretty-print.h"
  
- const char * const ld_plugin_symbol_resolution_names[]=
- {
-   "",
-   "undef",
-   "prevailing_def",
-   "prevailing_def_ironly",
-   "preempted_reg",
-   "preempted_ir",
-   "resolved_ir",
-   "resolved_exec",-   "resolved_dyn",
-   "prevailing_def_ironly_exp"
- };
- 
  static void cgraph_node_remove_callers (struct cgraph_node *node);
  static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
  static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
--- 54,59 ----
*************** enum cgraph_state cgraph_state = CGRAPH_
*** 94,105 ****
  /* Set when the cgraph is fully build and the basic flags are computed.  */
  bool cgraph_function_flags_ready = false;
  
- /* Linked list of cgraph asm nodes.  */
- struct cgraph_asm_node *cgraph_asm_nodes;
- 
- /* Last node in cgraph_asm_nodes.  */
- static GTY(()) struct cgraph_asm_node *cgraph_asm_last_node;
- 
  /* List of hooks triggered on cgraph_edge events.  */
  struct cgraph_edge_hook_list {
    cgraph_edge_hook hook;
--- 80,85 ----
*************** cgraph_remove_node (struct cgraph_node *
*** 1377,1407 ****
    free_nodes = node;
  }
  
- /* Add NEW_ to the same comdat group that OLD is in.  */
- 
- void
- cgraph_add_to_same_comdat_group (struct cgraph_node *new_node,
- 				 struct cgraph_node *old_node)
- {
-   gcc_assert (DECL_ONE_ONLY (old_node->symbol.decl));
-   gcc_assert (!new_node->symbol.same_comdat_group);
-   gcc_assert (new_node != old_node);
- 
-   DECL_COMDAT_GROUP (new_node->symbol.decl) = DECL_COMDAT_GROUP (old_node->symbol.decl);
-   new_node->symbol.same_comdat_group = (symtab_node)old_node;
-   if (!old_node->symbol.same_comdat_group)
-     old_node->symbol.same_comdat_group = (symtab_node)new_node;
-   else
-     {
-       symtab_node n;
-       for (n = old_node->symbol.same_comdat_group;
- 	   n->symbol.same_comdat_group != (symtab_node)old_node;
- 	   n = n->symbol.same_comdat_group)
- 	;
-       n->symbol.same_comdat_group = (symtab_node)new_node;
-     }
- }
- 
  /* Remove the node from cgraph and all inline clones inlined into it.
     Skip however removal of FORBIDDEN_NODE and return true if it needs to be
     removed.  This allows to call the function from outer loop walking clone
--- 1357,1362 ----
*************** debug_cgraph (void)
*** 1660,1684 ****
    dump_cgraph (stderr);
  }
  
- /* Add a top-level asm statement to the list.  */
- 
- struct cgraph_asm_node *
- cgraph_add_asm_node (tree asm_str)
- {
-   struct cgraph_asm_node *node;
- 
-   node = ggc_alloc_cleared_cgraph_asm_node ();
-   node->asm_str = asm_str;
-   node->order = symtab_order++;
-   node->next = NULL;
-   if (cgraph_asm_nodes == NULL)
-     cgraph_asm_nodes = node;
-   else
-     cgraph_asm_last_node->next = node;
-   cgraph_asm_last_node = node;
-   return node;
- }
- 
  /* Return true when the DECL can possibly be inlined.  */
  bool
  cgraph_function_possibly_inlined_p (tree decl)
--- 1615,1620 ----
*************** cgraph_node_can_be_local_p (struct cgrap
*** 2047,2123 ****
  					   NULL, true));
  }
  
- /* Make DECL local.  FIXME: We shouldn't need to mess with rtl this early,
-    but other code such as notice_global_symbol generates rtl.  */
- void
- cgraph_make_decl_local (tree decl)
- {
-   rtx rtl, symbol;
- 
-   if (TREE_CODE (decl) == VAR_DECL)
-     DECL_COMMON (decl) = 0;
-   else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- 
-   if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl))
-     {
-       /* It is possible that we are linking against library defining same COMDAT
- 	 function.  To avoid conflict we need to rename our local name of the
- 	 function just in the case WHOPR partitioning decide to make it hidden
- 	 to avoid cross partition references.  */
-       if (flag_wpa)
- 	{
- 	  const char *old_name;
- 
- 	  old_name  = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- 	  if (TREE_CODE (decl) == FUNCTION_DECL)
- 	    {
- 	      struct cgraph_node *node = cgraph_get_node (decl);
- 	      change_decl_assembler_name (decl,
- 					  clone_function_name (decl, "local"));
- 	      if (node->symbol.lto_file_data)
- 		lto_record_renamed_decl (node->symbol.lto_file_data,
- 					 old_name,
- 					 IDENTIFIER_POINTER
- 					   (DECL_ASSEMBLER_NAME (decl)));
- 	    }
- 	  else if (TREE_CODE (decl) == VAR_DECL)
- 	    {
- 	      struct varpool_node *vnode = varpool_get_node (decl);
- 	      /* change_decl_assembler_name will warn here on vtables because
- 		 C++ frontend still sets TREE_SYMBOL_REFERENCED on them.  */
- 	      SET_DECL_ASSEMBLER_NAME (decl,
- 				       clone_function_name (decl, "local"));
- 	      if (vnode->symbol.lto_file_data)
- 		lto_record_renamed_decl (vnode->symbol.lto_file_data,
- 					 old_name,
- 					 IDENTIFIER_POINTER
- 					   (DECL_ASSEMBLER_NAME (decl)));
- 	    }
- 	}
-       DECL_SECTION_NAME (decl) = 0;
-       DECL_COMDAT (decl) = 0;
-     }
-   DECL_COMDAT_GROUP (decl) = 0;
-   DECL_WEAK (decl) = 0;
-   DECL_EXTERNAL (decl) = 0;
-   TREE_PUBLIC (decl) = 0;
-   if (!DECL_RTL_SET_P (decl))
-     return;
- 
-   /* Update rtl flags.  */
-   make_decl_rtl (decl);
- 
-   rtl = DECL_RTL (decl);
-   if (!MEM_P (rtl))
-     return;
- 
-   symbol = XEXP (rtl, 0);
-   if (GET_CODE (symbol) != SYMBOL_REF)
-     return;
- 
-   SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
- }
- 
  /* Call calback on NODE, thunks and aliases asociated to NODE. 
     When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
     skipped. */
--- 1983,1988 ----
*************** cgraph_make_node_local_1 (struct cgraph_
*** 2190,2196 ****
    gcc_checking_assert (cgraph_node_can_be_local_p (node));
    if (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
      {
!       cgraph_make_decl_local (node->symbol.decl);
  
        node->symbol.externally_visible = false;
        node->local.local = true;
--- 2055,2061 ----
    gcc_checking_assert (cgraph_node_can_be_local_p (node));
    if (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
      {
!       symtab_make_decl_local (node->symbol.decl);
  
        node->symbol.externally_visible = false;
        node->local.local = true;
*************** cgraph_can_remove_if_no_direct_calls_and
*** 2472,2478 ****
    /* Only COMDAT functions can be removed if externally visible.  */
    if (node->symbol.externally_visible
        && (!DECL_COMDAT (node->symbol.decl)
! 	  || cgraph_used_from_object_file_p (node)))
      return false;
    return true;
  }
--- 2337,2343 ----
    /* Only COMDAT functions can be removed if externally visible.  */
    if (node->symbol.externally_visible
        && (!DECL_COMDAT (node->symbol.decl)
! 	  || symtab_used_from_object_file_p ((symtab_node) node)))
      return false;
    return true;
  }
*************** cgraph_can_remove_if_no_direct_calls_p (
*** 2504,2510 ****
  static bool
  used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
  {
!   return cgraph_used_from_object_file_p (node);
  }
  
  /* Return true when function NODE can be expected to be removed
--- 2369,2375 ----
  static bool
  used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
  {
!   return symtab_used_from_object_file_p ((symtab_node) node);
  }
  
  /* Return true when function NODE can be expected to be removed
*************** cgraph_will_be_removed_from_program_if_n
*** 2537,2568 ****
      }
  }
  
- /* Return true when RESOLUTION indicate that linker will use
-    the symbol from non-LTO object files.  */
- 
- bool
- resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
- {
-   return (resolution == LDPR_PREVAILING_DEF
-           || resolution == LDPR_PREEMPTED_REG
-           || resolution == LDPR_RESOLVED_EXEC
-           || resolution == LDPR_RESOLVED_DYN);
- }
- 
- 
- /* Return true when NODE is known to be used from other (non-LTO) object file.
-    Known only when doing LTO via linker plugin.  */
- 
- bool
- cgraph_used_from_object_file_p (struct cgraph_node *node)
- {
-   gcc_assert (!node->global.inlined_to);
-   if (!TREE_PUBLIC (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
-     return false;
-   if (resolution_used_from_other_file_p (node->symbol.resolution))
-     return true;
-   return false;
- }
  
  /* Worker for cgraph_only_called_directly_p.  */
  
--- 2402,2407 ----
*************** verify_cgraph_node (struct cgraph_node *
*** 2741,2746 ****
--- 2580,2590 ----
        error ("execution count is negative");
        error_found = true;
      }
+   if (node->global.inlined_to && node->symbol.same_comdat_group)
+     {
+       error ("inline clone in same comdat group list");
+       error_found = true;
+     }
    if (node->global.inlined_to && node->symbol.externally_visible)
      {
        error ("externally visible inline clone");
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 186961)
--- cgraph.h	(working copy)
*************** struct GTY(()) varpool_node {
*** 422,432 ****
    unsigned extra_name_alias : 1;
  };
  
! /* Every top level asm statement is put into a cgraph_asm_node.  */
  
! struct GTY(()) cgraph_asm_node {
    /* Next asm node.  */
!   struct cgraph_asm_node *next;
    /* String for this asm node.  */
    tree asm_str;
    /* Ordering of all cgraph nodes.  */
--- 422,432 ----
    unsigned extra_name_alias : 1;
  };
  
! /* Every top level asm statement is put into a asm_node.  */
  
! struct GTY(()) asm_node {
    /* Next asm node.  */
!   struct asm_node *next;
    /* String for this asm node.  */
    tree asm_str;
    /* Ordering of all cgraph nodes.  */
*************** extern enum cgraph_state cgraph_state;
*** 467,473 ****
  extern bool cgraph_function_flags_ready;
  extern cgraph_node_set cgraph_new_nodes;
  
! extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
  extern GTY(()) int symtab_order;
  extern bool same_body_aliases_done;
  
--- 467,473 ----
  extern bool cgraph_function_flags_ready;
  extern cgraph_node_set cgraph_new_nodes;
  
! extern GTY(()) struct asm_node *asm_nodes;
  extern GTY(()) int symtab_order;
  extern bool same_body_aliases_done;
  
*************** symtab_node symtab_node_for_asm (const_t
*** 480,485 ****
--- 480,487 ----
  const char * symtab_node_asm_name (symtab_node);
  const char * symtab_node_name (symtab_node);
  void symtab_insert_node_to_hashtable (symtab_node);
+ void symtab_add_to_same_comdat_group (symtab_node, symtab_node);
+ void symtab_dissolve_same_comdat_group_list (symtab_node node);
  void dump_symtab (FILE *);
  void debug_symtab (void);
  void dump_symtab_node (FILE *, symtab_node);
*************** void dump_symtab_base (FILE *, symtab_no
*** 488,493 ****
--- 490,497 ----
  void verify_symtab (void);
  void verify_symtab_node (symtab_node);
  bool verify_symtab_base (symtab_node);
+ bool symtab_used_from_object_file_p (symtab_node);
+ void symtab_make_decl_local (tree);
  
  /* In cgraph.c  */
  void dump_cgraph (FILE *);
*************** void debug_cgraph_node (struct cgraph_no
*** 497,503 ****
  void cgraph_remove_edge (struct cgraph_edge *);
  void cgraph_remove_node (struct cgraph_node *);
  struct cgraph_node *cgraph_find_replacement_node (struct cgraph_node *);
- void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *);
  bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *);
  void cgraph_release_function_body (struct cgraph_node *);
  void cgraph_node_remove_callees (struct cgraph_node *node);
--- 501,506 ----
*************** void cgraph_redirect_edge_callee (struct
*** 538,545 ****
  void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *);
  bool cgraph_only_called_directly_p (struct cgraph_node *);
  
- struct cgraph_asm_node *cgraph_add_asm_node (tree);
- 
  bool cgraph_function_possibly_inlined_p (tree);
  void cgraph_unnest_node (struct cgraph_node *);
  
--- 541,546 ----
*************** bool cgraph_can_remove_if_no_direct_call
*** 564,571 ****
    (struct cgraph_node *node);
  bool cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node);
  bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
- bool cgraph_used_from_object_file_p (struct cgraph_node *);
- bool varpool_used_from_object_file_p (struct varpool_node *);
  bool cgraph_for_node_thunks_and_aliases (struct cgraph_node *,
  			                 bool (*) (struct cgraph_node *, void *),
  			                 void *,
--- 565,570 ----
*************** gimple cgraph_redirect_edge_call_stmt_to
*** 605,614 ****
  bool cgraph_propagate_frequency (struct cgraph_node *node);
  
  /* In cgraphunit.c  */
  extern FILE *cgraph_dump_file;
  void cgraph_finalize_function (tree, bool);
! void cgraph_finalize_compilation_unit (void);
! void cgraph_optimize (void);
  void init_cgraph (void);
  struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
  		tree, VEC(cgraph_edge_p,heap)*, bitmap);
--- 604,614 ----
  bool cgraph_propagate_frequency (struct cgraph_node *node);
  
  /* In cgraphunit.c  */
+ struct asm_node *add_asm_node (tree);
  extern FILE *cgraph_dump_file;
  void cgraph_finalize_function (tree, bool);
! void finalize_compilation_unit (void);
! void compile (void);
  void init_cgraph (void);
  struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
  		tree, VEC(cgraph_edge_p,heap)*, bitmap);
*************** void tree_function_versioning (tree, tre
*** 621,626 ****
--- 621,627 ----
  			       bool, bitmap, bool, bitmap, basic_block);
  bool cgraph_process_new_functions (void);
  void cgraph_process_same_body_aliases (void);
+ void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias);
  
  
  /* In cgraphbuild.c  */
*************** void dump_varpool_node (FILE *, struct v
*** 668,684 ****
  void varpool_finalize_decl (tree);
  bool decide_is_variable_needed (struct varpool_node *, tree);
  enum availability cgraph_variable_initializer_availability (struct varpool_node *);
- void cgraph_make_decl_local (tree);
  void cgraph_make_node_local (struct cgraph_node *);
  bool cgraph_node_can_be_local_p (struct cgraph_node *);
  
  
  void varpool_remove_node (struct varpool_node *node);
  void varpool_finalize_named_section_flags (struct varpool_node *node);
! bool varpool_assemble_pending_decls (void);
  bool varpool_assemble_decl (struct varpool_node *node);
  void varpool_analyze_node (struct varpool_node *);
- void varpool_remove_unreferenced_decls (void);
  struct varpool_node * varpool_extra_name_alias (tree, tree);
  struct varpool_node * varpool_create_variable_alias (tree, tree);
  void varpool_reset_queue (void);
--- 669,683 ----
  void varpool_finalize_decl (tree);
  bool decide_is_variable_needed (struct varpool_node *, tree);
  enum availability cgraph_variable_initializer_availability (struct varpool_node *);
  void cgraph_make_node_local (struct cgraph_node *);
  bool cgraph_node_can_be_local_p (struct cgraph_node *);
  
  
  void varpool_remove_node (struct varpool_node *node);
  void varpool_finalize_named_section_flags (struct varpool_node *node);
! bool varpool_output_variables (void);
  bool varpool_assemble_decl (struct varpool_node *node);
  void varpool_analyze_node (struct varpool_node *);
  struct varpool_node * varpool_extra_name_alias (tree, tree);
  struct varpool_node * varpool_create_variable_alias (tree, tree);
  void varpool_reset_queue (void);
*************** cgraph_mark_force_output_node (struct cg
*** 1288,1291 ****
--- 1287,1291 ----
    node->symbol.force_output = 1;
    gcc_checking_assert (!node->global.inlined_to);
  }
+ 
  #endif  /* GCC_CGRAPH_H  */
Index: ipa-inline-transform.c
===================================================================
*** ipa-inline-transform.c	(revision 186961)
--- ipa-inline-transform.c	(working copy)
*************** clone_inlined_nodes (struct cgraph_edge 
*** 157,162 ****
--- 157,163 ----
  	     For now we keep the ohter functions in the group in program until
  	     cgraph_remove_unreachable_functions gets rid of them.  */
  	  gcc_assert (!e->callee->global.inlined_to);
+           symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee);
  	  if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->symbol.decl))
  	    {
  	      if (overall_size)
*************** clone_inlined_nodes (struct cgraph_edge 
*** 176,181 ****
--- 177,184 ----
  	  cgraph_redirect_edge_callee (e, n);
  	}
      }
+   else
+     symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee);
  
    if (e->caller->global.inlined_to)
      e->callee->global.inlined_to = e->caller->global.inlined_to;
*************** save_inline_function_body (struct cgraph
*** 355,361 ****
  
  /* Return true when function body of DECL still needs to be kept around
     for later re-use.  */
! bool
  preserve_function_body_p (struct cgraph_node *node)
  {
    gcc_assert (cgraph_global_info_ready);
--- 358,364 ----
  
  /* Return true when function body of DECL still needs to be kept around
     for later re-use.  */
! static bool
  preserve_function_body_p (struct cgraph_node *node)
  {
    gcc_assert (cgraph_global_info_ready);
Index: toplev.c
===================================================================
*** toplev.c	(revision 186961)
--- toplev.c	(working copy)
*************** compile_file (void)
*** 567,573 ****
  
    ggc_protect_identifiers = false;
  
!   /* This must also call cgraph_finalize_compilation_unit.  */
    lang_hooks.decls.final_write_globals ();
  
    if (seen_error ())
--- 567,573 ----
  
    ggc_protect_identifiers = false;
  
!   /* This must also call finalize_compilation_unit.  */
    lang_hooks.decls.final_write_globals ();
  
    if (seen_error ())
*************** compile_file (void)
*** 580,587 ****
       basically finished.  */
    if (in_lto_p || !flag_lto || flag_fat_lto_objects)
      {
!       varpool_remove_unreferenced_decls ();
!       varpool_assemble_pending_decls ();
        finish_aliases_2 ();
  
        /* Likewise for mudflap static object registrations.  */
--- 580,586 ----
       basically finished.  */
    if (in_lto_p || !flag_lto || flag_fat_lto_objects)
      {
!       varpool_output_variables ();
        finish_aliases_2 ();
  
        /* Likewise for mudflap static object registrations.  */
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 186961)
--- cgraphunit.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 39,45 ****
        This function has same behavior as the above but is used for static
        variables.
  
!     - cgraph_finalize_compilation_unit
  
        This function is called once (source level) compilation unit is finalized
        and it will no longer change.
--- 39,49 ----
        This function has same behavior as the above but is used for static
        variables.
  
!     - add_asm_node
! 
!       Insert new toplevel ASM statement
! 
!     - finalize_compilation_unit
  
        This function is called once (source level) compilation unit is finalized
        and it will no longer change.
*************** along with GCC; see the file COPYING3.  
*** 54,60 ****
        The function can be called multiple times when multiple source level
        compilation units are combined.
  
!     - cgraph_optimize
  
        This passes control to the back-end.  Optimizations are performed and
        final assembler is generated.  This is done in the following way. Note
--- 58,64 ----
        The function can be called multiple times when multiple source level
        compilation units are combined.
  
!     - compile
  
        This passes control to the back-end.  Optimizations are performed and
        final assembler is generated.  This is done in the following way. Note
*************** along with GCC; see the file COPYING3.  
*** 130,136 ****
  	    Simple IP passes working within single program partition.
  
  	 5) Expansion
! 	    (cgraph_expand_all_functions)
  
  	    At this stage functions that needs to be output into
  	    assembler are identified and compiled in topological order
--- 134,140 ----
  	    Simple IP passes working within single program partition.
  
  	 5) Expansion
! 	    (expand_all_functions)
  
  	    At this stage functions that needs to be output into
  	    assembler are identified and compiled in topological order
*************** along with GCC; see the file COPYING3.  
*** 197,210 ****
     may generate new functions that need to be optimized and expanded.  */
  cgraph_node_set cgraph_new_nodes;
  
! static void cgraph_expand_all_functions (void);
! static void cgraph_mark_functions_to_output (void);
! static void cgraph_expand_function (struct cgraph_node *);
! static void cgraph_output_pending_asms (void);
  static void cgraph_analyze_function (struct cgraph_node *);
  
  FILE *cgraph_dump_file;
  
  /* Used for vtable lookup in thunk adjusting.  */
  static GTY (()) tree vtable_entry_type;
  
--- 201,219 ----
     may generate new functions that need to be optimized and expanded.  */
  cgraph_node_set cgraph_new_nodes;
  
! static void expand_all_functions (void);
! static void mark_functions_to_output (void);
! static void expand_function (struct cgraph_node *);
  static void cgraph_analyze_function (struct cgraph_node *);
  
  FILE *cgraph_dump_file;
  
+ /* Linked list of cgraph asm nodes.  */
+ struct asm_node *asm_nodes;
+ 
+ /* Last node in cgraph_asm_nodes.  */
+ static GTY(()) struct asm_node *asm_last_node;
+ 
  /* Used for vtable lookup in thunk adjusting.  */
  static GTY (()) tree vtable_entry_type;
  
*************** cgraph_process_new_functions (void)
*** 324,330 ****
  	     directly.  */
  	  node->process = 0;
            cgraph_call_function_insertion_hooks (node);
! 	  cgraph_expand_function (node);
  	  break;
  
  	default:
--- 333,339 ----
  	     directly.  */
  	  node->process = 0;
            cgraph_call_function_insertion_hooks (node);
! 	  expand_function (node);
  	  break;
  
  	default:
*************** cgraph_reset_node (struct cgraph_node *n
*** 372,383 ****
  static bool
  referred_to_p (symtab_node node)
  {
-   int i;
    struct ipa_ref *ref;
  
!   for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref);
!        i++)
      return true;
    if (symtab_function_p (node) && cgraph (node)->callers)
      return true;
    return false;
--- 381,392 ----
  static bool
  referred_to_p (symtab_node node)
  {
    struct ipa_ref *ref;
  
!   /* See if there are any refrences at all.  */
!   if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref))
      return true;
+   /* For functions check also calls.  */
    if (symtab_function_p (node) && cgraph (node)->callers)
      return true;
    return false;
*************** cgraph_add_new_function (tree fndecl, bo
*** 518,524 ****
  	  execute_pass_list (pass_early_local_passes.pass.sub);
  	bitmap_obstack_release (NULL);
  	pop_cfun ();
! 	cgraph_expand_function (node);
  	current_function_decl = NULL;
  	break;
  
--- 527,533 ----
  	  execute_pass_list (pass_early_local_passes.pass.sub);
  	bitmap_obstack_release (NULL);
  	pop_cfun ();
! 	expand_function (node);
  	current_function_decl = NULL;
  	break;
  
*************** cgraph_add_new_function (tree fndecl, bo
*** 533,551 ****
      DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
  }
  
  /* Output all asm statements we have stored up to be output.  */
  
  static void
! cgraph_output_pending_asms (void)
  {
!   struct cgraph_asm_node *can;
  
    if (seen_error ())
      return;
  
!   for (can = cgraph_asm_nodes; can; can = can->next)
      assemble_asm (can->asm_str);
!   cgraph_asm_nodes = NULL;
  }
  
  /* Analyze the function scheduled to be output.  */
--- 542,595 ----
      DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality ();
  }
  
+ /* Add a top-level asm statement to the list.  */
+ 
+ struct asm_node *
+ add_asm_node (tree asm_str)
+ {
+   struct asm_node *node;
+ 
+   node = ggc_alloc_cleared_asm_node ();
+   node->asm_str = asm_str;
+   node->order = symtab_order++;
+   node->next = NULL;
+   if (asm_nodes == NULL)
+     asm_nodes = node;
+   else
+     asm_last_node->next = node;
+   asm_last_node = node;
+   return node;
+ }
+ 
  /* Output all asm statements we have stored up to be output.  */
  
  static void
! output_asm_statements (void)
  {
!   struct asm_node *can;
  
    if (seen_error ())
      return;
  
!   for (can = asm_nodes; can; can = can->next)
      assemble_asm (can->asm_str);
!   asm_nodes = NULL;
! }
! 
! /* C++ FE sometimes change linkage flags after producing same body aliases.  */
! void
! fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alias)
! {
!   DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (alias);
!   if (TREE_PUBLIC (node->symbol.decl))
!     {
!       DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (alias);
!       DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (alias);
!       DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (alias);
!       if (DECL_ONE_ONLY (alias)
! 	  && !node->symbol.same_comdat_group)
! 	symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target);
!     }
  }
  
  /* Analyze the function scheduled to be output.  */
*************** cgraph_analyze_function (struct cgraph_n
*** 576,614 ****
  			      IPA_REF_ALIAS, NULL);
        if (node->same_body_alias)
  	{ 
- 	  DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (node->thunk.alias);
  	  DECL_DECLARED_INLINE_P (node->symbol.decl)
  	     = DECL_DECLARED_INLINE_P (node->thunk.alias);
  	  DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
  	     = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
  	}
  
-       /* Fixup visibility nonsences C++ frontend produce on same body aliases.  */
-       if (TREE_PUBLIC (node->symbol.decl) && node->same_body_alias)
- 	{
-           DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->thunk.alias);
- 	  if (DECL_ONE_ONLY (node->thunk.alias))
- 	    {
- 	      DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (node->thunk.alias);
- 	      DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (node->thunk.alias);
- 	      if (DECL_ONE_ONLY (node->thunk.alias) && !node->symbol.same_comdat_group)
- 		{
- 		  struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
- 		  node->symbol.same_comdat_group = (symtab_node)tgt;
- 		  if (!tgt->symbol.same_comdat_group)
- 		    tgt->symbol.same_comdat_group = (symtab_node)node;
- 		  else
- 		    {
- 		      symtab_node n;
- 		      for (n = tgt->symbol.same_comdat_group;
- 			   n->symbol.same_comdat_group != (symtab_node)tgt;
- 			   n = n->symbol.same_comdat_group)
- 			;
- 		      n->symbol.same_comdat_group = (symtab_node)node;
- 		    }
- 		}
- 	    }
- 	}
        if (node->symbol.address_taken)
  	cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
      }
--- 620,632 ----
  			      IPA_REF_ALIAS, NULL);
        if (node->same_body_alias)
  	{ 
  	  DECL_DECLARED_INLINE_P (node->symbol.decl)
  	     = DECL_DECLARED_INLINE_P (node->thunk.alias);
  	  DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)
  	     = DECL_DISREGARD_INLINE_LIMITS (node->thunk.alias);
+ 	  fixup_same_cpp_alias_visibility ((symtab_node) node, (symtab_node) tgt, node->thunk.alias);
  	}
  
        if (node->symbol.address_taken)
  	cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
      }
*************** handle_alias_pairs (void)
*** 1074,1080 ****
  /* Figure out what functions we want to assemble.  */
  
  static void
! cgraph_mark_functions_to_output (void)
  {
    struct cgraph_node *node;
  #ifdef ENABLE_CHECKING
--- 1092,1098 ----
  /* Figure out what functions we want to assemble.  */
  
  static void
! mark_functions_to_output (void)
  {
    struct cgraph_node *node;
  #ifdef ENABLE_CHECKING
*************** cgraph_mark_functions_to_output (void)
*** 1087,1102 ****
    FOR_EACH_FUNCTION (node)
      {
        tree decl = node->symbol.decl;
-       struct cgraph_edge *e;
  
        gcc_assert (!node->process || node->symbol.same_comdat_group);
        if (node->process)
  	continue;
  
-       for (e = node->callers; e; e = e->next_caller)
- 	if (e->inline_failed)
- 	  break;
- 
        /* We need to output all local functions that are used and not
  	 always inlined, as well as those that are reachable from
  	 outside the current compilation unit.  */
--- 1105,1115 ----
*************** assemble_thunks_and_aliases (struct cgra
*** 1544,1550 ****
  /* Expand function specified by NODE.  */
  
  static void
! cgraph_expand_function (struct cgraph_node *node)
  {
    tree decl = node->symbol.decl;
    location_t saved_loc;
--- 1557,1563 ----
  /* Expand function specified by NODE.  */
  
  static void
! expand_function (struct cgraph_node *node)
  {
    tree decl = node->symbol.decl;
    location_t saved_loc;
*************** cgraph_expand_function (struct cgraph_no
*** 1641,1649 ****
    current_function_decl = NULL;
  
    /* It would make a lot more sense to output thunks before function body to get more
!      forward and lest backwarding jumps.  This is however would need solving problem
       with comdats. See PR48668.  Also aliases must come after function itself to
!      make one pass assemblers, like one on AIX happy.  See PR 50689.
       FIXME: Perhaps thunks should be move before function IFF they are not in comdat
       groups.  */
    assemble_thunks_and_aliases (node);
--- 1654,1662 ----
    current_function_decl = NULL;
  
    /* It would make a lot more sense to output thunks before function body to get more
!      forward and lest backwarding jumps.  This however would need solving problem
       with comdats. See PR48668.  Also aliases must come after function itself to
!      make one pass assemblers, like one on AIX, happy.  See PR 50689.
       FIXME: Perhaps thunks should be move before function IFF they are not in comdat
       groups.  */
    assemble_thunks_and_aliases (node);
*************** cgraph_expand_function (struct cgraph_no
*** 1665,1671 ****
     order).  */
  
  static void
! cgraph_expand_all_functions (void)
  {
    struct cgraph_node *node;
    struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
--- 1678,1684 ----
     order).  */
  
  static void
! expand_all_functions (void)
  {
    struct cgraph_node *node;
    struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
*************** cgraph_expand_all_functions (void)
*** 1687,1693 ****
        if (node->process)
  	{
  	  node->process = 0;
! 	  cgraph_expand_function (node);
  	}
      }
    cgraph_process_new_functions ();
--- 1700,1706 ----
        if (node->process)
  	{
  	  node->process = 0;
! 	  expand_function (node);
  	}
      }
    cgraph_process_new_functions ();
*************** struct cgraph_order_sort
*** 1713,1719 ****
    {
      struct cgraph_node *f;
      struct varpool_node *v;
!     struct cgraph_asm_node *a;
    } u;
  };
  
--- 1726,1732 ----
    {
      struct cgraph_node *f;
      struct varpool_node *v;
!     struct asm_node *a;
    } u;
  };
  
*************** struct cgraph_order_sort
*** 1724,1737 ****
     need to be output.  */
  
  static void
! cgraph_output_in_order (void)
  {
    int max;
    struct cgraph_order_sort *nodes;
    int i;
    struct cgraph_node *pf;
    struct varpool_node *pv;
!   struct cgraph_asm_node *pa;
  
    max = symtab_order;
    nodes = XCNEWVEC (struct cgraph_order_sort, max);
--- 1737,1750 ----
     need to be output.  */
  
  static void
! output_in_order (void)
  {
    int max;
    struct cgraph_order_sort *nodes;
    int i;
    struct cgraph_node *pf;
    struct varpool_node *pv;
!   struct asm_node *pa;
  
    max = symtab_order;
    nodes = XCNEWVEC (struct cgraph_order_sort, max);
*************** cgraph_output_in_order (void)
*** 1755,1761 ****
        nodes[i].u.v = pv;
      }
  
!   for (pa = cgraph_asm_nodes; pa; pa = pa->next)
      {
        i = pa->order;
        gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
--- 1768,1774 ----
        nodes[i].u.v = pv;
      }
  
!   for (pa = asm_nodes; pa; pa = pa->next)
      {
        i = pa->order;
        gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
*************** cgraph_output_in_order (void)
*** 1775,1781 ****
  	{
  	case ORDER_FUNCTION:
  	  nodes[i].u.f->process = 0;
! 	  cgraph_expand_function (nodes[i].u.f);
  	  break;
  
  	case ORDER_VAR:
--- 1788,1794 ----
  	{
  	case ORDER_FUNCTION:
  	  nodes[i].u.f->process = 0;
! 	  expand_function (nodes[i].u.f);
  	  break;
  
  	case ORDER_VAR:
*************** cgraph_output_in_order (void)
*** 1794,1800 ****
  	}
      }
  
!   cgraph_asm_nodes = NULL;
    free (nodes);
  }
  
--- 1807,1813 ----
  	}
      }
  
!   asm_nodes = NULL;
    free (nodes);
  }
  
*************** cgraph_function_versioning (struct cgrap
*** 2054,2060 ****
       that is not weak also.
       ??? We cannot use COMDAT linkage because there is no
       ABI support for this.  */
!   cgraph_make_decl_local (new_version_node->symbol.decl);
    DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
    new_version_node->symbol.externally_visible = 0;
    new_version_node->local.local = 1;
--- 2067,2073 ----
       that is not weak also.
       ??? We cannot use COMDAT linkage because there is no
       ABI support for this.  */
!   symtab_make_decl_local (new_version_node->symbol.decl);
    DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0;
    new_version_node->symbol.externally_visible = 0;
    new_version_node->local.local = 1;
*************** cgraph_materialize_all_clones (void)
*** 2275,2281 ****
  /* Perform simple optimizations based on callgraph.  */
  
  void
! cgraph_optimize (void)
  {
    if (seen_error ())
      return;
--- 2288,2294 ----
  /* Perform simple optimizations based on callgraph.  */
  
  void
! compile (void)
  {
    if (seen_error ())
      return;
*************** cgraph_optimize (void)
*** 2294,2299 ****
--- 2307,2316 ----
      fprintf (stderr, "Performing interprocedural optimizations\n");
    cgraph_state = CGRAPH_STATE_IPA;
  
+   /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE.  */
+   if (flag_lto)
+     lto_streamer_hooks_init ();
+ 
    /* Don't run the IPA passes if there was any error or sorry messages.  */
    if (!seen_error ())
      ipa_passes ();
*************** cgraph_optimize (void)
*** 2338,2357 ****
    verify_symtab ();
  #endif
    bitmap_obstack_release (NULL);
!   cgraph_mark_functions_to_output ();
    output_weakrefs ();
  
    cgraph_state = CGRAPH_STATE_EXPANSION;
    if (!flag_toplevel_reorder)
!     cgraph_output_in_order ();
    else
      {
!       cgraph_output_pending_asms ();
! 
!       cgraph_expand_all_functions ();
!       varpool_remove_unreferenced_decls ();
  
!       varpool_assemble_pending_decls ();
      }
  
    cgraph_process_new_functions ();
--- 2355,2372 ----
    verify_symtab ();
  #endif
    bitmap_obstack_release (NULL);
!   mark_functions_to_output ();
    output_weakrefs ();
  
    cgraph_state = CGRAPH_STATE_EXPANSION;
    if (!flag_toplevel_reorder)
!     output_in_order ();
    else
      {
!       output_asm_statements ();
  
!       expand_all_functions ();
!       varpool_output_variables ();
      }
  
    cgraph_process_new_functions ();
*************** cgraph_optimize (void)
*** 2388,2401 ****
  /* Analyze the whole compilation unit once it is parsed completely.  */
  
  void
! cgraph_finalize_compilation_unit (void)
  {
    timevar_push (TV_CGRAPH);
  
-   /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE.  */
-   if (flag_lto)
-     lto_streamer_hooks_init ();
- 
    /* If we're here there's no current function anymore.  Some frontends
       are lazy in clearing these.  */
    current_function_decl = NULL;
--- 2403,2412 ----
  /* Analyze the whole compilation unit once it is parsed completely.  */
  
  void
! finalize_compilation_unit (void)
  {
    timevar_push (TV_CGRAPH);
  
    /* If we're here there's no current function anymore.  Some frontends
       are lazy in clearing these.  */
    current_function_decl = NULL;
*************** cgraph_finalize_compilation_unit (void)
*** 2432,2438 ****
    cgraph_analyze_functions ();
  
    /* Finally drive the pass manager.  */
!   cgraph_optimize ();
  
    timevar_pop (TV_CGRAPH);
  }
--- 2443,2449 ----
    cgraph_analyze_functions ();
  
    /* Finally drive the pass manager.  */
!   compile ();
  
    timevar_pop (TV_CGRAPH);
  }
Index: cp/optimize.c
===================================================================
*** cp/optimize.c	(revision 186961)
--- cp/optimize.c	(working copy)
*************** maybe_clone_body (tree fn)
*** 324,331 ****
  		 *[CD][12]*.  */
  	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
  	      DECL_COMDAT_GROUP (fns[0]) = comdat_group;
! 	      cgraph_add_to_same_comdat_group (cgraph_get_node (clone),
! 					       cgraph_get_node (fns[0]));
  	    }
  	}
  
--- 324,331 ----
  		 *[CD][12]*.  */
  	      comdat_group = cdtor_comdat_group (fns[1], fns[0]);
  	      DECL_COMDAT_GROUP (fns[0]) = comdat_group;
! 	      symtab_add_to_same_comdat_group (symtab_get_node (clone),
! 					       symtab_get_node (fns[0]));
  	    }
  	}
  
*************** maybe_clone_body (tree fn)
*** 337,344 ****
  	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
  	     virtual, it goes into the same comdat group as well.  */
  	  if (comdat_group)
! 	    cgraph_add_to_same_comdat_group (cgraph_get_create_node (clone),
! 					     cgraph_get_node (fns[0]));
  	}
        else if (alias)
  	/* No need to populate body.  */ ;
--- 337,345 ----
  	  /* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
  	     virtual, it goes into the same comdat group as well.  */
  	  if (comdat_group)
! 	    symtab_add_to_same_comdat_group
! 	       ((symtab_node) cgraph_get_create_node (clone),
! 	        symtab_get_node (fns[0]));
  	}
        else if (alias)
  	/* No need to populate body.  */ ;
Index: cp/method.c
===================================================================
*** cp/method.c	(revision 186961)
--- cp/method.c	(working copy)
*************** use_thunk (tree thunk_fndecl, bool emit_
*** 389,395 ****
  				 this_adjusting, fixed_offset, virtual_value,
  				 virtual_offset, alias);
    if (DECL_ONE_ONLY (function))
!     cgraph_add_to_same_comdat_group (thunk_node, funcn);
  
    if (!this_adjusting
        || !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
--- 389,396 ----
  				 this_adjusting, fixed_offset, virtual_value,
  				 virtual_offset, alias);
    if (DECL_ONE_ONLY (function))
!     symtab_add_to_same_comdat_group ((symtab_node) thunk_node,
! 				     (symtab_node) funcn);
  
    if (!this_adjusting
        || !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
Index: cp/semantics.c
===================================================================
*** cp/semantics.c	(revision 186961)
--- cp/semantics.c	(working copy)
*************** maybe_add_lambda_conv_op (tree type)
*** 9330,9337 ****
    if (DECL_ONE_ONLY (statfn))
      {
        /* Put the thunk in the same comdat group as the call op.  */
!       cgraph_add_to_same_comdat_group (cgraph_get_create_node (statfn),
! 				       cgraph_get_create_node (callop));
      }
    body = begin_function_body ();
    compound_stmt = begin_compound_stmt (0);
--- 9330,9338 ----
    if (DECL_ONE_ONLY (statfn))
      {
        /* Put the thunk in the same comdat group as the call op.  */
!       symtab_add_to_same_comdat_group
! 	 ((symtab_node) cgraph_get_create_node (statfn),
!           (symtab_node) cgraph_get_create_node (callop));
      }
    body = begin_function_body ();
    compound_stmt = begin_compound_stmt (0);
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 186961)
--- cp/decl2.c	(working copy)
*************** maybe_emit_vtables (tree ctype)
*** 1830,1836 ****
    tree vtbl;
    tree primary_vtbl;
    int needed = 0;
!   struct varpool_node *current = NULL, *last = NULL, *first = NULL;
  
    /* If the vtables for this class have already been emitted there is
       nothing more to do.  */
--- 1830,1836 ----
    tree vtbl;
    tree primary_vtbl;
    int needed = 0;
!   struct varpool_node *current = NULL, *last = NULL;
  
    /* If the vtables for this class have already been emitted there is
       nothing more to do.  */
*************** maybe_emit_vtables (tree ctype)
*** 1894,1909 ****
  	{
  	  current = varpool_node (vtbl);
  	  if (last)
! 	    last->symbol.same_comdat_group = (symtab_node) current;
  	  last = current;
- 	  if (!first)
- 	    first = current;
  	}
      }
  
-   if (first != last)
-     last->symbol.same_comdat_group = (symtab_node)first;
- 
    /* Since we're writing out the vtable here, also write the debug
       info.  */
    note_debug_info_needed (ctype);
--- 1894,1904 ----
  	{
  	  current = varpool_node (vtbl);
  	  if (last)
! 	    symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
  	  last = current;
  	}
      }
  
    /* Since we're writing out the vtable here, also write the debug
       info.  */
    note_debug_info_needed (ctype);
*************** cp_write_global_declarations (void)
*** 4027,4033 ****
    timevar_stop (TV_PHASE_DEFERRED);
    timevar_start (TV_PHASE_CGRAPH);
  
!   cgraph_finalize_compilation_unit ();
  
    timevar_stop (TV_PHASE_CGRAPH);
    timevar_start (TV_PHASE_CHECK_DBGINFO);
--- 4022,4028 ----
    timevar_stop (TV_PHASE_DEFERRED);
    timevar_start (TV_PHASE_CGRAPH);
  
!   finalize_compilation_unit ();
  
    timevar_stop (TV_PHASE_CGRAPH);
    timevar_start (TV_PHASE_CHECK_DBGINFO);
Index: cp/parser.c
===================================================================
*** cp/parser.c	(revision 186961)
--- cp/parser.c	(working copy)
*************** cp_parser_asm_definition (cp_parser* par
*** 15375,15381 ****
  	    }
  	}
        else
! 	cgraph_add_asm_node (string);
      }
  }
  
--- 15375,15381 ----
  	    }
  	}
        else
! 	add_asm_node (string);
      }
  }
  
Index: lto-streamer-out.c
===================================================================
*** lto-streamer-out.c	(revision 186961)
--- lto-streamer-out.c	(working copy)
*************** void
*** 968,979 ****
  lto_output_toplevel_asms (void)
  {
    struct output_block *ob;
!   struct cgraph_asm_node *can;
    char *section_name;
    struct lto_output_stream *header_stream;
    struct lto_asm_header header;
  
!   if (! cgraph_asm_nodes)
      return;
  
    ob = create_output_block (LTO_section_asm);
--- 968,979 ----
  lto_output_toplevel_asms (void)
  {
    struct output_block *ob;
!   struct asm_node *can;
    char *section_name;
    struct lto_output_stream *header_stream;
    struct lto_asm_header header;
  
!   if (! asm_nodes)
      return;
  
    ob = create_output_block (LTO_section_asm);
*************** lto_output_toplevel_asms (void)
*** 981,987 ****
    /* Make string 0 be a NULL string.  */
    streamer_write_char_stream (ob->string_stream, 0);
  
!   for (can = cgraph_asm_nodes; can; can = can->next)
      {
        streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
        streamer_write_hwi (ob, can->order);
--- 981,987 ----
    /* Make string 0 be a NULL string.  */
    streamer_write_char_stream (ob->string_stream, 0);
  
!   for (can = asm_nodes; can; can = can->next)
      {
        streamer_write_string_cst (ob, ob->main_stream, can->asm_str);
        streamer_write_hwi (ob, can->order);
Index: dwarf2out.c
===================================================================
*** dwarf2out.c	(revision 186961)
--- dwarf2out.c	(working copy)
*************** dwarf2out_init (const char *filename ATT
*** 20378,20384 ****
    text_section_line_info->end_label = text_end_label;
  }
  
! /* Called before cgraph_optimize starts outputtting functions, variables
     and toplevel asms into assembly.  */
  
  static void
--- 20378,20384 ----
    text_section_line_info->end_label = text_end_label;
  }
  
! /* Called before compile () starts outputtting functions, variables
     and toplevel asms into assembly.  */
  
  static void
Index: go/gofrontend/gogo-tree.cc
===================================================================
*** go/gofrontend/gogo-tree.cc	(revision 186961)
--- go/gofrontend/gogo-tree.cc	(working copy)
*************** Gogo::write_globals()
*** 930,936 ****
  
    wrapup_global_declarations(vec, count);
  
!   cgraph_finalize_compilation_unit();
  
    check_global_declarations(vec, count);
    emit_debug_global_declarations(vec, count);
--- 930,936 ----
  
    wrapup_global_declarations(vec, count);
  
!   finalize_compilation_unit();
  
    check_global_declarations(vec, count);
    emit_debug_global_declarations(vec, count);
Index: ada/gcc-interface/utils.c
===================================================================
*** ada/gcc-interface/utils.c	(revision 186961)
--- ada/gcc-interface/utils.c	(working copy)
*************** rest_of_subprog_body_compilation (tree s
*** 2036,2042 ****
    /* Dump functions before gimplification.  */
    dump_function (TDI_original, subprog_decl);
  
-   /* ??? This special handling of nested functions is probably obsolete.  */
    if (!decl_function_context (subprog_decl))
      cgraph_finalize_function (subprog_decl, false);
    else
--- 2036,2041 ----
*************** gnat_write_global_declarations (void)
*** 4907,4915 ****
      if (TREE_CODE (iter) == TYPE_DECL)
        debug_hooks->global_decl (iter);
  
!   /* Proceed to optimize and emit assembly.
!      FIXME: shouldn't be the front end's responsibility to call this.  */
!   cgraph_finalize_compilation_unit ();
  
    /* After cgraph has had a chance to emit everything that's going to
       be emitted, output debug information for the rest of globals.  */
--- 4906,4913 ----
      if (TREE_CODE (iter) == TYPE_DECL)
        debug_hooks->global_decl (iter);
  
!   /* Proceed to optimize and emit assembly. */
!   finalize_compilation_unit ();
  
    /* After cgraph has had a chance to emit everything that's going to
       be emitted, output debug information for the rest of globals.  */
Index: lto-streamer-in.c
===================================================================
*** lto-streamer-in.c	(revision 186961)
--- lto-streamer-in.c	(working copy)
*************** lto_input_toplevel_asms (struct lto_file
*** 1223,1229 ****
  
    while ((str = streamer_read_string_cst (data_in, &ib)))
      {
!       struct cgraph_asm_node *node = cgraph_add_asm_node (str);
        node->order = streamer_read_hwi (&ib) + order_base;
        if (node->order >= symtab_order)
  	symtab_order = node->order + 1;
--- 1223,1229 ----
  
    while ((str = streamer_read_string_cst (data_in, &ib)))
      {
!       struct asm_node *node = add_asm_node (str);
        node->order = streamer_read_hwi (&ib) + order_base;
        if (node->order >= symtab_order)
  	symtab_order = node->order + 1;
Index: c-decl.c
===================================================================
*** c-decl.c	(revision 186961)
--- c-decl.c	(working copy)
*************** c_write_global_declarations (void)
*** 10040,10046 ****
  
    /* We're done parsing; proceed to optimize and emit assembly.
       FIXME: shouldn't be the front end's responsibility to call this.  */
!   cgraph_finalize_compilation_unit ();
  
    timevar_stop (TV_PHASE_CGRAPH);
    timevar_start (TV_PHASE_DBGINFO);
--- 10040,10046 ----
  
    /* We're done parsing; proceed to optimize and emit assembly.
       FIXME: shouldn't be the front end's responsibility to call this.  */
!   finalize_compilation_unit ();
  
    timevar_stop (TV_PHASE_CGRAPH);
    timevar_start (TV_PHASE_DBGINFO);
Index: fortran/f95-lang.c
===================================================================
*** fortran/f95-lang.c	(revision 186961)
--- fortran/f95-lang.c	(working copy)
*************** gfc_finish (void)
*** 242,252 ****
  /* ??? This is something of a hack.
  
     Emulated tls lowering needs to see all TLS variables before we call
!    cgraph_finalize_compilation_unit.  The C/C++ front ends manage this
     by calling decl_rest_of_compilation on each global and static variable
     as they are seen.  The Fortran front end waits until this hook.
  
!    A Correct solution is for cgraph_finalize_compilation_unit not to be
     called during the WRITE_GLOBALS langhook, and have that hook only do what
     its name suggests and write out globals.  But the C++ and Java front ends
     have (unspecified) problems with aliases that gets in the way.  It has
--- 242,252 ----
  /* ??? This is something of a hack.
  
     Emulated tls lowering needs to see all TLS variables before we call
!    finalize_compilation_unit.  The C/C++ front ends manage this
     by calling decl_rest_of_compilation on each global and static variable
     as they are seen.  The Fortran front end waits until this hook.
  
!    A Correct solution is for finalize_compilation_unit not to be
     called during the WRITE_GLOBALS langhook, and have that hook only do what
     its name suggests and write out globals.  But the C++ and Java front ends
     have (unspecified) problems with aliases that gets in the way.  It has
Index: langhooks.c
===================================================================
*** langhooks.c	(revision 186961)
--- langhooks.c	(working copy)
*************** write_global_declarations (void)
*** 300,306 ****
  
    /* This lang hook is dual-purposed, and also finalizes the
       compilation unit.  */
!   cgraph_finalize_compilation_unit ();
  
    /* Really define vars that have had only a tentative definition.
       Really output inline functions that must actually be callable
--- 300,306 ----
  
    /* This lang hook is dual-purposed, and also finalizes the
       compilation unit.  */
!   finalize_compilation_unit ();
  
    /* Really define vars that have had only a tentative definition.
       Really output inline functions that must actually be callable
Index: ipa.c
===================================================================
*** ipa.c	(revision 186961)
--- ipa.c	(working copy)
*************** cgraph_externally_visible_p (struct cgra
*** 598,604 ****
      return true;
  
    /* If linker counts on us, we must preserve the function.  */
!   if (cgraph_used_from_object_file_p (node))
      return true;
    if (DECL_PRESERVE_P (node->symbol.decl))
      return true;
--- 598,604 ----
      return true;
  
    /* If linker counts on us, we must preserve the function.  */
!   if (symtab_used_from_object_file_p ((symtab_node) node))
      return true;
    if (DECL_PRESERVE_P (node->symbol.decl))
      return true;
*************** varpool_externally_visible_p (struct var
*** 657,663 ****
      return true;
  
    /* If linker counts on us, we must preserve the function.  */
!   if (varpool_used_from_object_file_p (vnode))
      return true;
  
    if (DECL_HARD_REGISTER (vnode->symbol.decl))
--- 657,663 ----
      return true;
  
    /* If linker counts on us, we must preserve the function.  */
!   if (symtab_used_from_object_file_p ((symtab_node) vnode))
      return true;
  
    if (DECL_HARD_REGISTER (vnode->symbol.decl))
*************** varpool_externally_visible_p (struct var
*** 678,684 ****
       Even if the linker clams the symbol is unused, never bring internal
       symbols that are declared by user as used or externally visible.
       This is needed for i.e. references from asm statements.   */
!   if (varpool_used_from_object_file_p (vnode))
      return true;
    if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
      return false;
--- 678,684 ----
       Even if the linker clams the symbol is unused, never bring internal
       symbols that are declared by user as used or externally visible.
       This is needed for i.e. references from asm statements.   */
!   if (symtab_used_from_object_file_p ((symtab_node) vnode))
      return true;
    if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
      return false;
*************** varpool_externally_visible_p (struct var
*** 716,736 ****
    return false;
  }
  
- /* Dissolve the same_comdat_group list in which NODE resides.  */
- 
- static void
- dissolve_same_comdat_group_list (symtab_node node)
- {
-   symtab_node n = node, next;
-   do
-     {
-       next = n->symbol.same_comdat_group;
-       n->symbol.same_comdat_group = NULL;
-       n = next;
-     }
-   while (n != node);
- }
- 
  /* Mark visibility of all functions.
  
     A local function is one whose calls can occur only in the current
--- 716,721 ----
*************** function_and_variable_visibility (bool w
*** 825,831 ****
  		 all of them have to be, otherwise it is a front-end bug.  */
  	      gcc_assert (DECL_EXTERNAL (n->symbol.decl));
  #endif
! 	  dissolve_same_comdat_group_list ((symtab_node) node);
  	}
        gcc_assert ((!DECL_WEAK (node->symbol.decl)
  		  && !DECL_COMDAT (node->symbol.decl))
--- 810,816 ----
  		 all of them have to be, otherwise it is a front-end bug.  */
  	      gcc_assert (DECL_EXTERNAL (n->symbol.decl));
  #endif
! 	  symtab_dissolve_same_comdat_group_list ((symtab_node) node);
  	}
        gcc_assert ((!DECL_WEAK (node->symbol.decl)
  		  && !DECL_COMDAT (node->symbol.decl))
*************** function_and_variable_visibility (bool w
*** 845,858 ****
  	{
  	  gcc_assert (whole_program || in_lto_p
  		      || !TREE_PUBLIC (node->symbol.decl));
! 	  cgraph_make_decl_local (node->symbol.decl);
  	  node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
  	  if (node->symbol.same_comdat_group)
  	    /* cgraph_externally_visible_p has already checked all other nodes
  	       in the group and they will all be made local.  We need to
  	       dissolve the group at once so that the predicate does not
  	       segfault though. */
! 	    dissolve_same_comdat_group_list ((symtab_node) node);
  	}
  
        if (node->thunk.thunk_p
--- 830,843 ----
  	{
  	  gcc_assert (whole_program || in_lto_p
  		      || !TREE_PUBLIC (node->symbol.decl));
! 	  symtab_make_decl_local (node->symbol.decl);
  	  node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
  	  if (node->symbol.same_comdat_group)
  	    /* cgraph_externally_visible_p has already checked all other nodes
  	       in the group and they will all be made local.  We need to
  	       dissolve the group at once so that the predicate does not
  	       segfault though. */
! 	    symtab_dissolve_same_comdat_group_list ((symtab_node) node);
  	}
  
        if (node->thunk.thunk_p
*************** function_and_variable_visibility (bool w
*** 921,929 ****
        if (!vnode->symbol.externally_visible)
  	{
  	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
! 	  cgraph_make_decl_local (vnode->symbol.decl);
  	  if (vnode->symbol.same_comdat_group)
! 	    dissolve_same_comdat_group_list ((symtab_node) vnode);
  	  vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
  	}
       gcc_assert (TREE_STATIC (vnode->symbol.decl));
--- 906,914 ----
        if (!vnode->symbol.externally_visible)
  	{
  	  gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
! 	  symtab_make_decl_local (vnode->symbol.decl);
  	  if (vnode->symbol.same_comdat_group)
! 	    symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
  	  vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
  	}
       gcc_assert (TREE_STATIC (vnode->symbol.decl));
Index: lto/lto.c
===================================================================
*** lto/lto.c	(revision 186961)
--- lto/lto.c	(working copy)
*************** lto_main (void)
*** 2116,2122 ****
  
  	  /* Let the middle end know that we have read and merged all of
  	     the input files.  */ 
! 	  cgraph_optimize ();
  
  	  /* FIXME lto, if the processes spawned by WPA fail, we miss
  	     the chance to print WPA's report, so WPA will call
--- 2116,2122 ----
  
  	  /* Let the middle end know that we have read and merged all of
  	     the input files.  */ 
! 	  compile ();
  
  	  /* FIXME lto, if the processes spawned by WPA fail, we miss
  	     the chance to print WPA's report, so WPA will call
Index: lto/lto-partition.c
===================================================================
*** lto/lto-partition.c	(revision 186961)
--- lto/lto-partition.c	(working copy)
*************** partition_cgraph_node_p (struct cgraph_n
*** 270,276 ****
    if (DECL_EXTERNAL (node->symbol.decl)
        || (DECL_COMDAT (node->symbol.decl)
  	  && !node->symbol.force_output
! 	  && !cgraph_used_from_object_file_p (node)))
      return false;
    if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
      return false;
--- 270,276 ----
    if (DECL_EXTERNAL (node->symbol.decl)
        || (DECL_COMDAT (node->symbol.decl)
  	  && !node->symbol.force_output
! 	  && !symtab_used_from_object_file_p ((symtab_node) node)))
      return false;
    if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
      return false;
*************** partition_varpool_node_p (struct varpool
*** 289,295 ****
    if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
        || (DECL_COMDAT (vnode->symbol.decl)
  	  && !vnode->symbol.force_output
! 	  && !varpool_used_from_object_file_p (vnode)))
      return false;
    if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
      return false;
--- 289,295 ----
    if (DECL_IN_CONSTANT_POOL (vnode->symbol.decl)
        || (DECL_COMDAT (vnode->symbol.decl)
  	  && !vnode->symbol.force_output
! 	  && !symtab_used_from_object_file_p ((symtab_node) vnode)))
      return false;
    if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
      return false;
Index: symtab.c
===================================================================
*** symtab.c	(revision 186961)
--- symtab.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 30,35 ****
--- 30,51 ----
  #include "cgraph.h"
  #include "diagnostic.h"
  #include "timevar.h"
+ #include "lto-streamer.h"
+ #include "rtl.h"
+ 
+ const char * const ld_plugin_symbol_resolution_names[]=
+ {
+   "",
+   "undef",
+   "prevailing_def",
+   "prevailing_def_ironly",
+   "preempted_reg",
+   "preempted_ir",
+   "resolved_ir",
+   "resolved_exec",
+   "resolved_dyn",
+   "prevailing_def_ironly_exp"
+ };
  
  /* Hash table used to convert declarations into nodes.  */
  static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
*************** change_decl_assembler_name (tree decl, t
*** 335,340 ****
--- 351,399 ----
      }
  }
  
+ /* Add NEW_ to the same comdat group that OLD is in.  */
+ 
+ void
+ symtab_add_to_same_comdat_group (symtab_node new_node,
+ 				 symtab_node old_node)
+ {
+   gcc_assert (DECL_ONE_ONLY (old_node->symbol.decl));
+   gcc_assert (!new_node->symbol.same_comdat_group);
+   gcc_assert (new_node != old_node);
+ 
+   DECL_COMDAT_GROUP (new_node->symbol.decl) = DECL_COMDAT_GROUP (old_node->symbol.decl);
+   new_node->symbol.same_comdat_group = old_node;
+   if (!old_node->symbol.same_comdat_group)
+     old_node->symbol.same_comdat_group = new_node;
+   else
+     {
+       symtab_node n;
+       for (n = old_node->symbol.same_comdat_group;
+ 	   n->symbol.same_comdat_group != old_node;
+ 	   n = n->symbol.same_comdat_group)
+ 	;
+       n->symbol.same_comdat_group = new_node;
+     }
+ }
+ 
+ /* Dissolve the same_comdat_group list in which NODE resides.  */
+ 
+ void
+ symtab_dissolve_same_comdat_group_list (symtab_node node)
+ {
+   symtab_node n = node, next;
+ 
+   if (!node->symbol.same_comdat_group)
+     return;
+   do
+     {
+       next = n->symbol.same_comdat_group;
+       n->symbol.same_comdat_group = NULL;
+       n = next;
+     }
+   while (n != node);
+ }
+ 
  /* Return printable assembler name of NODE.
     This function is used only for debugging.  When assembler name
     is unknown go with identifier name.  */
*************** verify_symtab (void)
*** 611,614 ****
--- 670,751 ----
     verify_symtab_node (node);
  }
  
+ /* Return true when RESOLUTION indicate that linker will use
+    the symbol from non-LTO object files.  */
+ 
+ bool
+ resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
+ {
+   return (resolution == LDPR_PREVAILING_DEF
+           || resolution == LDPR_PREEMPTED_REG
+           || resolution == LDPR_RESOLVED_EXEC
+           || resolution == LDPR_RESOLVED_DYN);
+ }
+ 
+ /* Return true when NODE is known to be used from other (non-LTO) object file.
+    Known only when doing LTO via linker plugin.  */
+ 
+ bool
+ symtab_used_from_object_file_p (symtab_node node)
+ {
+   if (!TREE_PUBLIC (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl))
+     return false;
+   if (resolution_used_from_other_file_p (node->symbol.resolution))
+     return true;
+   return false;
+ }
+ 
+ /* Make DECL local.  FIXME: We shouldn't need to mess with rtl this early,
+    but other code such as notice_global_symbol generates rtl.  */
+ void
+ symtab_make_decl_local (tree decl)
+ {
+   rtx rtl, symbol;
+ 
+   if (TREE_CODE (decl) == VAR_DECL)
+     DECL_COMMON (decl) = 0;
+   else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ 
+   if (DECL_ONE_ONLY (decl) || DECL_COMDAT (decl))
+     {
+       /* It is possible that we are linking against library defining same COMDAT
+ 	 function.  To avoid conflict we need to rename our local name of the
+ 	 function just in the case WHOPR partitioning decide to make it hidden
+ 	 to avoid cross partition references.  */
+       if (flag_wpa)
+ 	{
+ 	  const char *old_name;
+           symtab_node node = symtab_get_node (decl);
+ 	  old_name  = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ 	  change_decl_assembler_name (decl,
+ 				      clone_function_name (decl, "local"));
+ 	  if (node->symbol.lto_file_data)
+ 	    lto_record_renamed_decl (node->symbol.lto_file_data,
+ 				     old_name,
+ 				     IDENTIFIER_POINTER
+ 				       (DECL_ASSEMBLER_NAME (decl)));
+ 	}
+       DECL_SECTION_NAME (decl) = 0;
+       DECL_COMDAT (decl) = 0;
+     }
+   DECL_COMDAT_GROUP (decl) = 0;
+   DECL_WEAK (decl) = 0;
+   DECL_EXTERNAL (decl) = 0;
+   TREE_PUBLIC (decl) = 0;
+   if (!DECL_RTL_SET_P (decl))
+     return;
+ 
+   /* Update rtl flags.  */
+   make_decl_rtl (decl);
+ 
+   rtl = DECL_RTL (decl);
+   if (!MEM_P (rtl))
+     return;
+ 
+   symbol = XEXP (rtl, 0);
+   if (GET_CODE (symbol) != SYMBOL_REF)
+     return;
+ 
+   SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
+ }
  #include "gt-symtab.h"
Index: passes.c
===================================================================
*** passes.c	(revision 186961)
--- passes.c	(working copy)
*************** register_pass (struct register_pass_info
*** 1248,1266 ****
  /* Construct the pass tree.  The sequencing of passes is driven by
     the cgraph routines:
  
!    cgraph_finalize_compilation_unit ()
         for each node N in the cgraph
  	   cgraph_analyze_function (N)
  	       cgraph_lower_function (N) -> all_lowering_passes
  
!    If we are optimizing, cgraph_optimize is then invoked:
  
!    cgraph_optimize ()
         ipa_passes () 			-> all_small_ipa_passes
!        cgraph_expand_all_functions ()
             for each node N in the cgraph
! 	       cgraph_expand_function (N)
! 		  tree_rest_of_compilation (DECL (N))  -> all_passes
  */
  
  void
--- 1248,1271 ----
  /* Construct the pass tree.  The sequencing of passes is driven by
     the cgraph routines:
  
!    finalize_compilation_unit ()
         for each node N in the cgraph
  	   cgraph_analyze_function (N)
  	       cgraph_lower_function (N) -> all_lowering_passes
  
!    If we are optimizing, compile is then invoked:
  
!    compile ()
         ipa_passes () 			-> all_small_ipa_passes
! 					-> Analysis of all_regular_ipa_passes
! 	* possible LTO streaming at copmilation time *
! 					-> Execution of all_regular_ipa_passes
! 	* possible LTO streaming at link time *
! 					-> all_late_ipa_passes
!        expand_all_functions ()
             for each node N in the cgraph
! 	       expand_function (N)      -> Transformation of all_regular_ipa_passes
! 				        -> all_passes
  */
  
  void
Index: c-parser.c
===================================================================
*** c-parser.c	(revision 186961)
--- c-parser.c	(working copy)
*************** c_parser_asm_definition (c_parser *parse
*** 1792,1798 ****
  {
    tree asm_str = c_parser_simple_asm_expr (parser);
    if (asm_str)
!     cgraph_add_asm_node (asm_str);
    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  }
  
--- 1792,1798 ----
  {
    tree asm_str = c_parser_simple_asm_expr (parser);
    if (asm_str)
!     add_asm_node (asm_str);
    c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
  }
  
Index: varpool.c
===================================================================
*** varpool.c	(revision 186961)
--- varpool.c	(working copy)
*************** varpool_analyze_node (struct varpool_nod
*** 237,270 ****
  	  }
        if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
  	ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL);
-       /* C++ FE sometimes change linkage flags after producing same body aliases.  */
        if (node->extra_name_alias)
  	{
  	  DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of);
- 	  TREE_PUBLIC (node->symbol.decl) = TREE_PUBLIC (node->alias_of);
  	  DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of);
  	  DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of);
! 	  if (TREE_PUBLIC (node->symbol.decl))
! 	    {
! 	      DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (node->alias_of);
! 	      DECL_COMDAT_GROUP (node->symbol.decl) = DECL_COMDAT_GROUP (node->alias_of);
! 	      if (DECL_ONE_ONLY (node->alias_of)
! 		  && !node->symbol.same_comdat_group)
! 		{
! 		  node->symbol.same_comdat_group = (symtab_node)tgt;
! 		  if (!tgt->symbol.same_comdat_group)
! 		    tgt->symbol.same_comdat_group = (symtab_node)node;
! 		  else
! 		    {
! 		      symtab_node n;
! 		      for (n = tgt->symbol.same_comdat_group;
! 			   n->symbol.same_comdat_group != (symtab_node)tgt;
! 			   n = n->symbol.same_comdat_group)
! 			;
! 		      n->symbol.same_comdat_group = (symtab_node)node;
! 		    }
! 		}
! 	    }
  	}
      }
    else if (DECL_INITIAL (decl))
--- 237,249 ----
  	  }
        if (!VEC_length (ipa_ref_t, node->symbol.ref_list.references))
  	ipa_record_reference ((symtab_node)node, (symtab_node)tgt, IPA_REF_ALIAS, NULL);
        if (node->extra_name_alias)
  	{
  	  DECL_WEAK (node->symbol.decl) = DECL_WEAK (node->alias_of);
  	  DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (node->alias_of);
  	  DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (node->alias_of);
! 	  fixup_same_cpp_alias_visibility ((symtab_node) node,
! 					   (symtab_node) tgt, node->alias_of);
  	}
      }
    else if (DECL_INITIAL (decl))
*************** enqueue_node (struct varpool_node *node,
*** 331,337 ****
     reachability starting from variables that are either externally visible
     or was referred from the asm output routines.  */
  
! void
  varpool_remove_unreferenced_decls (void)
  {
    struct varpool_node *next, *node;
--- 310,316 ----
     reachability starting from variables that are either externally visible
     or was referred from the asm output routines.  */
  
! static void
  varpool_remove_unreferenced_decls (void)
  {
    struct varpool_node *next, *node;
*************** varpool_finalize_named_section_flags (st
*** 413,419 ****
  
  /* Output all variables enqueued to be assembled.  */
  bool
! varpool_assemble_pending_decls (void)
  {
    bool changed = false;
    struct varpool_node *node;
--- 392,398 ----
  
  /* Output all variables enqueued to be assembled.  */
  bool
! varpool_output_variables (void)
  {
    bool changed = false;
    struct varpool_node *node;
*************** varpool_assemble_pending_decls (void)
*** 421,426 ****
--- 400,407 ----
    if (seen_error ())
      return false;
  
+   varpool_remove_unreferenced_decls ();
+ 
    timevar_push (TV_VAROUT);
  
    FOR_EACH_DEFINED_VARIABLE (node)
*************** varpool_extra_name_alias (tree alias, tr
*** 501,519 ****
    return alias_node;
  }
  
- /* Return true when NODE is known to be used from other (non-LTO) object file.
-    Known only when doing LTO via linker plugin.  */
- 
- bool
- varpool_used_from_object_file_p (struct varpool_node *node)
- {
-   if (!TREE_PUBLIC (node->symbol.decl))
-     return false;
-   if (resolution_used_from_other_file_p (node->symbol.resolution))
-     return true;
-   return false;
- }
- 
  /* Call calback on NODE and aliases asociated to NODE. 
     When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
     skipped. */
--- 482,487 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]