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]

Symtab cleanups 1/17


Hi,
this patch is first of series that cleanups symtab code and allows more sharing
of code across variables and funtions.

Both variables and functions can be either external declarations, definitions
or aliases.  This patch make sit explicit by unifying the flags into
symtab_base rather than having separate flags for variables and functios.

I also renamed "finalized" flag into "definition" (to signify that symbol
is defined) and replaced most of "analyzed" flag uses by it.  I think
it is easier to follow even when all definitions are analyzed most
of the time through the compilation.

I tried to avoid too many changes in the renaming happy patch.  Some
were however too tangled together. In partiuclar I cleaned up unreacahble
function/variable removal.

I also renamed some accesors to the alias functions.
cgraph_alias_aliased_node, varpool_alias_aliased_node are now
cgraph_alias_target, varpool_alias_target that are both just simple
wrappers around symtab_alias_target. "target" is the term used in most of
alias code and it makes no sense to avoid it.

There is also new symtab_alias_ultimate_target to walk aliases on symtab leve.

Bootstrapped/regtested x86_64-linux.  The patch depends on the change of order
of OMP passes, so I plan to commit it shortly afterwards.

	* cgraph.h (symtab_node_base): Add definition, alias and analyzed
	flags; reorder rest of fields in more consistent way.
	(varpool_node): Remove analyzed, finalized and alias.
	(cgraph_ndoe): Likewise.
	(symtab_alias_ultimate_target): New function.
	(cgraph_function_node): Move offline.
	(cgraph_reset_node): Declare.
	(cgraph_comdat_can_be_unshared_p): Remove.
	(varpool_remove_initializer): Declare.
	(varpool_first_defined_variable, varpool_next_defined_variable
	cgraph_first_defined_function, cgraph_next_defined_function): Update.
	(cgraph_function_with_gimple_body_p): Update.
	(varpool_all_refs_explicit_p): Update.
	(symtab_alias_target): New function.
	(cgraph_alias_aliased_node, varpool_alias_aliased_node): Rename to ...
	(cgraph_alias_target, varpool_alias_target): .. this one; simplify.
	(cgraph_function_or_thunk_node): Simplify using symtab_alias_ultimate_target.
	(varpool_variable_node): Likewise.
	* cgraph.c (cgraph_create_function_alias): Update.
	(cgraph_add_thunk): Update.
	(cgraph_remove_node): Update.
	(dump_cgraph_node): Do not dump removed flags.
	(cgraph_function_body_availability): Update.
	(cgraph_propagate_frequency): Update.
	(verify_cgraph_node): Check sanity of local flag.
	(cgraph_function_node): Move here from cgraph.h; revamp for
	cgraph_function_or_thunk_node.
	* lto-symtab.c (lto_varpool_replace_node): Update.
	(lto_symtab_resolve_can_prevail_p): Update.
	(lto_symtab_merge_cgraph_nodes): Update.
	* ipa-cp.c (determine_versionability, initialize_node_lattices,
	propagate_constants_accross_call, devirtualization_time_bonus,
	ipcp_propagate_stage): Update.
	* tree-emutls.c (create_emultls_var, ipa_lower_emutls): Update.
	* ipa-inline-transform.c (clone_inlined_nodes, preserve_function_body_p): Update.
	* ipa-reference.c (propagate): Update.
	(write_node_summary_p): Update.
	* toplev.c (wrapup_global_declaration_2): Update.
	* cgraphunit.c (cgraph_analyze_function): Rename to ...
	(analyze_function) ... this one.
	(cgraph_process_new_functions): Update.
	(cgraph_reset_node): Export.
	(cgraph_finalize_function): Update.
	(cgraph_add_new_function): Update.
	(process_function_and_variable_attributes): Update.
	(varpool_finalize_decl): Update.
	(symbol_finalized): Remove.
	(symbol_finalized_and_needed): Rename to ...
	(symbol_defined_and_needed): ... update.
	(cgraph_analyze_functions): Update.
	(handle_alias_pairs): Update.
	(mark_functions_to_output): Update.
	(assemble_thunk): Update.
	(output_in_order): Update.
	(output_weakrefs): Update.
	(finalize_compilation_unit): Update.
	* lto-cgraph.c (reachable_from_other_partition_p, lto_output_node,
	lto_output_varpool_node, compute_ltrans_boundary, input_overwrite_node,
	input_node, input_varpool_node): Update.
	* dbxout.c (dbxout_expand_expr): Update.
	* cgraphclones.c (cgraph_clone_node): Update.
	(cgraph_copy_node_for_versioning): Update.
	(cgraph_materialize_clone): Update.
	(cgraph_materialize_all_clones): Update.
	* ipa-pure-const.c (analyze_function, pure_const_write_summary,
	propagate_pure_const, propagate_nothrow): Update.
	* lto-streamer-out.c (lto_output, write_symbol): Update.
	* ipa-utils.c (ipa_reverse_postorder): Update.
	* ipa-inline.c (can_inline_edge_p): Update.
	(update_caller_keys, ipa_inline): Update.
	* dwarf2out.c (reference_to_unused,
	premark_types_used_by_global_vars_helper): Update.
	* tree-eh.c (tree_could_trap_p): Update.
	* ipa-split.c (consider_split, execute_split_functions): Update.
	* ipa.c (cgraph_non_local_node_p_1, cgraph_local_node_p,
	 has_addr_references_p): Update;
	move ahead in file for better readability.
	(process_references): Simplify.
	(symtab_remove_unreachable_nodes): Update; cleanup way function/var
	bodies are removed.
	(cgraph_comdat_can_be_unshared_p): Make static.
	(cgraph_externally_visible_p): Update.
	(varpool_externally_visible_p): Update.
	(function_and_variable_visibility): Update.
	* trans-mem.c (get_cg_data, ipa_tm_mayenterirr_function,
	ipa_tm_mark_force_output_node): Update.
	* ipa-inline-analysis.c (dump_inline_summary, initialize_inline_failed,
	estimate_edge_devirt_benefit, inline_generate_summary,
	inline_write_summary): Update.
	* gimple-fold.c (can_refer_decl_in_current_unit_p): Update.
	* ipa-prop.c (ipa_compute_jump_functions): Update.
	(ipa_print_node_params, ipa_prop_read_section, ipa_update_after_lto_read,
	read_replacements_section): Update.
	* varasm.c (mark_decl_referenced): Update.
	(assemble_alias, dump_tm_clone_pairs): Update.
	* tree-inline.c (copy_bb): Update.
	(estimate_num_insns, optimize_inline_calls, tree_function_versioning):
	Update.
	* symtab.c (dump_symtab_base): Print new flags.
	(verify_symtab_base): Verify new flags.
	(symtab_alias_ultimate_target): New function.
	* tree-ssa-structalias.c (get_constraint_for_ssa_var,
	create_variable_info_for, associate_varinfo_to_alias, ipa_pta_execute):
	Update.
	* passes.c (ipa_write_summaries, ipa_write_optimization_summaries): Update.
	* i386.c (ix86_get_function_versions_dispatcher,
	ix86_generate_version_dispatcher_body): Update.
	(fold_builtin_cpu): Use varpool_add_new_variable.
	* varpool.c (varpool_remove_initializer): Break out from ...
	(varpool_remove_node): ... this one.
	(dump_varpool_node, varpool_node_for_asm,
	cgraph_variable_initializer_availability, varpool_analyze_node,
	varpool_assemble_decl, varpool_remove_unreferenced_decls,
	varpool_finalize_named_section_flags, varpool_create_variable_alias): Update

	* decl.c (java_mark_decl_local): Update for new symtab flags.

	* tree.c (cp_fix_function_decl_p): Update for new symtab flags.
	* decl2.c )var_finalized_p, cp_write_global_declarations): Likewise.

	* lto.c (has_analyzed_clone_p, lto_materialize_function): Update for new symtab
	flags.
	* lto-partition.c (get_symbol_class, lto_balanced_map): Likewise.

Index: cgraph.h
===================================================================
*** cgraph.h	(revision 199343)
--- cgraph.h	(working copy)
*************** along with GCC; see the file COPYING3.
*** 30,36 ****
  #include "ipa-ref.h"
  
  /* Symbol table consists of functions and variables.
!    TODO: add labels, constant pool and aliases.  */
  enum symtab_type
  {
    SYMTAB_SYMBOL,
--- 30,36 ----
  #include "ipa-ref.h"
  
  /* Symbol table consists of functions and variables.
!    TODO: add labels and CONST_DECLs.  */
  enum symtab_type
  {
    SYMTAB_SYMBOL,
*************** struct GTY(()) symtab_node_base
*** 48,62 ****
    /* The symbols resolution.  */
    ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
  
!   /* Set when function has address taken.
!      In current implementation it imply needed flag. */
!   unsigned address_taken : 1;
!   /* Set when variable is used from other LTRANS partition.  */
!   unsigned used_from_other_partition : 1;
!   /* Set when function is available in the other LTRANS partition.  
!      During WPA output it is used to mark nodes that are present in
!      multiple partitions.  */
!   unsigned in_other_partition : 1;
    /* Set when function is visible by other units.  */
    unsigned externally_visible : 1;
    /* Needed variables might become dead by optimization.  This flag
--- 48,68 ----
    /* The symbols resolution.  */
    ENUM_BITFIELD (ld_plugin_symbol_resolution) resolution : 8;
  
!   /*** Flags representing the symbol type.  ***/
! 
!   /* True when symbol corresponds to a definition in current unit.
!      set via cgraph_finalize_function or varpool_finalize_decl  */
!   unsigned definition : 1;
!   /* True when symbol is an alias.  
!      Set by assemble_alias.  */
!   unsigned alias : 1;
!   /* Set once the definition was analyzed.  The list of references and
!      other properties are built during analysis.  */
!   unsigned analyzed : 1;
! 
! 
!   /*** Visibility and linkage flags.  ***/
! 
    /* Set when function is visible by other units.  */
    unsigned externally_visible : 1;
    /* Needed variables might become dead by optimization.  This flag
*************** struct GTY(()) symtab_node_base
*** 65,94 ****
    /* True when the name is known to be unique and thus it does not need mangling.  */
    unsigned unique_name : 1;
  
-   /* Ordering of all symtab entries.  */
-   int order;
  
!   tree decl;
  
!   /* Vectors of referring and referenced entities.  */
!   struct ipa_ref_list ref_list;
  
-   /* Circular list of nodes in the same comdat group if non-NULL.  */
-   symtab_node same_comdat_group;
  
!   /* File stream where this node is being written to.  */
!   struct lto_file_decl_data * lto_file_data;
  
    /* Linked list of symbol table entries starting with symtab_nodes.  */
    symtab_node next;
    symtab_node previous;
    /* Linked list of symbols with the same asm name.  There may be multiple
!      entries for single symbol name in the case of LTO resolutions,
!      existence of inline clones, or duplicated declaration. The last case
!      is a long standing bug frontends and builtin handling. */
    symtab_node next_sharing_asm_name;
    symtab_node previous_sharing_asm_name;
  
    PTR GTY ((skip)) aux;
  };
  
--- 71,127 ----
    /* True when the name is known to be unique and thus it does not need mangling.  */
    unsigned unique_name : 1;
  
  
!   /*** WHOPR Partitioning flags.
!        These flags are used at ltrans stage when only part of the callgraph is
!        available. ***/
  
!   /* Set when variable is used from other LTRANS partition.  */
!   unsigned used_from_other_partition : 1;
!   /* Set when function is available in the other LTRANS partition.  
!      During WPA output it is used to mark nodes that are present in
!      multiple partitions.  */
!   unsigned in_other_partition : 1;
  
  
! 
!   /*** other flags.  ***/
! 
!   /* Set when symbol has address taken. */
!   unsigned address_taken : 1;
! 
! 
!   /* Ordering of all symtab entries.  */
!   int order;
! 
!   /* Declaration representing the symbol.  */
!   tree decl;
  
    /* Linked list of symbol table entries starting with symtab_nodes.  */
    symtab_node next;
    symtab_node previous;
+ 
    /* Linked list of symbols with the same asm name.  There may be multiple
!      entries for single symbol name during LTO, because symbols are renamed
!      only after partitioning.
! 
!      Because inline clones are kept in the assembler name has, they also produce
!      duplicate entries.
! 
!      There are also several long standing bugs where frontends and builtin
!      code produce duplicated decls.  */
    symtab_node next_sharing_asm_name;
    symtab_node previous_sharing_asm_name;
  
+   /* Circular list of nodes in the same comdat group if non-NULL.  */
+   symtab_node same_comdat_group;
+ 
+   /* Vectors of referring and referenced entities.  */
+   struct ipa_ref_list ref_list;
+ 
+   /* File stream where this node is being written to.  */
+   struct lto_file_decl_data * lto_file_data;
+ 
    PTR GTY ((skip)) aux;
  };
  
*************** struct GTY(()) cgraph_local_info {
*** 142,150 ****
       and its address is never taken.  */
    unsigned local : 1;
  
-   /* Set once it has been finalized so we consider it to be output.  */
-   unsigned finalized : 1;
- 
    /* False when there is something makes versioning impossible.  */
    unsigned versionable : 1;
  
--- 175,180 ----
*************** struct GTY(()) cgraph_node {
*** 260,270 ****
    unsigned lowered : 1;
    /* Set once the function has been instantiated and its callee
       lists created.  */
-   unsigned analyzed : 1;
-   /* Set when function is scheduled to be processed by local passes.  */
    unsigned process : 1;
-   /* Set for aliases once they got through assemble_alias.  */
-   unsigned alias : 1;
    /* Set for aliases created as C++ same body aliases.  */
    unsigned same_body_alias : 1;
    /* How commonly executed the node is.  Initialized during branch
--- 290,296 ----
*************** struct GTY(()) varpool_node {
*** 455,470 ****
    /* For aliases points to declaration DECL is alias of.  */
    tree alias_of;
  
-   /* Set once the variable has been instantiated and its callee
-      lists created.  */
-   unsigned analyzed : 1;
-   /* Set once it has been finalized so we consider it to be output.  */
-   unsigned finalized : 1;
    /* Set when variable is scheduled to be assembled.  */
    unsigned output : 1;
-   /* Set for aliases once they got through assemble_alias.  Also set for
-      extra name aliases in varpool_extra_name_alias.  */
-   unsigned alias : 1;
    unsigned extra_name_alias : 1;
  };
  
--- 481,488 ----
*************** void verify_symtab_node (symtab_node);
*** 558,563 ****
--- 576,582 ----
  bool verify_symtab_base (symtab_node);
  bool symtab_used_from_object_file_p (symtab_node);
  void symtab_make_decl_local (tree);
+ symtab_node symtab_alias_ultimate_target (symtab_node, enum availability *);
  
  /* In cgraph.c  */
  void dump_cgraph (FILE *);
*************** struct cgraph_2node_hook_list *cgraph_ad
*** 653,658 ****
--- 672,678 ----
  void cgraph_remove_node_duplication_hook (struct cgraph_2node_hook_list *);
  gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
  bool cgraph_propagate_frequency (struct cgraph_node *node);
+ struct cgraph_node * cgraph_function_node (struct cgraph_node *, enum availability *);
  
  /* In cgraphunit.c  */
  struct asm_node *add_asm_node (tree);
*************** void compile (void);
*** 663,672 ****
  void init_cgraph (void);
  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);
  /*  Initialize datastructures so DECL is a function in lowered gimple form.
      IN_SSA is true if the gimple is in SSA.  */
! basic_block init_lowered_empty_function (tree decl, bool in_ssa);
  
  /* In cgraphclones.c  */
  
--- 683,693 ----
  void init_cgraph (void);
  bool cgraph_process_new_functions (void);
  void cgraph_process_same_body_aliases (void);
! void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree);
  /*  Initialize datastructures so DECL is a function in lowered gimple form.
      IN_SSA is true if the gimple is in SSA.  */
! basic_block init_lowered_empty_function (tree, bool);
! void cgraph_reset_node (struct cgraph_node *);
  
  /* In cgraphclones.c  */
  
*************** void dump_varpool_node_set (FILE *, varp
*** 728,734 ****
  void debug_varpool_node_set (varpool_node_set);
  void free_varpool_node_set (varpool_node_set);
  void ipa_discover_readonly_nonaddressable_vars (void);
- bool cgraph_comdat_can_be_unshared_p (struct cgraph_node *);
  bool varpool_externally_visible_p (struct varpool_node *);
  
  /* In predict.c  */
--- 749,754 ----
*************** bool varpool_for_node_and_aliases (struc
*** 765,770 ****
--- 785,791 ----
  void varpool_add_new_variable (tree);
  void symtab_initialize_asm_name_hash (void);
  void symtab_prevail_in_asm_name_hash (symtab_node node);
+ void varpool_remove_initializer (struct varpool_node *);
  
  
  /* Return callgraph node for given symbol and check it is a function. */
*************** varpool_first_defined_variable (void)
*** 900,906 ****
    for (node = symtab_nodes; node; node = node->symbol.next)
      {
        varpool_node *vnode = dyn_cast <varpool_node> (node);
!       if (vnode && vnode->analyzed)
  	return vnode;
      }
    return NULL;
--- 921,927 ----
    for (node = symtab_nodes; node; node = node->symbol.next)
      {
        varpool_node *vnode = dyn_cast <varpool_node> (node);
!       if (vnode && vnode->symbol.definition)
  	return vnode;
      }
    return NULL;
*************** varpool_next_defined_variable (struct va
*** 914,920 ****
    for (; node1; node1 = node1->symbol.next)
      {
        varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
!       if (vnode1 && vnode1->analyzed)
  	return vnode1;
      }
    return NULL;
--- 935,941 ----
    for (; node1; node1 = node1->symbol.next)
      {
        varpool_node *vnode1 = dyn_cast <varpool_node> (node1);
!       if (vnode1 && vnode1->symbol.definition)
  	return vnode1;
      }
    return NULL;
*************** cgraph_first_defined_function (void)
*** 932,938 ****
    for (node = symtab_nodes; node; node = node->symbol.next)
      {
        cgraph_node *cn = dyn_cast <cgraph_node> (node);
!       if (cn && cn->analyzed)
  	return cn;
      }
    return NULL;
--- 953,959 ----
    for (node = symtab_nodes; node; node = node->symbol.next)
      {
        cgraph_node *cn = dyn_cast <cgraph_node> (node);
!       if (cn && cn->symbol.definition)
  	return cn;
      }
    return NULL;
*************** cgraph_next_defined_function (struct cgr
*** 946,952 ****
    for (; node1; node1 = node1->symbol.next)
      {
        cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
!       if (cn1 && cn1->analyzed)
  	return cn1;
      }
    return NULL;
--- 967,973 ----
    for (; node1; node1 = node1->symbol.next)
      {
        cgraph_node *cn1 = dyn_cast <cgraph_node> (node1);
!       if (cn1 && cn1->symbol.definition)
  	return cn1;
      }
    return NULL;
*************** cgraph_next_function (struct cgraph_node
*** 992,998 ****
  static inline bool
  cgraph_function_with_gimple_body_p (struct cgraph_node *node)
  {
!   return node->analyzed && !node->thunk.thunk_p && !node->alias;
  }
  
  /* Return first function with body defined.  */
--- 1013,1019 ----
  static inline bool
  cgraph_function_with_gimple_body_p (struct cgraph_node *node)
  {
!   return node->symbol.definition && !node->thunk.thunk_p && !node->symbol.alias;
  }
  
  /* Return first function with body defined.  */
*************** varpool_can_remove_if_no_refs (struct va
*** 1197,1203 ****
  static inline bool
  varpool_all_refs_explicit_p (struct varpool_node *vnode)
  {
!   return (vnode->analyzed
  	  && !vnode->symbol.externally_visible
  	  && !vnode->symbol.used_from_other_partition
  	  && !vnode->symbol.force_output);
--- 1218,1224 ----
  static inline bool
  varpool_all_refs_explicit_p (struct varpool_node *vnode)
  {
!   return (vnode->symbol.definition
  	  && !vnode->symbol.externally_visible
  	  && !vnode->symbol.used_from_other_partition
  	  && !vnode->symbol.force_output);
*************** htab_t constant_pool_htab (void);
*** 1211,1270 ****
  
  /* Return node that alias N is aliasing.  */
  
! static inline struct cgraph_node *
! cgraph_alias_aliased_node (struct cgraph_node *n)
  {
    struct ipa_ref *ref;
- 
    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
!   if (is_a <cgraph_node> (ref->referred))
!     return ipa_ref_node (ref);
!   return NULL;
  }
  
! /* Return node that alias N is aliasing.  */
! 
! static inline struct varpool_node *
! varpool_alias_aliased_node (struct varpool_node *n)
  {
!   struct ipa_ref *ref;
! 
!   ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
!   gcc_checking_assert (ref->use == IPA_REF_ALIAS);
!   if (is_a <varpool_node> (ref->referred))
!     return ipa_ref_varpool_node (ref);
!   return NULL;
  }
  
! /* Given NODE, walk the alias chain to return the function NODE is alias of.
!    Walk through thunk, too.
!    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
! 
! static inline struct cgraph_node *
! cgraph_function_node (struct cgraph_node *node, enum availability *availability)
  {
!   if (availability)
!     *availability = cgraph_function_body_availability (node);
!   while (node)
!     {
!       if (node->alias && node->analyzed)
! 	node = cgraph_alias_aliased_node (node);
!       else if (node->thunk.thunk_p)
! 	node = node->callees->callee;
!       else
! 	return node;
!       if (node && availability)
! 	{
! 	  enum availability a;
! 	  a = cgraph_function_body_availability (node);
! 	  if (a < *availability)
! 	    *availability = a;
! 	}
!     }
!   if (availability)
!     *availability = AVAIL_NOT_AVAILABLE;
!   return NULL;
  }
  
  /* Given NODE, walk the alias chain to return the function NODE is alias of.
--- 1232,1256 ----
  
  /* Return node that alias N is aliasing.  */
  
! static inline symtab_node
! symtab_alias_target (symtab_node n)
  {
    struct ipa_ref *ref;
    ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref);
    gcc_checking_assert (ref->use == IPA_REF_ALIAS);
!   return ref->referred;
  }
  
! static inline struct cgraph_node *
! cgraph_alias_target (struct cgraph_node *n)
  {
!   return dyn_cast <cgraph_node> (symtab_alias_target ((symtab_node) n));
  }
  
! static inline struct varpool_node *
! varpool_alias_target (struct varpool_node *n)
  {
!   return dyn_cast <varpool_node> (symtab_alias_target ((symtab_node) n));
  }
  
  /* Given NODE, walk the alias chain to return the function NODE is alias of.
*************** cgraph_function_node (struct cgraph_node
*** 1274,1300 ****
  static inline struct cgraph_node *
  cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability)
  {
!   if (availability)
!     *availability = cgraph_function_body_availability (node);
!   while (node)
!     {
!       if (node->alias && node->analyzed)
! 	node = cgraph_alias_aliased_node (node);
!       else
! 	return node;
!       if (node && availability)
! 	{
! 	  enum availability a;
! 	  a = cgraph_function_body_availability (node);
! 	  if (a < *availability)
! 	    *availability = a;
! 	}
!     }
!   if (availability)
      *availability = AVAIL_NOT_AVAILABLE;
!   return NULL;
  }
- 
  /* Given NODE, walk the alias chain to return the function NODE is alias of.
     Do not walk through thunks.
     When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
--- 1260,1272 ----
  static inline struct cgraph_node *
  cgraph_function_or_thunk_node (struct cgraph_node *node, enum availability *availability)
  {
!   struct cgraph_node *n;
! 
!   n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node, availability));
!   if (!n)
      *availability = AVAIL_NOT_AVAILABLE;
!   return n;
  }
  /* Given NODE, walk the alias chain to return the function NODE is alias of.
     Do not walk through thunks.
     When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
*************** cgraph_function_or_thunk_node (struct cg
*** 1302,1326 ****
  static inline struct varpool_node *
  varpool_variable_node (struct varpool_node *node, enum availability *availability)
  {
!   if (availability)
!     *availability = cgraph_variable_initializer_availability (node);
!   while (node)
!     {
!       if (node->alias && node->analyzed)
! 	node = varpool_alias_aliased_node (node);
!       else
! 	return node;
!       if (node && availability)
! 	{
! 	  enum availability a;
! 	  a = cgraph_variable_initializer_availability (node);
! 	  if (a < *availability)
! 	    *availability = a;
! 	}
!     }
!   if (availability)
      *availability = AVAIL_NOT_AVAILABLE;
!   return NULL;
  }
  
  /* Return true when the edge E represents a direct recursion.  */
--- 1274,1285 ----
  static inline struct varpool_node *
  varpool_variable_node (struct varpool_node *node, enum availability *availability)
  {
!   struct varpool_node *n;
! 
!   n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node, availability));
!   if (!n)
      *availability = AVAIL_NOT_AVAILABLE;
!   return n;
  }
  
  /* Return true when the edge E represents a direct recursion.  */
*************** cgraph_mark_force_output_node (struct cg
*** 1355,1361 ****
  }
  
  /* 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)
--- 1314,1320 ----
  }
  
  /* Return true when the symbol is real symbol, i.e. it is not inline clone
!    or abstract function kept for debug info purposes only.  */
  
  static inline bool
  symtab_real_symbol_p (symtab_node node)
Index: lto-symtab.c
===================================================================
*** lto-symtab.c	(revision 199343)
--- lto-symtab.c	(working copy)
*************** static void
*** 91,98 ****
  lto_varpool_replace_node (struct varpool_node *vnode,
  			  struct varpool_node *prevailing_node)
  {
!   gcc_assert (!vnode->finalized || prevailing_node->finalized);
!   gcc_assert (!vnode->analyzed || prevailing_node->analyzed);
  
    ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
  
--- 91,98 ----
  lto_varpool_replace_node (struct varpool_node *vnode,
  			  struct varpool_node *prevailing_node)
  {
!   gcc_assert (!vnode->symbol.definition || prevailing_node->symbol.definition);
!   gcc_assert (!vnode->symbol.analyzed || prevailing_node->symbol.analyzed);
  
    ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
  
*************** lto_symtab_resolve_can_prevail_p (symtab
*** 255,268 ****
    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 ();
  }
  
  /* Resolve the symbol with the candidates in the chain *SLOT and store
--- 255,261 ----
    if (DECL_EXTERNAL (e->symbol.decl))
      return false;
  
!   return e->symbol.definition;
  }
  
  /* Resolve the symbol with the candidates in the chain *SLOT and store
*************** lto_symtab_merge_cgraph_nodes (void)
*** 594,626 ****
    FOR_EACH_FUNCTION (cnode)
      {
        /* Resolve weakrefs to symbol defined in other unit.  */
!       if (!cnode->analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias))
  	{
  	  symtab_node node = symtab_node_for_asm (cnode->thunk.alias);
  	  if (node && is_a <cgraph_node> (node))
  	    {
  	      struct cgraph_node *n;
  
! 	      for (n = cgraph (node); n && n->alias;
! 		   n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL)
  		if (n == cnode)
  		  {
  		    error ("function %q+D part of alias cycle", cnode->symbol.decl);
! 		    cnode->alias = false;
  		    break;
  		  }
! 	      if (cnode->alias)
  		{
  		  cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl);
  		  ipa_record_reference ((symtab_node)cnode, (symtab_node)node,
  					IPA_REF_ALIAS, NULL);
! 		  cnode->analyzed = true;
  		}
  	    }
  	  else if (node)
  	    error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl);
  	}
!       if ((cnode->thunk.thunk_p || cnode->alias)
  	  && cnode->thunk.alias && DECL_P (cnode->thunk.alias))
          cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
        cnode->symbol.aux = NULL;
--- 587,619 ----
    FOR_EACH_FUNCTION (cnode)
      {
        /* Resolve weakrefs to symbol defined in other unit.  */
!       if (!cnode->symbol.analyzed && cnode->thunk.alias && !DECL_P (cnode->thunk.alias))
  	{
  	  symtab_node node = symtab_node_for_asm (cnode->thunk.alias);
  	  if (node && is_a <cgraph_node> (node))
  	    {
  	      struct cgraph_node *n;
  
! 	      for (n = cgraph (node); n && n->symbol.alias;
! 		   n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL)
  		if (n == cnode)
  		  {
  		    error ("function %q+D part of alias cycle", cnode->symbol.decl);
! 		    cnode->symbol.alias = false;
  		    break;
  		  }
! 	      if (cnode->symbol.alias)
  		{
  		  cgraph_create_function_alias (cnode->symbol.decl, node->symbol.decl);
  		  ipa_record_reference ((symtab_node)cnode, (symtab_node)node,
  					IPA_REF_ALIAS, NULL);
! 		  cnode->symbol.analyzed = true;
  		}
  	    }
  	  else if (node)
  	    error ("%q+D alias in between function and variable is not supported", cnode->symbol.decl);
  	}
!       if ((cnode->thunk.thunk_p || cnode->symbol.alias)
  	  && cnode->thunk.alias && DECL_P (cnode->thunk.alias))
          cnode->thunk.alias = lto_symtab_prevailing_decl (cnode->thunk.alias);
        cnode->symbol.aux = NULL;
*************** lto_symtab_merge_cgraph_nodes (void)
*** 628,660 ****
    FOR_EACH_VARIABLE (vnode)
      {
        /* Resolve weakrefs to symbol defined in other unit.  */
!       if (!vnode->analyzed && vnode->alias_of && !DECL_P (vnode->alias_of))
  	{
  	  symtab_node node = symtab_node_for_asm (vnode->alias_of);
  	  if (node && is_a <cgraph_node> (node))
  	    {
  	      struct varpool_node *n;
  
! 	      for (n = varpool (node); n && n->alias;
! 		   n = n->analyzed ? varpool_alias_aliased_node (n) : NULL)
  		if (n == vnode)
  		  {
  		    error ("function %q+D part of alias cycle", vnode->symbol.decl);
! 		    vnode->alias = false;
  		    break;
  		  }
! 	      if (vnode->alias)
  		{
  		  varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl);
  		  ipa_record_reference ((symtab_node)vnode, (symtab_node)node,
  					IPA_REF_ALIAS, NULL);
! 		  vnode->analyzed = true;
  		}
  	    }
  	  else if (node)
  	    error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl);
  	}
!       if (vnode->alias_of)
          vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
        vnode->symbol.aux = NULL;
      }
--- 621,653 ----
    FOR_EACH_VARIABLE (vnode)
      {
        /* Resolve weakrefs to symbol defined in other unit.  */
!       if (!vnode->symbol.analyzed && vnode->alias_of && !DECL_P (vnode->alias_of))
  	{
  	  symtab_node node = symtab_node_for_asm (vnode->alias_of);
  	  if (node && is_a <cgraph_node> (node))
  	    {
  	      struct varpool_node *n;
  
! 	      for (n = varpool (node); n && n->symbol.alias;
! 		   n = n->symbol.analyzed ? varpool_alias_target (n) : NULL)
  		if (n == vnode)
  		  {
  		    error ("function %q+D part of alias cycle", vnode->symbol.decl);
! 		    vnode->symbol.alias = false;
  		    break;
  		  }
! 	      if (vnode->symbol.alias)
  		{
  		  varpool_create_variable_alias (vnode->symbol.decl, node->symbol.decl);
  		  ipa_record_reference ((symtab_node)vnode, (symtab_node)node,
  					IPA_REF_ALIAS, NULL);
! 		  vnode->symbol.analyzed = true;
  		}
  	    }
  	  else if (node)
  	    error ("%q+D alias in between function and variable is not supported", vnode->symbol.decl);
  	}
!       if (vnode->symbol.alias && DECL_P (vnode->alias_of))
          vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of);
        vnode->symbol.aux = NULL;
      }
Index: java/decl.c
===================================================================
*** java/decl.c	(revision 199343)
--- java/decl.c	(working copy)
*************** java_mark_decl_local (tree decl)
*** 1904,1910 ****
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        struct cgraph_node *node = cgraph_get_node (decl);
!       gcc_assert (!node || !node->local.finalized);
      }
  #endif
    gcc_assert (!DECL_RTL_SET_P (decl));
--- 1904,1910 ----
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        struct cgraph_node *node = cgraph_get_node (decl);
!       gcc_assert (!node || !node->symbol.definition);
      }
  #endif
    gcc_assert (!DECL_RTL_SET_P (decl));
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 199343)
--- cgraph.c	(working copy)
*************** cgraph_create_function_alias (tree alias
*** 563,572 ****
    gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
    gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
    alias_node = cgraph_get_create_node (alias);
!   gcc_assert (!alias_node->local.finalized);
    alias_node->thunk.alias = decl;
!   alias_node->local.finalized = true;
!   alias_node->alias = 1;
    return alias_node;
  }
  
--- 563,572 ----
    gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
    gcc_assert (TREE_CODE (alias) == FUNCTION_DECL);
    alias_node = cgraph_get_create_node (alias);
!   gcc_assert (!alias_node->symbol.definition);
    alias_node->thunk.alias = decl;
!   alias_node->symbol.definition = true;
!   alias_node->symbol.alias = true;
    return alias_node;
  }
  
*************** cgraph_add_thunk (struct cgraph_node *de
*** 613,620 ****
    node = cgraph_get_node (alias);
    if (node)
      {
!       gcc_assert (node->local.finalized);
!       gcc_assert (!node->alias);
        gcc_assert (!node->thunk.thunk_p);
        cgraph_remove_node (node);
      }
--- 613,620 ----
    node = cgraph_get_node (alias);
    if (node)
      {
!       gcc_assert (node->symbol.definition);
!       gcc_assert (!node->symbol.alias);
        gcc_assert (!node->thunk.thunk_p);
        cgraph_remove_node (node);
      }
*************** cgraph_add_thunk (struct cgraph_node *de
*** 629,635 ****
    node->thunk.virtual_offset_p = virtual_offset != NULL;
    node->thunk.alias = real_alias;
    node->thunk.thunk_p = true;
!   node->local.finalized = true;
  
    return node;
  }
--- 629,635 ----
    node->thunk.virtual_offset_p = virtual_offset != NULL;
    node->thunk.alias = real_alias;
    node->thunk.thunk_p = true;
!   node->symbol.definition = true;
  
    return node;
  }
*************** cgraph_remove_node (struct cgraph_node *
*** 1384,1390 ****
  	  && (cgraph_global_info_ready
  	      && (TREE_ASM_WRITTEN (n->symbol.decl)
  		  || DECL_EXTERNAL (n->symbol.decl)
! 		  || !n->analyzed
  		  || n->symbol.in_other_partition))))
      cgraph_release_function_body (node);
  
--- 1384,1390 ----
  	  && (cgraph_global_info_ready
  	      && (TREE_ASM_WRITTEN (n->symbol.decl)
  		  || DECL_EXTERNAL (n->symbol.decl)
! 		  || !n->symbol.analyzed
  		  || n->symbol.in_other_partition))))
      cgraph_release_function_body (node);
  
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1521,1528 ****
  	     cgraph_availability_names [cgraph_function_body_availability (node)]);
  
    fprintf (f, "  Function flags:");
-   if (node->analyzed)
-     fprintf (f, " analyzed");
    if (node->count)
      fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
  	     (HOST_WIDEST_INT)node->count);
--- 1521,1526 ----
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1534,1549 ****
      fprintf (f, " process");
    if (node->local.local)
      fprintf (f, " local");
-   if (node->local.finalized)
-     fprintf (f, " finalized");
    if (node->local.redefined_extern_inline)
      fprintf (f, " redefined_extern_inline");
    if (node->only_called_at_startup)
      fprintf (f, " only_called_at_startup");
    if (node->only_called_at_exit)
      fprintf (f, " only_called_at_exit");
-   else if (node->alias)
-     fprintf (f, " alias");
    if (node->tm_clone)
      fprintf (f, " tm_clone");
  
--- 1532,1543 ----
*************** dump_cgraph_node (FILE *f, struct cgraph
*** 1559,1565 ****
  	       (int)node->thunk.virtual_value,
  	       (int)node->thunk.virtual_offset_p);
      }
!   if (node->alias && node->thunk.alias && DECL_P (node->thunk.alias))
      {
        fprintf (f, "  Alias of %s",
  	       lang_hooks.decl_printable_name (node->thunk.alias, 2));
--- 1553,1560 ----
  	       (int)node->thunk.virtual_value,
  	       (int)node->thunk.virtual_offset_p);
      }
!   if (node->symbol.alias && node->thunk.alias
!       && DECL_P (node->thunk.alias))
      {
        fprintf (f, "  Alias of %s",
  	       lang_hooks.decl_printable_name (node->thunk.alias, 2));
*************** cgraph_function_body_availability (struc
*** 1676,1682 ****
  {
    enum availability avail;
    gcc_assert (cgraph_function_flags_ready);
!   if (!node->analyzed)
      avail = AVAIL_NOT_AVAILABLE;
    else if (node->local.local)
      avail = AVAIL_LOCAL;
--- 1671,1677 ----
  {
    enum availability avail;
    gcc_assert (cgraph_function_flags_ready);
!   if (!node->symbol.analyzed)
      avail = AVAIL_NOT_AVAILABLE;
    else if (node->local.local)
      avail = AVAIL_LOCAL;
*************** cgraph_propagate_frequency (struct cgrap
*** 1983,1989 ****
  
    if (!node->local.local)
      return false;
!   gcc_assert (node->analyzed);
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
  
--- 1978,1984 ----
  
    if (!node->local.local)
      return false;
!   gcc_assert (node->symbol.analyzed);
    if (dump_file && (dump_flags & TDF_DETAILS))
      fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node));
  
*************** verify_cgraph_node (struct cgraph_node *
*** 2342,2347 ****
--- 2337,2347 ----
        error ("inline clone in same comdat group list");
        error_found = true;
      }
+   if (!node->symbol.definition && node->local.local)
+     {
+       error ("local symbols must be defined");
+       error_found = true;
+     }
    if (node->global.inlined_to && node->symbol.externally_visible)
      {
        error ("externally visible inline clone");
*************** verify_cgraph_node (struct cgraph_node *
*** 2455,2461 ****
        error_found = true;
      }
  
!   if (node->analyzed && node->alias)
      {
        bool ref_found = false;
        int i;
--- 2455,2461 ----
        error_found = true;
      }
  
!   if (node->symbol.analyzed && node->symbol.alias)
      {
        bool ref_found = false;
        int i;
*************** verify_cgraph_node (struct cgraph_node *
*** 2486,2492 ****
  	    error_found = true;
  	  }
      }
!   if (node->analyzed && node->thunk.thunk_p)
      {
        if (!node->callees)
  	{
--- 2486,2492 ----
  	    error_found = true;
  	  }
      }
!   if (node->symbol.analyzed && node->thunk.thunk_p)
      {
        if (!node->callees)
  	{
*************** verify_cgraph_node (struct cgraph_node *
*** 2504,2510 ****
            error_found = true;
          }
      }
!   else if (node->analyzed && gimple_has_body_p (node->symbol.decl)
             && !TREE_ASM_WRITTEN (node->symbol.decl)
             && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to)
             && !flag_wpa)
--- 2504,2510 ----
            error_found = true;
          }
      }
!   else if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl)
             && !TREE_ASM_WRITTEN (node->symbol.decl)
             && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to)
             && !flag_wpa)
*************** cgraph_get_create_real_symbol_node (tree
*** 2653,2656 ****
--- 2653,2684 ----
  	     node->symbol.order);
    return node;
  }
+ 
+ 
+ /* Given NODE, walk the alias chain to return the function NODE is alias of.
+    Walk through thunk, too.
+    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
+ 
+ struct cgraph_node *
+ cgraph_function_node (struct cgraph_node *node, enum availability *availability)
+ {
+   do
+     {
+       node = cgraph_function_or_thunk_node (node, availability);
+       if (node->thunk.thunk_p)
+ 	{
+ 	  node = node->callees->callee;
+ 	  if (availability)
+ 	    {
+ 	      enum availability a;
+ 	      a = cgraph_function_body_availability (node);
+ 	      if (a < *availability)
+ 		*availability = a;
+ 	    }
+ 	  node = cgraph_function_or_thunk_node (node, availability);
+ 	}
+     } while (node && node->thunk.thunk_p);
+   return node;
+ }
+ 
  #include "gt-cgraph.h"
Index: ipa-cp.c
===================================================================
*** ipa-cp.c	(revision 199343)
--- ipa-cp.c	(working copy)
*************** determine_versionability (struct cgraph_
*** 440,453 ****
    /* There are a number of generic reasons functions cannot be versioned.  We
       also cannot remove parameters if there are type attributes such as fnspec
       present.  */
!   if (node->alias || node->thunk.thunk_p)
      reason = "alias or thunk";
    else if (!node->local.versionable)
      reason = "not a tree_versionable_function";
    else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
      reason = "insufficient body availability";
  
!   if (reason && dump_file && !node->alias && !node->thunk.thunk_p)
      fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
  	     cgraph_node_name (node), node->symbol.order, reason);
  
--- 440,453 ----
    /* There are a number of generic reasons functions cannot be versioned.  We
       also cannot remove parameters if there are type attributes such as fnspec
       present.  */
!   if (node->symbol.alias || node->thunk.thunk_p)
      reason = "alias or thunk";
    else if (!node->local.versionable)
      reason = "not a tree_versionable_function";
    else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
      reason = "insufficient body availability";
  
!   if (reason && dump_file && !node->symbol.alias && !node->thunk.thunk_p)
      fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n",
  	     cgraph_node_name (node), node->symbol.order, reason);
  
*************** initialize_node_lattices (struct cgraph_
*** 727,733 ****
  	    set_all_contains_variable (plats);
  	}
        if (dump_file && (dump_flags & TDF_DETAILS)
! 	  && !node->alias && !node->thunk.thunk_p)
  	fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
  		 cgraph_node_name (node), node->symbol.order,
  		 disable ? "BOTTOM" : "VARIABLE");
--- 727,733 ----
  	    set_all_contains_variable (plats);
  	}
        if (dump_file && (dump_flags & TDF_DETAILS)
! 	  && !node->symbol.alias && !node->thunk.thunk_p)
  	fprintf (dump_file, "Marking all lattices of %s/%i as %s\n",
  		 cgraph_node_name (node), node->symbol.order,
  		 disable ? "BOTTOM" : "VARIABLE");
*************** propagate_constants_accross_call (struct
*** 1418,1424 ****
    int i, args_count, parms_count;
  
    callee = cgraph_function_node (cs->callee, &availability);
!   if (!callee->analyzed)
      return false;
    gcc_checking_assert (cgraph_function_with_gimple_body_p (callee));
    callee_info = IPA_NODE_REF (callee);
--- 1418,1424 ----
    int i, args_count, parms_count;
  
    callee = cgraph_function_node (cs->callee, &availability);
!   if (!callee->symbol.definition)
      return false;
    gcc_checking_assert (cgraph_function_with_gimple_body_p (callee));
    callee_info = IPA_NODE_REF (callee);
*************** propagate_constants_accross_call (struct
*** 1431,1438 ****
       parameter.  However, we might need to uncover a thunk from below a series
       of aliases first.  */
    alias_or_thunk = cs->callee;
!   while (alias_or_thunk->alias)
!     alias_or_thunk = cgraph_alias_aliased_node (alias_or_thunk);
    if (alias_or_thunk->thunk.thunk_p)
      {
        ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
--- 1431,1438 ----
       parameter.  However, we might need to uncover a thunk from below a series
       of aliases first.  */
    alias_or_thunk = cs->callee;
!   while (alias_or_thunk->symbol.alias)
!     alias_or_thunk = cgraph_alias_target (alias_or_thunk);
    if (alias_or_thunk->thunk.thunk_p)
      {
        ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info,
*************** devirtualization_time_bonus (struct cgra
*** 1601,1607 ****
        /* Only bare minimum benefit for clearly un-inlineable targets.  */
        res += 1;
        callee = cgraph_get_node (target);
!       if (!callee || !callee->analyzed)
  	continue;
        isummary = inline_summary (callee);
        if (!isummary->inlinable)
--- 1601,1607 ----
        /* Only bare minimum benefit for clearly un-inlineable targets.  */
        res += 1;
        callee = cgraph_get_node (target);
!       if (!callee || !callee->symbol.definition)
  	continue;
        isummary = inline_summary (callee);
        if (!isummary->inlinable)
*************** ipcp_propagate_stage (struct topo_info *
*** 2231,2239 ****
  				   ipa_get_param_count (info));
  	initialize_node_lattices (node);
        }
      if (node->count > max_count)
        max_count = node->count;
-     overall_size += inline_summary (node)->self_size;
    }
  
    max_new_size = overall_size;
--- 2231,2240 ----
  				   ipa_get_param_count (info));
  	initialize_node_lattices (node);
        }
+     if (node->symbol.definition && !node->symbol.alias)
+       overall_size += inline_summary (node)->self_size;
      if (node->count > max_count)
        max_count = node->count;
    }
  
    max_new_size = overall_size;
Index: tree-emutls.c
===================================================================
*** tree-emutls.c	(revision 199343)
--- tree-emutls.c	(working copy)
*************** create_emultls_var (struct varpool_node
*** 704,718 ****
    cvar = varpool_get_node (cdecl);
    control_vars.quick_push (cvar);
  
!   if (!var->alias)
      {
        /* Make sure the COMMON block control variable gets initialized.
  	 Note that there's no point in doing this for aliases; we only
  	 need to do this once for the main variable.  */
        emutls_common_1 (var->symbol.decl, cdecl, (tree *)data);
      }
!   if (var->alias && !var->alias_of)
!     cvar->alias = true;
  
    /* Indicate that the value of the TLS variable may be found elsewhere,
       preventing the variable from re-appearing in the GIMPLE.  We cheat
--- 704,718 ----
    cvar = varpool_get_node (cdecl);
    control_vars.quick_push (cvar);
  
!   if (!var->symbol.alias)
      {
        /* Make sure the COMMON block control variable gets initialized.
  	 Note that there's no point in doing this for aliases; we only
  	 need to do this once for the main variable.  */
        emutls_common_1 (var->symbol.decl, cdecl, (tree *)data);
      }
!   if (var->symbol.alias && !var->alias_of)
!     cvar->symbol.alias = true;
  
    /* Indicate that the value of the TLS variable may be found elsewhere,
       preventing the variable from re-appearing in the GIMPLE.  We cheat
*************** ipa_lower_emutls (void)
*** 743,749 ****
  	gcc_checking_assert (TREE_STATIC (var->symbol.decl)
  			     || DECL_EXTERNAL (var->symbol.decl));
  	varpool_node_set_add (tls_vars, var);
! 	if (var->alias && var->analyzed)
  	  varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL));
        }
  
--- 743,749 ----
  	gcc_checking_assert (TREE_STATIC (var->symbol.decl)
  			     || DECL_EXTERNAL (var->symbol.decl));
  	varpool_node_set_add (tls_vars, var);
! 	if (var->symbol.alias && var->symbol.definition)
  	  varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL));
        }
  
*************** ipa_lower_emutls (void)
*** 767,775 ****
      {
        var = tls_vars->nodes[i];
  
!       if (var->alias && !var->alias_of)
  	any_aliases = true;
!       else if (!var->alias)
  	varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true);
      }
  
--- 767,775 ----
      {
        var = tls_vars->nodes[i];
  
!       if (var->symbol.alias && !var->alias_of)
  	any_aliases = true;
!       else if (!var->symbol.alias)
  	varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true);
      }
  
Index: ipa-inline-transform.c
===================================================================
*** ipa-inline-transform.c	(revision 199343)
--- ipa-inline-transform.c	(working copy)
*************** clone_inlined_nodes (struct cgraph_edge
*** 153,159 ****
  	     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)
  	        *overall_size -= inline_summary (e->callee)->size;
--- 153,159 ----
  	     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->symbol.definition && !DECL_EXTERNAL (e->callee->symbol.decl))
  	    {
  	      if (overall_size)
  	        *overall_size -= inline_summary (e->callee)->size;
*************** inline_call (struct cgraph_edge *e, bool
*** 236,242 ****
  	  if (!alias->callers
  	      && can_remove_node_now_p (alias, e))
  	    {
! 	      next_alias = cgraph_alias_aliased_node (alias);
  	      cgraph_remove_node (alias);
  	      alias = next_alias;
  	    }
--- 236,242 ----
  	  if (!alias->callers
  	      && can_remove_node_now_p (alias, e))
  	    {
! 	      next_alias = cgraph_alias_target (alias);
  	      cgraph_remove_node (alias);
  	      alias = next_alias;
  	    }
*************** static bool
*** 381,387 ****
  preserve_function_body_p (struct cgraph_node *node)
  {
    gcc_assert (cgraph_global_info_ready);
!   gcc_assert (!node->alias && !node->thunk.thunk_p);
  
    /* Look if there is any clone around.  */
    if (node->clones)
--- 381,387 ----
  preserve_function_body_p (struct cgraph_node *node)
  {
    gcc_assert (cgraph_global_info_ready);
!   gcc_assert (!node->symbol.alias && !node->thunk.thunk_p);
  
    /* Look if there is any clone around.  */
    if (node->clones)
Index: ipa-reference.c
===================================================================
*** ipa-reference.c	(revision 199343)
--- ipa-reference.c	(working copy)
*************** propagate (void)
*** 684,690 ****
  	|| TREE_ADDRESSABLE (vnode->symbol.decl)
  	|| TREE_READONLY (vnode->symbol.decl)
  	|| !is_proper_for_analysis (vnode->symbol.decl)
! 	|| !vnode->analyzed)
        bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl));
  
    /* Forget info we collected "just for fun" on variables that turned out to be
--- 684,690 ----
  	|| TREE_ADDRESSABLE (vnode->symbol.decl)
  	|| TREE_READONLY (vnode->symbol.decl)
  	|| !is_proper_for_analysis (vnode->symbol.decl)
! 	|| !vnode->symbol.definition)
        bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl));
  
    /* Forget info we collected "just for fun" on variables that turned out to be
*************** propagate (void)
*** 716,722 ****
        bool write_all = false;
  
        node = order[i];
!       if (node->alias)
  	continue;
  
        node_info = get_reference_vars_info (node);
--- 716,722 ----
        bool write_all = false;
  
        node = order[i];
!       if (node->symbol.alias)
  	continue;
  
        node_info = get_reference_vars_info (node);
*************** propagate (void)
*** 794,800 ****
  	  struct cgraph_node *w;
  
  	  node = order[i];
! 	  if (node->alias)
  	    continue;
  
  	  fprintf (dump_file,
--- 794,800 ----
  	  struct cgraph_node *w;
  
  	  node = order[i];
! 	  if (node->symbol.alias)
  	    continue;
  
  	  fprintf (dump_file,
*************** propagate (void)
*** 835,841 ****
        ipa_reference_optimization_summary_t opt;
  
        node_info = get_reference_vars_info (node);
!       if (!node->alias
  	  && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
  	      || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF)))
  	{
--- 835,841 ----
        ipa_reference_optimization_summary_t opt;
  
        node_info = get_reference_vars_info (node);
!       if (!node->symbol.alias
  	  && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
  	      || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF)))
  	{
*************** write_node_summary_p (struct cgraph_node
*** 894,900 ****
    ipa_reference_optimization_summary_t info;
  
    /* See if we have (non-empty) info.  */
!   if (!node->analyzed || node->global.inlined_to)
      return false;
    info = get_reference_optimization_summary (node);
    if (!info || (bitmap_empty_p (info->statics_not_read)
--- 894,900 ----
    ipa_reference_optimization_summary_t info;
  
    /* See if we have (non-empty) info.  */
!   if (!node->symbol.definition || node->global.inlined_to)
      return false;
    info = get_reference_optimization_summary (node);
    if (!info || (bitmap_empty_p (info->statics_not_read)
Index: toplev.c
===================================================================
*** toplev.c	(revision 199343)
--- toplev.c	(working copy)
*************** wrapup_global_declaration_2 (tree decl)
*** 393,407 ****
  
        if (!node && flag_ltrans)
  	needed = false;
!       else if (node && node->finalized)
  	needed = false;
!       else if (node && node->alias)
  	needed = false;
        else if (!cgraph_global_info_ready
  	       && (TREE_USED (decl)
  		   || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
  	/* needed */;
!       else if (node && node->analyzed)
  	/* needed */;
        else if (DECL_COMDAT (decl))
  	needed = false;
--- 393,407 ----
  
        if (!node && flag_ltrans)
  	needed = false;
!       else if (node && node->symbol.definition)
  	needed = false;
!       else if (node && node->symbol.alias)
  	needed = false;
        else if (!cgraph_global_info_ready
  	       && (TREE_USED (decl)
  		   || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
  	/* needed */;
!       else if (node && node->symbol.analyzed)
  	/* needed */;
        else if (DECL_COMDAT (decl))
  	needed = false;
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 199343)
--- cgraphunit.c	(working copy)
*************** cgraph_node_set cgraph_new_nodes;
*** 202,208 ****
  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 *);
  static void handle_alias_pairs (void);
  
  FILE *cgraph_dump_file;
--- 202,208 ----
  static void expand_all_functions (void);
  static void mark_functions_to_output (void);
  static void expand_function (struct cgraph_node *);
! static void analyze_function (struct cgraph_node *);
  static void handle_alias_pairs (void);
  
  FILE *cgraph_dump_file;
*************** cgraph_process_new_functions (void)
*** 309,316 ****
  	     cgraph but not on this function.  */
  
  	  gimple_register_cfg_hooks ();
! 	  if (!node->analyzed)
! 	    cgraph_analyze_function (node);
  	  push_cfun (DECL_STRUCT_FUNCTION (fndecl));
  	  if ((cgraph_state == CGRAPH_STATE_IPA_SSA
  	      && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
--- 309,316 ----
  	     cgraph but not on this function.  */
  
  	  gimple_register_cfg_hooks ();
! 	  if (!node->symbol.analyzed)
! 	    analyze_function (node);
  	  push_cfun (DECL_STRUCT_FUNCTION (fndecl));
  	  if ((cgraph_state == CGRAPH_STATE_IPA_SSA
  	      && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
*************** cgraph_process_new_functions (void)
*** 354,360 ****
     ??? It may make more sense to use one body for inlining and other
     body for expanding the function but this is difficult to do.  */
  
! static void
  cgraph_reset_node (struct cgraph_node *node)
  {
    /* If node->process is set, then we have already begun whole-unit analysis.
--- 354,360 ----
     ??? It may make more sense to use one body for inlining and other
     body for expanding the function but this is difficult to do.  */
  
! void
  cgraph_reset_node (struct cgraph_node *node)
  {
    /* If node->process is set, then we have already begun whole-unit analysis.
*************** cgraph_reset_node (struct cgraph_node *n
*** 368,377 ****
    memset (&node->local, 0, sizeof (node->local));
    memset (&node->global, 0, sizeof (node->global));
    memset (&node->rtl, 0, sizeof (node->rtl));
!   node->analyzed = false;
!   node->local.finalized = false;
  
    cgraph_node_remove_callees (node);
  }
  
  /* Return true when there are references to NODE.  */
--- 368,378 ----
    memset (&node->local, 0, sizeof (node->local));
    memset (&node->global, 0, sizeof (node->global));
    memset (&node->rtl, 0, sizeof (node->rtl));
!   node->symbol.analyzed = false;
!   node->symbol.definition = false;
  
    cgraph_node_remove_callees (node);
+   ipa_remove_all_references (&node->symbol.ref_list);
  }
  
  /* Return true when there are references to NODE.  */
*************** cgraph_finalize_function (tree decl, boo
*** 401,414 ****
  {
    struct cgraph_node *node = cgraph_get_create_node (decl);
  
!   if (node->local.finalized)
      {
        cgraph_reset_node (node);
        node->local.redefined_extern_inline = true;
      }
  
    notice_global_symbol (decl);
!   node->local.finalized = true;
    node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
  
    /* With -fkeep-inline-functions we are keeping all inline functions except
--- 402,415 ----
  {
    struct cgraph_node *node = cgraph_get_create_node (decl);
  
!   if (node->symbol.definition)
      {
        cgraph_reset_node (node);
        node->local.redefined_extern_inline = true;
      }
  
    notice_global_symbol (decl);
!   node->symbol.definition = true;
    node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
  
    /* With -fkeep-inline-functions we are keeping all inline functions except
*************** cgraph_add_new_function (tree fndecl, bo
*** 488,494 ****
  	   analyzing and compilation.  */
  	node = cgraph_get_create_node (fndecl);
  	node->local.local = false;
! 	node->local.finalized = true;
  	node->symbol.force_output = true;
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
--- 489,495 ----
  	   analyzing and compilation.  */
  	node = cgraph_get_create_node (fndecl);
  	node->local.local = false;
! 	node->symbol.definition = true;
  	node->symbol.force_output = true;
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
*************** cgraph_add_new_function (tree fndecl, bo
*** 515,521 ****
  	node = cgraph_create_node (fndecl);
  	if (lowered)
  	  node->lowered = true;
! 	cgraph_analyze_function (node);
  	push_cfun (DECL_STRUCT_FUNCTION (fndecl));
  	gimple_register_cfg_hooks ();
  	bitmap_obstack_initialize (NULL);
--- 516,523 ----
  	node = cgraph_create_node (fndecl);
  	if (lowered)
  	  node->lowered = true;
! 	node->symbol.definition = true;
! 	analyze_function (node);
  	push_cfun (DECL_STRUCT_FUNCTION (fndecl));
  	gimple_register_cfg_hooks ();
  	bitmap_obstack_initialize (NULL);
*************** fixup_same_cpp_alias_visibility (symtab_
*** 589,611 ****
  
  /* Analyze the function scheduled to be output.  */
  static void
! cgraph_analyze_function (struct cgraph_node *node)
  {
    tree decl = node->symbol.decl;
    location_t saved_loc = input_location;
    input_location = DECL_SOURCE_LOCATION (decl);
  
!   if (node->alias && node->thunk.alias)
      {
        struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
        struct cgraph_node *n;
  
!       for (n = tgt; n && n->alias;
! 	   n = n->analyzed ? cgraph_alias_aliased_node (n) : NULL)
  	if (n == node)
  	  {
  	    error ("function %q+D part of alias cycle", node->symbol.decl);
! 	    node->alias = false;
  	    input_location = saved_loc;
  	    return;
  	  }
--- 591,613 ----
  
  /* Analyze the function scheduled to be output.  */
  static void
! analyze_function (struct cgraph_node *node)
  {
    tree decl = node->symbol.decl;
    location_t saved_loc = input_location;
    input_location = DECL_SOURCE_LOCATION (decl);
  
!   if (node->symbol.alias && node->thunk.alias)
      {
        struct cgraph_node *tgt = cgraph_get_node (node->thunk.alias);
        struct cgraph_node *n;
  
!       for (n = tgt; n && n->symbol.alias;
! 	   n = n->symbol.analyzed ? cgraph_alias_target (n) : NULL)
  	if (n == node)
  	  {
  	    error ("function %q+D part of alias cycle", node->symbol.decl);
! 	    node->symbol.alias = false;
  	    input_location = saved_loc;
  	    return;
  	  }
*************** cgraph_analyze_function (struct cgraph_n
*** 622,628 ****
  	}
  
        if (node->symbol.address_taken)
! 	cgraph_mark_address_taken_node (cgraph_alias_aliased_node (node));
      }
    else if (node->thunk.thunk_p)
      {
--- 624,630 ----
  	}
  
        if (node->symbol.address_taken)
! 	cgraph_mark_address_taken_node (cgraph_alias_target (node));
      }
    else if (node->thunk.thunk_p)
      {
*************** cgraph_analyze_function (struct cgraph_n
*** 677,683 ****
  
        pop_cfun ();
      }
!   node->analyzed = true;
  
    input_location = saved_loc;
  }
--- 679,685 ----
  
        pop_cfun ();
      }
!   node->symbol.analyzed = true;
  
    input_location = saved_loc;
  }
*************** process_function_and_variable_attributes
*** 766,772 ****
  			" attribute have effect only on public objects");
  	}
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
! 	  && (node->local.finalized && !node->alias))
  	{
  	  warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
  		      "%<weakref%> attribute ignored"
--- 768,774 ----
  			" attribute have effect only on public objects");
  	}
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
! 	  && (node->symbol.definition && !node->symbol.alias))
  	{
  	  warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes,
  		      "%<weakref%> attribute ignored"
*************** process_function_and_variable_attributes
*** 803,809 ****
  			" attribute have effect only on public objects");
  	}
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
! 	  && vnode->finalized
  	  && DECL_INITIAL (decl))
  	{
  	  warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
--- 805,811 ----
  			" attribute have effect only on public objects");
  	}
        if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
! 	  && vnode->symbol.definition
  	  && DECL_INITIAL (decl))
  	{
  	  warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes,
*************** varpool_finalize_decl (tree decl)
*** 828,837 ****
  
    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
  
!   if (node->finalized)
      return;
    notice_global_symbol (decl);
!   node->finalized = true;
    if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
        /* Traditionally we do not eliminate static variables when not
  	 optimizing and when not doing toplevel reoder.  */
--- 830,839 ----
  
    gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
  
!   if (node->symbol.definition)
      return;
    notice_global_symbol (decl);
!   node->symbol.definition = true;
    if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl)
        /* Traditionally we do not eliminate static variables when not
  	 optimizing and when not doing toplevel reoder.  */
*************** varpool_finalize_decl (tree decl)
*** 855,890 ****
  /* Determine if a symbol NODE is finalized and needed.  */
  
  inline static bool
! symbol_finalized_and_needed (symtab_node node)
  {
    if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
!     return cnode->local.finalized
  	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
    if (varpool_node *vnode = dyn_cast <varpool_node> (node))
!     return vnode->finalized
  	   && !DECL_EXTERNAL (vnode->symbol.decl)
  	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
    return false;
  }
  
- /* Determine if a symbol NODE is finalized.  */
- 
- inline static bool
- symbol_finalized (symtab_node node)
- {
-   if (cgraph_node *cnode= dyn_cast <cgraph_node> (node))
-     return cnode->local.finalized;
-   if (varpool_node *vnode = dyn_cast <varpool_node> (node))
-     return vnode->finalized;
-   return false;
- }
- 
- 
  /* Discover all functions and variables that are trivially needed, analyze
     them as well as all functions and variables referred by them  */
  
  static void
! cgraph_analyze_functions (void)
  {
    /* Keep track of already processed nodes when called multiple times for
       intermodule optimization.  */
--- 857,879 ----
  /* Determine if a symbol NODE is finalized and needed.  */
  
  inline static bool
! symbol_defined_and_needed (symtab_node node)
  {
    if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
!     return cnode->symbol.definition
  	   && cgraph_decide_is_function_needed (cnode, cnode->symbol.decl);
    if (varpool_node *vnode = dyn_cast <varpool_node> (node))
!     return vnode->symbol.definition
  	   && !DECL_EXTERNAL (vnode->symbol.decl)
  	   && decide_is_variable_needed (vnode, vnode->symbol.decl);
    return false;
  }
  
  /* Discover all functions and variables that are trivially needed, analyze
     them as well as all functions and variables referred by them  */
  
  static void
! analyze_functions (void)
  {
    /* Keep track of already processed nodes when called multiple times for
       intermodule optimization.  */
*************** cgraph_analyze_functions (void)
*** 914,920 ****
  	   node != (symtab_node)first_analyzed
  	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
  	{
! 	  if (symbol_finalized_and_needed (node))
  	    {
  	      enqueue_node (node);
  	      if (!changed && cgraph_dump_file)
--- 903,909 ----
  	   node != (symtab_node)first_analyzed
  	   && node != (symtab_node)first_analyzed_var; node = node->symbol.next)
  	{
! 	  if (symbol_defined_and_needed (node))
  	    {
  	      enqueue_node (node);
  	      if (!changed && cgraph_dump_file)
*************** cgraph_analyze_functions (void)
*** 942,948 ****
  	  node = first;
  	  first = (symtab_node)first->symbol.aux;
  	  cgraph_node *cnode = dyn_cast <cgraph_node> (node);
! 	  if (cnode && cnode->local.finalized)
  	    {
  	      struct cgraph_edge *edge;
  	      tree decl = cnode->symbol.decl;
--- 931,937 ----
  	  node = first;
  	  first = (symtab_node)first->symbol.aux;
  	  cgraph_node *cnode = dyn_cast <cgraph_node> (node);
! 	  if (cnode && cnode->symbol.definition)
  	    {
  	      struct cgraph_edge *edge;
  	      tree decl = cnode->symbol.decl;
*************** cgraph_analyze_functions (void)
*** 951,957 ****
  	      and later using weak alias attribute to kill its body.
  	      See gcc.c-torture/compile/20011119-1.c  */
  	      if (!DECL_STRUCT_FUNCTION (decl)
! 		  && (!cnode->alias || !cnode->thunk.alias)
  		  && !cnode->thunk.thunk_p
  		  && !cnode->dispatcher_function)
  		{
--- 940,946 ----
  	      and later using weak alias attribute to kill its body.
  	      See gcc.c-torture/compile/20011119-1.c  */
  	      if (!DECL_STRUCT_FUNCTION (decl)
! 		  && (!cnode->symbol.alias || !cnode->thunk.alias)
  		  && !cnode->thunk.thunk_p
  		  && !cnode->dispatcher_function)
  		{
*************** cgraph_analyze_functions (void)
*** 960,970 ****
  		  continue;
  		}
  
! 	      if (!cnode->analyzed)
! 		cgraph_analyze_function (cnode);
  
  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
! 		if (edge->callee->local.finalized)
  		   enqueue_node ((symtab_node)edge->callee);
  
  	      /* If decl is a clone of an abstract function,
--- 949,959 ----
  		  continue;
  		}
  
! 	      if (!cnode->symbol.analyzed)
! 		analyze_function (cnode);
  
  	      for (edge = cnode->callees; edge; edge = edge->next_callee)
! 		if (edge->callee->symbol.definition)
  		   enqueue_node ((symtab_node)edge->callee);
  
  	      /* If decl is a clone of an abstract function,
*************** cgraph_analyze_functions (void)
*** 981,987 ****
  	  else
  	    {
  	      varpool_node *vnode = dyn_cast <varpool_node> (node);
! 	      if (vnode && vnode->finalized)
  		varpool_analyze_node (vnode);
  	    }
  
--- 970,976 ----
  	  else
  	    {
  	      varpool_node *vnode = dyn_cast <varpool_node> (node);
! 	      if (vnode && vnode->symbol.definition)
  		varpool_analyze_node (vnode);
  	    }
  
*************** cgraph_analyze_functions (void)
*** 994,1000 ****
  		enqueue_node (next);
  	    }
  	  for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
! 	    if (symbol_finalized (ref->referred))
  	      enqueue_node (ref->referred);
            cgraph_process_new_functions ();
  	}
--- 983,989 ----
  		enqueue_node (next);
  	    }
  	  for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
! 	    if (ref->referred->symbol.definition)
  	      enqueue_node (ref->referred);
            cgraph_process_new_functions ();
  	}
*************** cgraph_analyze_functions (void)
*** 1026,1040 ****
  	{
  	  tree decl = node->symbol.decl;
  
! 	  if (cnode->local.finalized && !gimple_has_body_p (decl)
! 	      && (!cnode->alias || !cnode->thunk.alias)
  	      && !cnode->thunk.thunk_p)
  	    cgraph_reset_node (cnode);
  
! 	  gcc_assert (!cnode->local.finalized || cnode->thunk.thunk_p
! 		      || cnode->alias
  		      || gimple_has_body_p (decl));
! 	  gcc_assert (cnode->analyzed == cnode->local.finalized);
  	}
        node->symbol.aux = NULL;
      }
--- 1015,1029 ----
  	{
  	  tree decl = node->symbol.decl;
  
! 	  if (cnode->symbol.definition && !gimple_has_body_p (decl)
! 	      && (!cnode->symbol.alias || !cnode->thunk.alias)
  	      && !cnode->thunk.thunk_p)
  	    cgraph_reset_node (cnode);
  
! 	  gcc_assert (!cnode->symbol.definition || cnode->thunk.thunk_p
! 		      || cnode->symbol.alias
  		      || gimple_has_body_p (decl));
! 	  gcc_assert (cnode->symbol.analyzed == cnode->symbol.definition);
  	}
        node->symbol.aux = NULL;
      }
*************** handle_alias_pairs (void)
*** 1071,1083 ****
  	  if (TREE_CODE (p->decl) == FUNCTION_DECL)
  	    {
  	      struct cgraph_node *anode = cgraph_get_create_node (p->decl);
! 	      anode->alias = true;
  	      anode->thunk.alias = p->target;
  	    }
  	  else
  	    {
  	      struct varpool_node *anode = varpool_get_node (p->decl);
! 	      anode->alias = true;
  	      anode->alias_of = p->target;
  	    }
  	  DECL_EXTERNAL (p->decl) = 1;
--- 1060,1072 ----
  	  if (TREE_CODE (p->decl) == FUNCTION_DECL)
  	    {
  	      struct cgraph_node *anode = cgraph_get_create_node (p->decl);
! 	      anode->symbol.alias = true;
  	      anode->thunk.alias = p->target;
  	    }
  	  else
  	    {
  	      struct varpool_node *anode = varpool_get_node (p->decl);
! 	      anode->symbol.alias = true;
  	      anode->alias_of = p->target;
  	    }
  	  DECL_EXTERNAL (p->decl) = 1;
*************** handle_alias_pairs (void)
*** 1117,1123 ****
            && target_node && is_a <cgraph_node> (target_node))
  	{
  	  struct cgraph_node *src_node = cgraph_get_node (p->decl);
! 	  if (src_node && src_node->local.finalized)
              cgraph_reset_node (src_node);
  	  cgraph_create_function_alias (p->decl, target_node->symbol.decl);
  	  alias_pairs->unordered_remove (i);
--- 1106,1112 ----
            && target_node && is_a <cgraph_node> (target_node))
  	{
  	  struct cgraph_node *src_node = cgraph_get_node (p->decl);
! 	  if (src_node && src_node->symbol.definition)
              cgraph_reset_node (src_node);
  	  cgraph_create_function_alias (p->decl, target_node->symbol.decl);
  	  alias_pairs->unordered_remove (i);
*************** mark_functions_to_output (void)
*** 1165,1173 ****
        /* 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.  */
!       if (node->analyzed
  	  && !node->thunk.thunk_p
! 	  && !node->alias
  	  && !node->global.inlined_to
  	  && !TREE_ASM_WRITTEN (decl)
  	  && !DECL_EXTERNAL (decl))
--- 1154,1162 ----
        /* 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.  */
!       if (node->symbol.analyzed
  	  && !node->thunk.thunk_p
! 	  && !node->symbol.alias
  	  && !node->global.inlined_to
  	  && !TREE_ASM_WRITTEN (decl)
  	  && !DECL_EXTERNAL (decl))
*************** mark_functions_to_output (void)
*** 1179,1185 ****
  	      for (next = cgraph (node->symbol.same_comdat_group);
  		   next != node;
  		   next = cgraph (next->symbol.same_comdat_group))
! 		if (!next->thunk.thunk_p && !next->alias)
  		  next->process = 1;
  	    }
  	}
--- 1168,1174 ----
  	      for (next = cgraph (node->symbol.same_comdat_group);
  		   next != node;
  		   next = cgraph (next->symbol.same_comdat_group))
! 		if (!next->thunk.thunk_p && !next->symbol.alias)
  		  next->process = 1;
  	    }
  	}
*************** mark_functions_to_output (void)
*** 1199,1205 ****
  		 are inside partition, we can end up not removing the body since we no longer
  		 have analyzed node pointing to it.  */
  	      && !node->symbol.in_other_partition
! 	      && !node->alias
  	      && !node->clones
  	      && !DECL_EXTERNAL (decl))
  	    {
--- 1188,1194 ----
  		 are inside partition, we can end up not removing the body since we no longer
  		 have analyzed node pointing to it.  */
  	      && !node->symbol.in_other_partition
! 	      && !node->symbol.alias
  	      && !node->clones
  	      && !DECL_EXTERNAL (decl))
  	    {
*************** assemble_thunk (struct cgraph_node *node
*** 1435,1441 ****
        set_cfun (NULL);
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
        node->thunk.thunk_p = false;
!       node->analyzed = false;
      }
    else
      {
--- 1424,1430 ----
        set_cfun (NULL);
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
        node->thunk.thunk_p = false;
!       node->symbol.analyzed = false;
      }
    else
      {
*************** output_in_order (void)
*** 1800,1806 ****
  
    FOR_EACH_DEFINED_FUNCTION (pf)
      {
!       if (pf->process && !pf->thunk.thunk_p && !pf->alias)
  	{
  	  i = pf->symbol.order;
  	  gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
--- 1789,1795 ----
  
    FOR_EACH_DEFINED_FUNCTION (pf)
      {
!       if (pf->process && !pf->thunk.thunk_p && !pf->symbol.alias)
  	{
  	  i = pf->symbol.order;
  	  gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
*************** output_weakrefs (void)
*** 1943,1956 ****
    struct cgraph_node *node;
    struct varpool_node *vnode;
    FOR_EACH_FUNCTION (node)
!     if (node->alias && DECL_EXTERNAL (node->symbol.decl)
          && !TREE_ASM_WRITTEN (node->symbol.decl)
  	&& lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
        do_assemble_alias (node->symbol.decl,
  		         node->thunk.alias && DECL_P (node->thunk.alias) ? DECL_ASSEMBLER_NAME (node->thunk.alias)
  		         : get_alias_symbol (node->symbol.decl));
    FOR_EACH_VARIABLE (vnode)
!     if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl)
          && !TREE_ASM_WRITTEN (vnode->symbol.decl)
  	&& lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
        do_assemble_alias (vnode->symbol.decl,
--- 1932,1945 ----
    struct cgraph_node *node;
    struct varpool_node *vnode;
    FOR_EACH_FUNCTION (node)
!     if (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl)
          && !TREE_ASM_WRITTEN (node->symbol.decl)
  	&& lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)))
        do_assemble_alias (node->symbol.decl,
  		         node->thunk.alias && DECL_P (node->thunk.alias) ? DECL_ASSEMBLER_NAME (node->thunk.alias)
  		         : get_alias_symbol (node->symbol.decl));
    FOR_EACH_VARIABLE (vnode)
!     if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl)
          && !TREE_ASM_WRITTEN (vnode->symbol.decl)
  	&& lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->symbol.decl)))
        do_assemble_alias (vnode->symbol.decl,
*************** finalize_compilation_unit (void)
*** 2115,2127 ****
  
    /* Gimplify and lower all functions, compute reachability and
       remove unreachable nodes.  */
!   cgraph_analyze_functions ();
  
    /* Mark alias targets necessary and emit diagnostics.  */
    handle_alias_pairs ();
  
    /* Gimplify and lower thunks.  */
!   cgraph_analyze_functions ();
  
    /* Finally drive the pass manager.  */
    compile ();
--- 2104,2116 ----
  
    /* Gimplify and lower all functions, compute reachability and
       remove unreachable nodes.  */
!   analyze_functions ();
  
    /* Mark alias targets necessary and emit diagnostics.  */
    handle_alias_pairs ();
  
    /* Gimplify and lower thunks.  */
!   analyze_functions ();
  
    /* Finally drive the pass manager.  */
    compile ();
Index: cp/tree.c
===================================================================
*** cp/tree.c	(revision 199343)
--- cp/tree.c	(working copy)
*************** cp_fix_function_decl_p (tree decl)
*** 3980,3986 ****
  
        /* Don't fix same_body aliases.  Although they don't have their own
  	 CFG, they share it with what they alias to.  */
!       if (!node || !node->alias
  	  || !vec_safe_length (node->symbol.ref_list.references))
  	return true;
      }
--- 3980,3986 ----
  
        /* Don't fix same_body aliases.  Although they don't have their own
  	 CFG, they share it with what they alias to.  */
!       if (!node || !node->symbol.alias
  	  || !vec_safe_length (node->symbol.ref_list.references))
  	return true;
      }
Index: cp/decl2.c
===================================================================
*** cp/decl2.c	(revision 199343)
--- cp/decl2.c	(working copy)
*************** import_export_class (tree ctype)
*** 1803,1809 ****
  static bool
  var_finalized_p (tree var)
  {
!   return varpool_node_for_decl (var)->finalized;
  }
  
  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
--- 1803,1809 ----
  static bool
  var_finalized_p (tree var)
  {
!   return varpool_node_for_decl (var)->symbol.definition;
  }
  
  /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
*************** cp_write_global_declarations (void)
*** 4202,4208 ****
  
  	      node = cgraph_get_node (decl);
  	      if (node->same_body_alias)
! 		node = cgraph_alias_aliased_node (node);
  
  	      cgraph_for_node_and_aliases (node, clear_decl_external,
  					   NULL, true);
--- 4202,4208 ----
  
  	      node = cgraph_get_node (decl);
  	      if (node->same_body_alias)
! 		node = cgraph_alias_target (node);
  
  	      cgraph_for_node_and_aliases (node, clear_decl_external,
  					   NULL, true);
*************** cp_write_global_declarations (void)
*** 4224,4230 ****
  	  if (!DECL_EXTERNAL (decl)
  	      && decl_needed_p (decl)
  	      && !TREE_ASM_WRITTEN (decl)
! 	      && !cgraph_get_node (decl)->local.finalized)
  	    {
  	      /* We will output the function; no longer consider it in this
  		 loop.  */
--- 4224,4230 ----
  	  if (!DECL_EXTERNAL (decl)
  	      && decl_needed_p (decl)
  	      && !TREE_ASM_WRITTEN (decl)
! 	      && !cgraph_get_node (decl)->symbol.definition)
  	    {
  	      /* We will output the function; no longer consider it in this
  		 loop.  */
Index: lto-cgraph.c
===================================================================
*** lto-cgraph.c	(revision 199343)
--- lto-cgraph.c	(working copy)
*************** bool
*** 320,326 ****
  reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
  {
    struct cgraph_edge *e;
!   if (!node->analyzed)
      return false;
    if (node->global.inlined_to)
      return false;
--- 320,326 ----
  reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
  {
    struct cgraph_edge *e;
!   if (!node->symbol.definition)
      return false;
    if (node->global.inlined_to)
      return false;
*************** lto_output_node (struct lto_simple_outpu
*** 380,386 ****
  
    boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
  
!   if (node->analyzed && !boundary_p)
      tag = LTO_symtab_analyzed_node;
    else
      tag = LTO_symtab_unavail_node;
--- 380,386 ----
  
    boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
  
!   if (node->symbol.analyzed && !boundary_p)
      tag = LTO_symtab_analyzed_node;
    else
      tag = LTO_symtab_unavail_node;
*************** lto_output_node (struct lto_simple_outpu
*** 399,405 ****
       Cherry-picked nodes:  These are nodes we pulled from other
       translation units into SET during IPA-inlining.  We make them as
       local static nodes to prevent clashes with other local statics.  */
!   if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->symbol.decl))
      {
        /* Inline clones can not be part of boundary.  
           gcc_assert (!node->global.inlined_to);  
--- 399,405 ----
       Cherry-picked nodes:  These are nodes we pulled from other
       translation units into SET during IPA-inlining.  We make them as
       local static nodes to prevent clashes with other local statics.  */
!   if (boundary_p && node->symbol.analyzed && !DECL_EXTERNAL (node->symbol.decl))
      {
        /* Inline clones can not be part of boundary.  
           gcc_assert (!node->global.inlined_to);  
*************** lto_output_node (struct lto_simple_outpu
*** 463,469 ****
    bp = bitpack_create (ob->main_stream);
    bp_pack_value (&bp, node->local.local, 1);
    bp_pack_value (&bp, node->symbol.externally_visible, 1);
!   bp_pack_value (&bp, node->local.finalized, 1);
    bp_pack_value (&bp, node->local.versionable, 1);
    bp_pack_value (&bp, node->local.can_change_signature, 1);
    bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
--- 463,469 ----
    bp = bitpack_create (ob->main_stream);
    bp_pack_value (&bp, node->local.local, 1);
    bp_pack_value (&bp, node->symbol.externally_visible, 1);
!   bp_pack_value (&bp, node->symbol.definition, 1);
    bp_pack_value (&bp, node->local.versionable, 1);
    bp_pack_value (&bp, node->local.can_change_signature, 1);
    bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
*************** lto_output_node (struct lto_simple_outpu
*** 485,491 ****
       defined in other unit, we may use the info on aliases to resolve 
       symbol1 != symbol2 type tests that we can do only for locally defined objects
       otherwise.  */
!   bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1);
    bp_pack_value (&bp, node->frequency, 2);
    bp_pack_value (&bp, node->only_called_at_startup, 1);
    bp_pack_value (&bp, node->only_called_at_exit, 1);
--- 485,491 ----
       defined in other unit, we may use the info on aliases to resolve 
       symbol1 != symbol2 type tests that we can do only for locally defined objects
       otherwise.  */
!   bp_pack_value (&bp, node->symbol.alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1);
    bp_pack_value (&bp, node->frequency, 2);
    bp_pack_value (&bp, node->only_called_at_startup, 1);
    bp_pack_value (&bp, node->only_called_at_exit, 1);
*************** lto_output_node (struct lto_simple_outpu
*** 504,511 ****
        streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
        streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
      }
!   if ((node->alias || node->thunk.thunk_p)
!       && (!boundary_p || (node->alias && DECL_EXTERNAL (node->symbol.decl))))
      {
        streamer_write_hwi_in_range (ob->main_stream, 0, 1,
  					node->thunk.alias != NULL);
--- 504,511 ----
        streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
        streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
      }
!   if ((node->symbol.alias || node->thunk.thunk_p)
!       && (!boundary_p || (node->symbol.alias && DECL_EXTERNAL (node->symbol.decl))))
      {
        streamer_write_hwi_in_range (ob->main_stream, 0, 1,
  					node->thunk.alias != NULL);
*************** static void
*** 522,528 ****
  lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
  			 lto_symtab_encoder_t encoder)
  {
!   bool boundary_p = (node->analyzed
  		     && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node));
    struct bitpack_d bp;
    int ref;
--- 522,528 ----
  lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
  			 lto_symtab_encoder_t encoder)
  {
!   bool boundary_p = (node->symbol.definition
  		     && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node));
    struct bitpack_d bp;
    int ref;
*************** lto_output_varpool_node (struct lto_simp
*** 535,544 ****
    bp_pack_value (&bp, node->symbol.externally_visible, 1);
    bp_pack_value (&bp, node->symbol.force_output, 1);
    bp_pack_value (&bp, node->symbol.unique_name, 1);
!   bp_pack_value (&bp, node->finalized, 1);
!   bp_pack_value (&bp, node->alias, 1);
    bp_pack_value (&bp, node->alias_of != NULL, 1);
!   gcc_assert (node->finalized || !node->analyzed);
    /* Constant pool initializers can be de-unified into individual ltrans units.
       FIXME: Alternatively at -Os we may want to avoid generating for them the local
       labels and share them across LTRANS partitions.  */
--- 535,544 ----
    bp_pack_value (&bp, node->symbol.externally_visible, 1);
    bp_pack_value (&bp, node->symbol.force_output, 1);
    bp_pack_value (&bp, node->symbol.unique_name, 1);
!   bp_pack_value (&bp, node->symbol.definition, 1);
!   bp_pack_value (&bp, node->symbol.alias, 1);
    bp_pack_value (&bp, node->alias_of != NULL, 1);
!   gcc_assert (node->symbol.definition || !node->symbol.analyzed);
    /* Constant pool initializers can be de-unified into individual ltrans units.
       FIXME: Alternatively at -Os we may want to avoid generating for them the local
       labels and share them across LTRANS partitions.  */
*************** lto_output_varpool_node (struct lto_simp
*** 551,557 ****
      }
    else
      {
!       bp_pack_value (&bp, node->analyzed
  		     && referenced_from_other_partition_p (&node->symbol.ref_list,
  							   encoder), 1);
        bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
--- 551,557 ----
      }
    else
      {
!       bp_pack_value (&bp, node->symbol.definition
  		     && referenced_from_other_partition_p (&node->symbol.ref_list,
  							   encoder), 1);
        bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
*************** compute_ltrans_boundary (lto_symtab_enco
*** 756,762 ****
         !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
      {
        struct varpool_node *vnode = lsei_varpool_node (lsei);
!       gcc_assert (!vnode->alias || vnode->alias_of);
        lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
        lto_set_symtab_encoder_encode_initializer (encoder, vnode);
        add_references (encoder, &vnode->symbol.ref_list);
--- 756,762 ----
         !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
      {
        struct varpool_node *vnode = lsei_varpool_node (lsei);
!       gcc_assert (!vnode->symbol.alias || vnode->alias_of);
        lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
        lto_set_symtab_encoder_encode_initializer (encoder, vnode);
        add_references (encoder, &vnode->symbol.ref_list);
*************** input_overwrite_node (struct lto_file_de
*** 883,889 ****
  
    node->local.local = bp_unpack_value (bp, 1);
    node->symbol.externally_visible = bp_unpack_value (bp, 1);
!   node->local.finalized = bp_unpack_value (bp, 1);
    node->local.versionable = bp_unpack_value (bp, 1);
    node->local.can_change_signature = bp_unpack_value (bp, 1);
    node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
--- 883,889 ----
  
    node->local.local = bp_unpack_value (bp, 1);
    node->symbol.externally_visible = bp_unpack_value (bp, 1);
!   node->symbol.definition = bp_unpack_value (bp, 1);
    node->local.versionable = bp_unpack_value (bp, 1);
    node->local.can_change_signature = bp_unpack_value (bp, 1);
    node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
*************** input_overwrite_node (struct lto_file_de
*** 893,899 ****
    node->abstract_and_needed = bp_unpack_value (bp, 1);
    node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
    node->lowered = bp_unpack_value (bp, 1);
!   node->analyzed = tag == LTO_symtab_analyzed_node;
    node->symbol.in_other_partition = bp_unpack_value (bp, 1);
    if (node->symbol.in_other_partition
        /* Avoid updating decl when we are seeing just inline clone.
--- 893,899 ----
    node->abstract_and_needed = bp_unpack_value (bp, 1);
    node->symbol.used_from_other_partition = bp_unpack_value (bp, 1);
    node->lowered = bp_unpack_value (bp, 1);
!   node->symbol.analyzed = tag == LTO_symtab_analyzed_node;
    node->symbol.in_other_partition = bp_unpack_value (bp, 1);
    if (node->symbol.in_other_partition
        /* Avoid updating decl when we are seeing just inline clone.
*************** input_overwrite_node (struct lto_file_de
*** 909,915 ****
        DECL_EXTERNAL (node->symbol.decl) = 1;
        TREE_STATIC (node->symbol.decl) = 0;
      }
!   node->alias = bp_unpack_value (bp, 1);
    node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
    node->only_called_at_startup = bp_unpack_value (bp, 1);
    node->only_called_at_exit = bp_unpack_value (bp, 1);
--- 909,915 ----
        DECL_EXTERNAL (node->symbol.decl) = 1;
        TREE_STATIC (node->symbol.decl) = 0;
      }
!   node->symbol.alias = bp_unpack_value (bp, 1);
    node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
    node->only_called_at_startup = bp_unpack_value (bp, 1);
    node->only_called_at_exit = bp_unpack_value (bp, 1);
*************** input_node (struct lto_file_decl_data *f
*** 1004,1010 ****
        node->thunk.virtual_value = virtual_value;
        node->thunk.virtual_offset_p = (type & 4);
      }
!   if (node->thunk.thunk_p || node->alias)
      {
        if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1))
  	{
--- 1004,1010 ----
        node->thunk.virtual_value = virtual_value;
        node->thunk.virtual_offset_p = (type & 4);
      }
!   if (node->thunk.thunk_p || node->symbol.alias)
      {
        if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1))
  	{
*************** input_varpool_node (struct lto_file_decl
*** 1044,1055 ****
    node->symbol.externally_visible = bp_unpack_value (&bp, 1);
    node->symbol.force_output = bp_unpack_value (&bp, 1);
    node->symbol.unique_name = bp_unpack_value (&bp, 1);
!   node->finalized = bp_unpack_value (&bp, 1);
!   node->alias = bp_unpack_value (&bp, 1);
    non_null_aliasof = bp_unpack_value (&bp, 1);
    node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
    node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
!   node->analyzed = (node->finalized && (!node->alias || !node->symbol.in_other_partition)); 
    if (node->symbol.in_other_partition)
      {
        DECL_EXTERNAL (node->symbol.decl) = 1;
--- 1044,1055 ----
    node->symbol.externally_visible = bp_unpack_value (&bp, 1);
    node->symbol.force_output = bp_unpack_value (&bp, 1);
    node->symbol.unique_name = bp_unpack_value (&bp, 1);
!   node->symbol.definition = bp_unpack_value (&bp, 1);
!   node->symbol.alias = bp_unpack_value (&bp, 1);
    non_null_aliasof = bp_unpack_value (&bp, 1);
    node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
    node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
!   node->symbol.analyzed = (node->symbol.definition && (!node->symbol.alias || !node->symbol.in_other_partition)); 
    if (node->symbol.in_other_partition)
      {
        DECL_EXTERNAL (node->symbol.decl) = 1;
Index: dbxout.c
===================================================================
*** dbxout.c	(revision 199343)
--- dbxout.c	(working copy)
*************** dbxout_expand_expr (tree expr)
*** 2480,2486 ****
  	     return NULL, otherwise stabs might reference an undefined
  	     symbol.  */
  	  struct varpool_node *node = varpool_get_node (expr);
! 	  if (!node || !node->analyzed)
  	    return NULL;
  	}
        /* FALLTHRU */
--- 2480,2486 ----
  	     return NULL, otherwise stabs might reference an undefined
  	     symbol.  */
  	  struct varpool_node *node = varpool_get_node (expr);
! 	  if (!node || !node->symbol.definition)
  	    return NULL;
  	}
        /* FALLTHRU */
Index: cgraphclones.c
===================================================================
*** cgraphclones.c	(revision 199343)
--- cgraphclones.c	(working copy)
*************** cgraph_clone_node (struct cgraph_node *n
*** 189,195 ****
        new_node->next_nested = new_node->origin->nested;
        new_node->origin->nested = new_node;
      }
!   new_node->analyzed = n->analyzed;
    new_node->local = n->local;
    new_node->symbol.externally_visible = false;
    new_node->local.local = true;
--- 189,196 ----
        new_node->next_nested = new_node->origin->nested;
        new_node->origin->nested = new_node;
      }
!   new_node->symbol.analyzed = n->symbol.analyzed;
!   new_node->symbol.definition = n->symbol.definition;
    new_node->local = n->local;
    new_node->symbol.externally_visible = false;
    new_node->local.local = true;
*************** cgraph_copy_node_for_versioning (struct
*** 638,647 ****
  
     new_version = cgraph_create_node (new_decl);
  
!    new_version->analyzed = old_version->analyzed;
     new_version->local = old_version->local;
     new_version->symbol.externally_visible = false;
!    new_version->local.local = old_version->analyzed;
     new_version->global = old_version->global;
     new_version->rtl = old_version->rtl;
     new_version->count = old_version->count;
--- 639,649 ----
  
     new_version = cgraph_create_node (new_decl);
  
!    new_version->symbol.analyzed = old_version->symbol.analyzed;
!    new_version->symbol.definition = old_version->symbol.definition;
     new_version->local = old_version->local;
     new_version->symbol.externally_visible = false;
!    new_version->local.local = new_version->symbol.definition;
     new_version->global = old_version->global;
     new_version->rtl = old_version->rtl;
     new_version->count = old_version->count;
*************** cgraph_materialize_clone (struct cgraph_
*** 791,797 ****
      node->clone_of->clones = node->next_sibling_clone;
    node->next_sibling_clone = NULL;
    node->prev_sibling_clone = NULL;
!   if (!node->clone_of->analyzed && !node->clone_of->clones)
      {
        cgraph_release_function_body (node->clone_of);
        cgraph_node_remove_callees (node->clone_of);
--- 793,799 ----
      node->clone_of->clones = node->next_sibling_clone;
    node->next_sibling_clone = NULL;
    node->prev_sibling_clone = NULL;
!   if (!node->clone_of->symbol.analyzed && !node->clone_of->clones)
      {
        cgraph_release_function_body (node->clone_of);
        cgraph_node_remove_callees (node->clone_of);
*************** cgraph_materialize_all_clones (void)
*** 874,880 ****
  	}
      }
    FOR_EACH_FUNCTION (node)
!     if (!node->analyzed && node->callees)
        cgraph_node_remove_callees (node);
    if (cgraph_dump_file)
      fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
--- 876,882 ----
  	}
      }
    FOR_EACH_FUNCTION (node)
!     if (!node->symbol.analyzed && node->callees)
        cgraph_node_remove_callees (node);
    if (cgraph_dump_file)
      fprintf (cgraph_dump_file, "Materialization Call site updates done.\n");
Index: ipa-pure-const.c
===================================================================
*** ipa-pure-const.c	(revision 199343)
--- ipa-pure-const.c	(working copy)
*************** analyze_function (struct cgraph_node *fn
*** 738,744 ****
  		    flags_from_decl_or_type (fn->symbol.decl),
  		    cgraph_node_cannot_return (fn));
  
!   if (fn->thunk.thunk_p || fn->alias)
      {
        /* Thunk gets propagated through, so nothing interesting happens.  */
        gcc_assert (ipa);
--- 738,744 ----
  		    flags_from_decl_or_type (fn->symbol.decl),
  		    cgraph_node_cannot_return (fn));
  
!   if (fn->thunk.thunk_p || fn->symbol.alias)
      {
        /* Thunk gets propagated through, so nothing interesting happens.  */
        gcc_assert (ipa);
*************** pure_const_write_summary (void)
*** 951,957 ****
         lsei_next_function_in_partition (&lsei))
      {
        node = lsei_cgraph_node (lsei);
!       if (node->analyzed && has_function_state (node))
  	count++;
      }
  
--- 951,957 ----
         lsei_next_function_in_partition (&lsei))
      {
        node = lsei_cgraph_node (lsei);
!       if (node->symbol.definition && has_function_state (node))
  	count++;
      }
  
*************** pure_const_write_summary (void)
*** 962,968 ****
         lsei_next_function_in_partition (&lsei))
      {
        node = lsei_cgraph_node (lsei);
!       if (node->analyzed && has_function_state (node))
  	{
  	  struct bitpack_d bp;
  	  funct_state fs;
--- 962,968 ----
         lsei_next_function_in_partition (&lsei))
      {
        node = lsei_cgraph_node (lsei);
!       if (node->symbol.definition && has_function_state (node))
  	{
  	  struct bitpack_d bp;
  	  funct_state fs;
*************** propagate_pure_const (void)
*** 1124,1130 ****
        int count = 0;
        node = order[i];
  
!       if (node->alias)
  	continue;
  
        if (dump_file && (dump_flags & TDF_DETAILS))
--- 1124,1130 ----
        int count = 0;
        node = order[i];
  
!       if (node->symbol.alias)
  	continue;
  
        if (dump_file && (dump_flags & TDF_DETAILS))
*************** propagate_nothrow (void)
*** 1394,1400 ****
        bool can_throw = false;
        node = order[i];
  
!       if (node->alias)
  	continue;
  
        /* Find the worst state for any node in the cycle.  */
--- 1394,1400 ----
        bool can_throw = false;
        node = order[i];
  
!       if (node->symbol.alias)
  	continue;
  
        /* Find the worst state for any node in the cycle.  */
Index: lto-streamer-out.c
===================================================================
*** lto-streamer-out.c	(revision 199343)
--- lto-streamer-out.c	(working copy)
*************** lto_output (void)
*** 1013,1019 ****
        cgraph_node *node = dyn_cast <cgraph_node> (snode);
        if (node
  	  && lto_symtab_encoder_encode_body_p (encoder, node)
! 	  && !node->alias
  	  && !node->thunk.thunk_p)
  	{
  #ifdef ENABLE_CHECKING
--- 1013,1019 ----
        cgraph_node *node = dyn_cast <cgraph_node> (snode);
        if (node
  	  && lto_symtab_encoder_encode_body_p (encoder, node)
! 	  && !node->symbol.alias
  	  && !node->thunk.thunk_p)
  	{
  #ifdef ENABLE_CHECKING
*************** write_symbol (struct streamer_tree_cache
*** 1243,1252 ****
  
        /* When something is defined, it should have node attached.  */
        gcc_assert (alias || TREE_CODE (t) != VAR_DECL
! 		  || varpool_get_node (t)->finalized);
        gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
  		  || (cgraph_get_node (t)
! 		      && cgraph_get_node (t)->analyzed));
      }
  
    /* Imitate what default_elf_asm_output_external do.
--- 1243,1252 ----
  
        /* When something is defined, it should have node attached.  */
        gcc_assert (alias || TREE_CODE (t) != VAR_DECL
! 		  || varpool_get_node (t)->symbol.definition);
        gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL
  		  || (cgraph_get_node (t)
! 		      && cgraph_get_node (t)->symbol.definition));
      }
  
    /* Imitate what default_elf_asm_output_external do.
Index: ipa-utils.c
===================================================================
*** ipa-utils.c	(revision 199343)
--- ipa-utils.c	(working copy)
*************** ipa_reverse_postorder (struct cgraph_nod
*** 287,293 ****
  	  && (pass
  	      || (!node->symbol.address_taken
  		  && !node->global.inlined_to
! 		  && !node->alias && !node->thunk.thunk_p
  		  && !cgraph_only_called_directly_p (node))))
  	{
  	  stack_size = 0;
--- 287,293 ----
  	  && (pass
  	      || (!node->symbol.address_taken
  		  && !node->global.inlined_to
! 		  && !node->symbol.alias && !node->thunk.thunk_p
  		  && !cgraph_only_called_directly_p (node))))
  	{
  	  stack_size = 0;
Index: ipa-inline.c
===================================================================
*** ipa-inline.c	(revision 199343)
--- ipa-inline.c	(working copy)
*************** can_inline_edge_p (struct cgraph_edge *e
*** 253,259 ****
  
    gcc_assert (e->inline_failed);
  
!   if (!callee || !callee->analyzed)
      {
        e->inline_failed = CIF_BODY_NOT_AVAILABLE;
        inlinable = false;
--- 253,259 ----
  
    gcc_assert (e->inline_failed);
  
!   if (!callee || !callee->symbol.definition)
      {
        e->inline_failed = CIF_BODY_NOT_AVAILABLE;
        inlinable = false;
*************** update_caller_keys (fibheap_t heap, stru
*** 1100,1106 ****
    int i;
    struct ipa_ref *ref;
  
!   if ((!node->alias && !inline_summary (node)->inlinable)
        || cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
        || node->global.inlined_to)
      return;
--- 1100,1106 ----
    int i;
    struct ipa_ref *ref;
  
!   if ((!node->symbol.alias && !inline_summary (node)->inlinable)
        || cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
        || node->global.inlined_to)
      return;
*************** ipa_inline (void)
*** 1795,1800 ****
--- 1795,1803 ----
      }
  
    inline_small_functions ();
+ 
+   /* Do first after-inlining removal.  We want to remove all "stale" extern inline
+      functions and virtual functions so we really know what is called once.  */
    symtab_remove_unreachable_nodes (false, dump_file);
    free (order);
  
Index: dwarf2out.c
===================================================================
*** dwarf2out.c	(revision 199343)
--- dwarf2out.c	(working copy)
*************** reference_to_unused (tree * tp, int * wa
*** 14919,14925 ****
    else if (TREE_CODE (*tp) == VAR_DECL)
      {
        struct varpool_node *node = varpool_get_node (*tp);
!       if (!node || !node->analyzed)
  	return *tp;
      }
    else if (TREE_CODE (*tp) == FUNCTION_DECL
--- 14919,14925 ----
    else if (TREE_CODE (*tp) == VAR_DECL)
      {
        struct varpool_node *node = varpool_get_node (*tp);
!       if (!node || !node->symbol.definition)
  	return *tp;
      }
    else if (TREE_CODE (*tp) == FUNCTION_DECL
*************** premark_types_used_by_global_vars_helper
*** 17597,17603 ****
        /* Ask cgraph if the global variable really is to be emitted.
           If yes, then we'll keep the DIE of ENTRY->TYPE.  */
        struct varpool_node *node = varpool_get_node (entry->var_decl);
!       if (node && node->analyzed)
  	{
  	  die->die_perennial_p = 1;
  	  /* Keep the parent DIEs as well.  */
--- 17597,17603 ----
        /* Ask cgraph if the global variable really is to be emitted.
           If yes, then we'll keep the DIE of ENTRY->TYPE.  */
        struct varpool_node *node = varpool_get_node (entry->var_decl);
!       if (node && node->symbol.definition)
  	{
  	  die->die_perennial_p = 1;
  	  /* Keep the parent DIEs as well.  */
Index: tree-eh.c
===================================================================
*** tree-eh.c	(revision 199343)
--- tree-eh.c	(working copy)
*************** tree_could_trap_p (tree expr)
*** 2580,2586 ****
        /* Assume that accesses to weak functions may trap, unless we know
  	 they are certainly defined in current TU or in some other
  	 LTO partition.  */
!       if (DECL_WEAK (expr))
  	{
  	  struct cgraph_node *node;
  	  if (!DECL_EXTERNAL (expr))
--- 2580,2586 ----
        /* Assume that accesses to weak functions may trap, unless we know
  	 they are certainly defined in current TU or in some other
  	 LTO partition.  */
!       if (DECL_WEAK (expr) && !DECL_COMDAT (expr))
  	{
  	  struct cgraph_node *node;
  	  if (!DECL_EXTERNAL (expr))
*************** tree_could_trap_p (tree expr)
*** 2596,2602 ****
        /* Assume that accesses to weak vars may trap, unless we know
  	 they are certainly defined in current TU or in some other
  	 LTO partition.  */
!       if (DECL_WEAK (expr))
  	{
  	  struct varpool_node *node;
  	  if (!DECL_EXTERNAL (expr))
--- 2596,2602 ----
        /* Assume that accesses to weak vars may trap, unless we know
  	 they are certainly defined in current TU or in some other
  	 LTO partition.  */
!       if (DECL_WEAK (expr) && !DECL_COMDAT (expr))
  	{
  	  struct varpool_node *node;
  	  if (!DECL_EXTERNAL (expr))
Index: ipa-split.c
===================================================================
*** ipa-split.c	(revision 199343)
--- ipa-split.c	(working copy)
*************** consider_split (struct split_point *curr
*** 367,389 ****
    unsigned int i;
    int incoming_freq = 0;
    tree retval;
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_split_point (dump_file, current);
  
    FOR_EACH_EDGE (e, ei, current->entry_bb->preds)
!     if (!bitmap_bit_p (current->split_bbs, e->src->index))
!       incoming_freq += EDGE_FREQUENCY (e);
  
    /* Do not split when we would end up calling function anyway.  */
    if (incoming_freq
        >= (ENTRY_BLOCK_PTR->frequency
  	  * PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY) / 100))
      {
!       if (dump_file && (dump_flags & TDF_DETAILS))
! 	fprintf (dump_file,
! 		 "  Refused: incoming frequency is too large.\n");
!       return;
      }
  
    if (!current->header_size)
--- 367,412 ----
    unsigned int i;
    int incoming_freq = 0;
    tree retval;
+   bool back_edge = false;
  
    if (dump_file && (dump_flags & TDF_DETAILS))
      dump_split_point (dump_file, current);
  
    FOR_EACH_EDGE (e, ei, current->entry_bb->preds)
!     {
!       if (e->flags & EDGE_DFS_BACK)
! 	back_edge = true;
!       if (!bitmap_bit_p (current->split_bbs, e->src->index))
!         incoming_freq += EDGE_FREQUENCY (e);
!     }
  
    /* Do not split when we would end up calling function anyway.  */
    if (incoming_freq
        >= (ENTRY_BLOCK_PTR->frequency
  	  * PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY) / 100))
      {
!       /* When profile is guessed, we can not expect it to give us
! 	 realistic estimate on likelyness of function taking the
! 	 complex path.  As a special case, when tail of the function is
! 	 a loop, enable splitting since inlining code skipping the loop
! 	 is likely noticeable win.  */
!       if (back_edge
! 	  && profile_status != PROFILE_READ
! 	  && incoming_freq < ENTRY_BLOCK_PTR->frequency)
! 	{
! 	  if (dump_file && (dump_flags & TDF_DETAILS))
! 	    fprintf (dump_file,
! 		     "  Split before loop, accepting despite low frequencies %i %i.\n",
! 		     incoming_freq,
! 		     ENTRY_BLOCK_PTR->frequency);
! 	}
!       else
! 	{
! 	  if (dump_file && (dump_flags & TDF_DETAILS))
! 	    fprintf (dump_file,
! 		     "  Refused: incoming frequency is too large.\n");
! 	  return;
! 	}
      }
  
    if (!current->header_size)
*************** execute_split_functions (void)
*** 1533,1538 ****
--- 1556,1566 ----
        return 0;
      }
  
+   /* We enforce splitting after loop headers when profile info is not
+      available.  */
+   if (profile_status != PROFILE_READ)
+     mark_dfs_back_edges ();
+ 
    /* Initialize bitmap to track forbidden calls.  */
    forbidden_dominators = BITMAP_ALLOC (NULL);
    calculate_dominance_info (CDI_DOMINATORS);
Index: ipa.c
===================================================================
*** ipa.c	(revision 199343)
--- ipa.c	(working copy)
*************** along with GCC; see the file COPYING3.
*** 39,44 ****
--- 39,91 ----
  #include "lto-streamer.h"
  #include "data-streamer.h"
  
+ /* Return true when NODE can not be local. Worker for cgraph_local_node_p.  */
+ 
+ static bool
+ cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
+ {
+    /* FIXME: Aliases can be local, but i386 gets thunks wrong then.  */
+    return !(cgraph_only_called_directly_or_aliased_p (node)
+ 	    && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
+ 	    && node->symbol.definition
+ 	    && !DECL_EXTERNAL (node->symbol.decl)
+ 	    && !node->symbol.externally_visible
+ 	    && !node->symbol.used_from_other_partition
+ 	    && !node->symbol.in_other_partition);
+ }
+ 
+ /* Return true when function can be marked local.  */
+ 
+ static bool
+ cgraph_local_node_p (struct cgraph_node *node)
+ {
+    struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
+ 
+    /* FIXME: thunks can be considered local, but we need prevent i386
+       from attempting to change calling convention of them.  */
+    if (n->thunk.thunk_p)
+      return false;
+    return !cgraph_for_node_and_aliases (n,
+ 					cgraph_non_local_node_p_1, NULL, true);
+ 					
+ }
+ 
+ /* Return true when NODE has ADDR reference.  */
+ 
+ static bool
+ has_addr_references_p (struct cgraph_node *node,
+ 		       void *data ATTRIBUTE_UNUSED)
+ {
+   int i;
+   struct ipa_ref *ref;
+ 
+   for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
+ 					      i, ref); i++)
+     if (ref->use == IPA_REF_ADDR)
+       return true;
+   return false;
+ }
+ 
  /* Look for all functions inlined to NODE and update their inlined_to pointers
     to INLINED_TO.  */
  
*************** process_references (struct ipa_ref_list
*** 89,167 ****
    struct ipa_ref *ref;
    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
      {
!       if (is_a <cgraph_node> (ref->referred))
! 	{
! 	  struct cgraph_node *node = ipa_ref_node (ref);
  
! 	  if (node->analyzed
! 	      && (!DECL_EXTERNAL (node->symbol.decl)
! 		  || node->alias
! 	          || before_inlining_p))
! 	    pointer_set_insert (reachable, node);
! 	  enqueue_node ((symtab_node) node, first, reachable);
! 	}
!       else
! 	{
! 	  struct varpool_node *node = ipa_ref_varpool_node (ref);
! 
! 	  if (node->analyzed
! 	      && (!DECL_EXTERNAL (node->symbol.decl)
! 		  || node->alias
! 		  || before_inlining_p))
! 	    pointer_set_insert (reachable, node);
! 	  enqueue_node ((symtab_node) node, first, reachable);
! 	}
      }
  }
  
  
- /* Return true when NODE can not be local. Worker for cgraph_local_node_p.  */
- 
- static bool
- cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
- {
-    /* FIXME: Aliases can be local, but i386 gets thunks wrong then.  */
-    return !(cgraph_only_called_directly_or_aliased_p (node)
- 	    && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
- 	    && node->analyzed
- 	    && !DECL_EXTERNAL (node->symbol.decl)
- 	    && !node->symbol.externally_visible
- 	    && !node->symbol.used_from_other_partition
- 	    && !node->symbol.in_other_partition);
- }
- 
- /* Return true when function can be marked local.  */
- 
- static bool
- cgraph_local_node_p (struct cgraph_node *node)
- {
-    struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
- 
-    /* FIXME: thunks can be considered local, but we need prevent i386
-       from attempting to change calling convention of them.  */
-    if (n->thunk.thunk_p)
-      return false;
-    return !cgraph_for_node_and_aliases (n,
- 					cgraph_non_local_node_p_1, NULL, true);
- 					
- }
- 
- /* Return true when NODE has ADDR reference.  */
- 
- static bool
- has_addr_references_p (struct cgraph_node *node,
- 		       void *data ATTRIBUTE_UNUSED)
- {
-   int i;
-   struct ipa_ref *ref;
- 
-   for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
- 					     i, ref); i++)
-     if (ref->use == IPA_REF_ADDR)
-       return true;
-   return false;
- }
- 
  /* Perform reachability analysis and reclaim all unreachable nodes.
  
     The algorithm is basically mark&sweep but with some extra refinements:
--- 136,158 ----
    struct ipa_ref *ref;
    for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
      {
!       symtab_node node = ref->referred;
  
!       if (node->symbol.definition
! 	  && (!DECL_EXTERNAL (node->symbol.decl)
! 	      || node->symbol.alias
! 	      || (before_inlining_p
! 		  /* We use variable constructors during late complation for
! 		     constant folding.  Keep references alive so partitioning
! 		     knows about potential references.  */
! 		  || (TREE_CODE (node->symbol.decl) == VAR_DECL
! 		      && flag_wpa && const_value_known_p (node->symbol.decl)))))
! 	pointer_set_insert (reachable, node);
!       enqueue_node ((symtab_node) node, first, reachable);
      }
  }
  
  
  /* Perform reachability analysis and reclaim all unreachable nodes.
  
     The algorithm is basically mark&sweep but with some extra refinements:
*************** symtab_remove_unreachable_nodes (bool be
*** 303,312 ****
  	      struct cgraph_edge *e;
  	      for (e = cnode->callees; e; e = e->next_callee)
  		{
! 		  if (e->callee->analyzed
  		      && (!e->inline_failed
  			  || !DECL_EXTERNAL (e->callee->symbol.decl)
! 			  || cnode->alias
  			  || before_inlining_p))
  		    pointer_set_insert (reachable, e->callee);
  		  enqueue_node ((symtab_node) e->callee, &first, reachable);
--- 294,303 ----
  	      struct cgraph_edge *e;
  	      for (e = cnode->callees; e; e = e->next_callee)
  		{
! 		  if (e->callee->symbol.definition
  		      && (!e->inline_failed
  			  || !DECL_EXTERNAL (e->callee->symbol.decl)
! 			  || cnode->symbol.alias
  			  || before_inlining_p))
  		    pointer_set_insert (reachable, e->callee);
  		  enqueue_node ((symtab_node) e->callee, &first, reachable);
*************** symtab_remove_unreachable_nodes (bool be
*** 314,320 ****
  
  	      /* When inline clone exists, mark body to be preserved so when removing
  		 offline copy of the function we don't kill it.  */
! 	      if (!cnode->alias && cnode->global.inlined_to)
  	        pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
  	    }
  
--- 305,311 ----
  
  	      /* When inline clone exists, mark body to be preserved so when removing
  		 offline copy of the function we don't kill it.  */
! 	      if (!cnode->symbol.alias && cnode->global.inlined_to)
  	        pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
  	    }
  
*************** symtab_remove_unreachable_nodes (bool be
*** 339,345 ****
        varpool_node *vnode = dyn_cast <varpool_node> (node);
        if (vnode
  	  && DECL_EXTERNAL (node->symbol.decl)
! 	  && !vnode->alias
  	  && in_boundary_p)
  	{
  	  struct ipa_ref *ref;
--- 330,336 ----
        varpool_node *vnode = dyn_cast <varpool_node> (node);
        if (vnode
  	  && DECL_EXTERNAL (node->symbol.decl)
! 	  && !vnode->symbol.alias
  	  && in_boundary_p)
  	{
  	  struct ipa_ref *ref;
*************** symtab_remove_unreachable_nodes (bool be
*** 352,357 ****
--- 343,350 ----
    for (node = cgraph_first_function (); node; node = next)
      {
        next = cgraph_next_function (node);
+ 
+       /* If node is not needed at all, remove it.  */
        if (!node->symbol.aux)
  	{
  	  if (file)
*************** symtab_remove_unreachable_nodes (bool be
*** 359,378 ****
  	  cgraph_remove_node (node);
  	  changed = true;
  	}
        else if (!pointer_set_contains (reachable, node))
          {
! 	  if (node->analyzed)
  	    {
  	      if (file)
  		fprintf (file, " %s", cgraph_node_name (node));
! 	      cgraph_node_remove_callees (node);
! 	      ipa_remove_all_references (&node->symbol.ref_list);
  	      changed = true;
  	    }
- 	  if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
- 	      && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
- 	    cgraph_release_function_body (node);
- 	  node->analyzed = false;
  	}
      }
  
--- 352,369 ----
  	  cgraph_remove_node (node);
  	  changed = true;
  	}
+       /* If node is unreachable, remove its body.  */
        else if (!pointer_set_contains (reachable, node))
          {
! 	  if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl))
! 	    cgraph_release_function_body (node);
! 	  if (node->symbol.definition)
  	    {
  	      if (file)
  		fprintf (file, " %s", cgraph_node_name (node));
! 	      cgraph_reset_node (node);
  	      changed = true;
  	    }
  	}
      }
  
*************** symtab_remove_unreachable_nodes (bool be
*** 406,419 ****
  	}
        else if (!pointer_set_contains (reachable, vnode))
          {
! 	  if (vnode->analyzed)
  	    {
  	      if (file)
  		fprintf (file, " %s", varpool_node_name (vnode));
  	      changed = true;
  	    }
! 	  vnode->analyzed = false;
  	  vnode->symbol.aux = NULL;
  	}
        else
  	vnode->symbol.aux = NULL;
--- 397,416 ----
  	}
        else if (!pointer_set_contains (reachable, vnode))
          {
! 	  if (vnode->symbol.definition)
  	    {
  	      if (file)
  		fprintf (file, " %s", varpool_node_name (vnode));
  	      changed = true;
  	    }
! 	  vnode->symbol.definition = false;
! 	  vnode->symbol.analyzed = false;
  	  vnode->symbol.aux = NULL;
+ 
+ 	  /* Keep body if it may be useful for constant folding.  */
+ 	  if (!const_value_known_p (vnode->symbol.decl))
+ 	    varpool_remove_initializer (vnode);
+ 	  ipa_remove_all_references (&vnode->symbol.ref_list);
  	}
        else
  	vnode->symbol.aux = NULL;
*************** ipa_discover_readonly_nonaddressable_var
*** 474,480 ****
    if (dump_file)
      fprintf (dump_file, "Clearing variable flags:");
    FOR_EACH_VARIABLE (vnode)
!     if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
  	&& (TREE_ADDRESSABLE (vnode->symbol.decl)
  	    || !TREE_READONLY (vnode->symbol.decl)))
        {
--- 471,477 ----
    if (dump_file)
      fprintf (dump_file, "Clearing variable flags:");
    FOR_EACH_VARIABLE (vnode)
!     if (vnode->symbol.definition && varpool_all_refs_explicit_p (vnode)
  	&& (TREE_ADDRESSABLE (vnode->symbol.decl)
  	    || !TREE_READONLY (vnode->symbol.decl)))
        {
*************** cgraph_address_taken_from_non_vtable_p (
*** 546,557 ****
     Virtual functions do have their addresses taken from the vtables,
     but in C++ there is no way to compare their addresses for equality.  */
  
! bool
  cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
  {
    if ((cgraph_address_taken_from_non_vtable_p (node)
         && !DECL_VIRTUAL_P (node->symbol.decl))
!       || !node->analyzed)
      return false;
    if (node->symbol.same_comdat_group)
      {
--- 543,554 ----
     Virtual functions do have their addresses taken from the vtables,
     but in C++ there is no way to compare their addresses for equality.  */
  
! static bool
  cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
  {
    if ((cgraph_address_taken_from_non_vtable_p (node)
         && !DECL_VIRTUAL_P (node->symbol.decl))
!       || !node->symbol.definition)
      return false;
    if (node->symbol.same_comdat_group)
      {
*************** static bool
*** 575,581 ****
  cgraph_externally_visible_p (struct cgraph_node *node,
  			     bool whole_program)
  {
!   if (!node->local.finalized)
      return false;
    if (!DECL_COMDAT (node->symbol.decl)
        && (!TREE_PUBLIC (node->symbol.decl)
--- 572,578 ----
  cgraph_externally_visible_p (struct cgraph_node *node,
  			     bool whole_program)
  {
!   if (!node->symbol.definition)
      return false;
    if (!DECL_COMDAT (node->symbol.decl)
        && (!TREE_PUBLIC (node->symbol.decl)
*************** cgraph_externally_visible_p (struct cgra
*** 619,625 ****
  	  || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
        /* Be sure that node is defined in IR file, not in other object
  	 file.  In that case we don't set used_from_other_object_file.  */
!       && node->analyzed)
      ;
    else if (!whole_program)
      return true;
--- 616,622 ----
  	  || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
        /* Be sure that node is defined in IR file, not in other object
  	 file.  In that case we don't set used_from_other_object_file.  */
!       && node->symbol.definition)
      ;
    else if (!whole_program)
      return true;
*************** varpool_externally_visible_p (struct var
*** 638,644 ****
    /* Do not touch weakrefs; while they are not externally visible,
       dropping their DECL_EXTERNAL flags confuse most
       of code handling them.  */
!   if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
      return true;
  
    if (DECL_EXTERNAL (vnode->symbol.decl))
--- 635,641 ----
    /* Do not touch weakrefs; while they are not externally visible,
       dropping their DECL_EXTERNAL flags confuse most
       of code handling them.  */
!   if (vnode->symbol.alias && DECL_EXTERNAL (vnode->symbol.decl))
      return true;
  
    if (DECL_EXTERNAL (vnode->symbol.decl))
*************** varpool_externally_visible_p (struct var
*** 690,696 ****
  	  || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
        /* Be sure that node is defined in IR file, not in other object
  	 file.  In that case we don't set used_from_other_object_file.  */
!       && vnode->finalized)
      ;
    else if (!flag_whole_program)
      return true;
--- 687,693 ----
  	  || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
        /* Be sure that node is defined in IR file, not in other object
  	 file.  In that case we don't set used_from_other_object_file.  */
!       && vnode->symbol.definition)
      ;
    else if (!flag_whole_program)
      return true;
*************** function_and_variable_visibility (bool w
*** 744,750 ****
  	 We may end up marking as node external nodes where this flag is meaningless
  	 strip it.  */
        if (node->symbol.force_output
! 	  && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
  	node->symbol.force_output = 0;
  
        /* C++ FE on lack of COMDAT support create local COMDAT functions
--- 741,747 ----
  	 We may end up marking as node external nodes where this flag is meaningless
  	 strip it.  */
        if (node->symbol.force_output
! 	  && (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition))
  	node->symbol.force_output = 0;
  
        /* C++ FE on lack of COMDAT support create local COMDAT functions
*************** function_and_variable_visibility (bool w
*** 781,787 ****
  	}
        else
  	node->symbol.externally_visible = false;
!       if (!node->symbol.externally_visible && node->analyzed
  	  && !DECL_EXTERNAL (node->symbol.decl))
  	{
  	  gcc_assert (whole_program || in_lto_p
--- 778,784 ----
  	}
        else
  	node->symbol.externally_visible = false;
!       if (!node->symbol.externally_visible && node->symbol.definition
  	  && !DECL_EXTERNAL (node->symbol.decl))
  	{
  	  gcc_assert (whole_program || in_lto_p
*************** function_and_variable_visibility (bool w
*** 854,860 ****
      }
    FOR_EACH_DEFINED_VARIABLE (vnode)
      {
!       if (!vnode->finalized)
          continue;
        if (varpool_externally_visible_p (vnode))
  	vnode->symbol.externally_visible = true;
--- 851,857 ----
      }
    FOR_EACH_DEFINED_VARIABLE (vnode)
      {
!       if (!vnode->symbol.definition)
          continue;
        if (varpool_externally_visible_p (vnode))
  	vnode->symbol.externally_visible = true;
Index: trans-mem.c
===================================================================
*** trans-mem.c	(revision 199343)
--- trans-mem.c	(working copy)
*************** get_cg_data (struct cgraph_node **node,
*** 3932,3938 ****
  {
    struct tm_ipa_cg_data *d;
  
!   if (traverse_aliases && (*node)->alias)
      *node = cgraph_get_node ((*node)->thunk.alias);
  
    d = (struct tm_ipa_cg_data *) (*node)->symbol.aux;
--- 3932,3938 ----
  {
    struct tm_ipa_cg_data *d;
  
!   if (traverse_aliases && (*node)->symbol.alias)
      *node = cgraph_get_node ((*node)->thunk.alias);
  
    d = (struct tm_ipa_cg_data *) (*node)->symbol.aux;
*************** ipa_tm_mayenterirr_function (struct cgra
*** 4518,4524 ****
    /* Recurse on the main body for aliases.  In general, this will
       result in one of the bits above being set so that we will not
       have to recurse next time.  */
!   if (node->alias)
      return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias));
  
    /* What remains is unmarked local functions without items that force
--- 4518,4524 ----
    /* Recurse on the main body for aliases.  In general, this will
       result in one of the bits above being set so that we will not
       have to recurse next time.  */
!   if (node->symbol.alias)
      return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias));
  
    /* What remains is unmarked local functions without items that force
*************** static inline void
*** 4678,4686 ****
  ipa_tm_mark_force_output_node (struct cgraph_node *node)
  {
    cgraph_mark_force_output_node (node);
!   /* ??? function_and_variable_visibility will reset
!      the needed bit, without actually checking.  */
!   node->analyzed = 1;
  }
  
  /* Callback data for ipa_tm_create_version_alias.  */
--- 4678,4684 ----
  ipa_tm_mark_force_output_node (struct cgraph_node *node)
  {
    cgraph_mark_force_output_node (node);
!   node->symbol.analyzed = true;
  }
  
  /* Callback data for ipa_tm_create_version_alias.  */
*************** ipa_tm_execute (void)
*** 5250,5256 ****
  	    {
  	      /* If this is an alias, make sure its base is queued as well.
  		 we need not scan the callees now, as the base will do.  */
! 	      if (node->alias)
  		{
  		  node = cgraph_get_node (node->thunk.alias);
  		  d = get_cg_data (&node, true);
--- 5248,5254 ----
  	    {
  	      /* If this is an alias, make sure its base is queued as well.
  		 we need not scan the callees now, as the base will do.  */
! 	      if (node->symbol.alias)
  		{
  		  node = cgraph_get_node (node->thunk.alias);
  		  d = get_cg_data (&node, true);
*************** ipa_tm_execute (void)
*** 5393,5399 ****
    for (i = 0; i < tm_callees.length (); ++i)
      {
        node = tm_callees[i];
!       if (node->analyzed)
  	{
  	  d = get_cg_data (&node, true);
  	  if (d->clone)
--- 5391,5397 ----
    for (i = 0; i < tm_callees.length (); ++i)
      {
        node = tm_callees[i];
!       if (node->symbol.analyzed)
  	{
  	  d = get_cg_data (&node, true);
  	  if (d->clone)
Index: ipa-inline-analysis.c
===================================================================
*** ipa-inline-analysis.c	(revision 199343)
--- ipa-inline-analysis.c	(working copy)
*************** dump_inline_edge_summary (FILE *f, int i
*** 1351,1357 ****
  void
  dump_inline_summary (FILE *f, struct cgraph_node *node)
  {
!   if (node->analyzed)
      {
        struct inline_summary *s = inline_summary (node);
        size_time_entry *e;
--- 1351,1357 ----
  void
  dump_inline_summary (FILE *f, struct cgraph_node *node)
  {
!   if (node->symbol.definition)
      {
        struct inline_summary *s = inline_summary (node);
        size_time_entry *e;
*************** initialize_inline_failed (struct cgraph_
*** 1427,1433 ****
  
    if (e->indirect_unknown_callee)
      e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
!   else if (!callee->analyzed)
      e->inline_failed = CIF_BODY_NOT_AVAILABLE;
    else if (callee->local.redefined_extern_inline)
      e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
--- 1427,1433 ----
  
    if (e->indirect_unknown_callee)
      e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
!   else if (!callee->symbol.definition)
      e->inline_failed = CIF_BODY_NOT_AVAILABLE;
    else if (callee->local.redefined_extern_inline)
      e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
*************** estimate_edge_devirt_benefit (struct cgr
*** 2765,2771 ****
    gcc_checking_assert (*size >= 0);
  
    callee = cgraph_get_node (target);
!   if (!callee || !callee->analyzed)
      return false;
    isummary = inline_summary (callee);
    return isummary->inlinable;
--- 2765,2771 ----
    gcc_checking_assert (*size >= 0);
  
    callee = cgraph_get_node (target);
!   if (!callee || !callee->symbol.definition)
      return false;
    isummary = inline_summary (callee);
    return isummary->inlinable;
*************** inline_generate_summary (void)
*** 3683,3689 ****
    inline_free_summary ();
  
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (!node->alias)
        inline_analyze_function (node);
  }
  
--- 3683,3689 ----
    inline_free_summary ();
  
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (!node->symbol.alias)
        inline_analyze_function (node);
  }
  
*************** inline_write_summary (void)
*** 3917,3923 ****
      {
        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
        cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
!       if (cnode && cnode->analyzed)
  	count++;
      }
    streamer_write_uhwi (ob, count);
--- 3917,3923 ----
      {
        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
        cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
!       if (cnode && cnode->symbol.definition && !cnode->symbol.alias)
  	count++;
      }
    streamer_write_uhwi (ob, count);
*************** inline_write_summary (void)
*** 3926,3932 ****
      {
        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
        cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
!       if (cnode && (node = cnode)->analyzed)
  	{
  	  struct inline_summary *info = inline_summary (node);
  	  struct bitpack_d bp;
--- 3926,3932 ----
      {
        symtab_node snode = lto_symtab_encoder_deref (encoder, i);
        cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
!       if (cnode && (node = cnode)->symbol.definition && !node->symbol.alias)
  	{
  	  struct inline_summary *info = inline_summary (node);
  	  struct bitpack_d bp;
Index: gimple-fold.c
===================================================================
*** gimple-fold.c	(revision 199343)
--- gimple-fold.c	(working copy)
*************** can_refer_decl_in_current_unit_p (tree d
*** 114,120 ****
           The second is important when devirtualization happens during final
           compilation stage when making a new reference no longer makes callee
           to be compiled.  */
!       if (!node || !node->analyzed || node->global.inlined_to)
  	{
  	  gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
  	  return false;
--- 114,120 ----
           The second is important when devirtualization happens during final
           compilation stage when making a new reference no longer makes callee
           to be compiled.  */
!       if (!node || !node->symbol.definition || node->global.inlined_to)
  	{
  	  gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
  	  return false;
*************** can_refer_decl_in_current_unit_p (tree d
*** 123,129 ****
    else if (TREE_CODE (decl) == VAR_DECL)
      {
        vnode = varpool_get_node (decl);
!       if (!vnode || !vnode->analyzed)
  	{
  	  gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
  	  return false;
--- 123,129 ----
    else if (TREE_CODE (decl) == VAR_DECL)
      {
        vnode = varpool_get_node (decl);
!       if (!vnode || !vnode->symbol.definition)
  	{
  	  gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
  	  return false;
Index: lto/lto.c
===================================================================
*** lto/lto.c	(revision 199343)
--- lto/lto.c	(working copy)
*************** has_analyzed_clone_p (struct cgraph_node
*** 166,172 ****
    if (node)
      while (node != orig)
        {
! 	if (node->analyzed)
  	  return true;
  	if (node->clones)
  	  node = node->clones;
--- 166,172 ----
    if (node)
      while (node != orig)
        {
! 	if (node->symbol.analyzed)
  	  return true;
  	if (node->clones)
  	  node = node->clones;
*************** lto_materialize_function (struct cgraph_
*** 196,202 ****
    decl = node->symbol.decl;
    /* Read in functions with body (analyzed nodes)
       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)
--- 196,203 ----
    decl = node->symbol.decl;
    /* Read in functions with body (analyzed nodes)
       and also functions that are needed to produce virtual clones.  */
!   if ((cgraph_function_with_gimple_body_p (node) && node->symbol.analyzed)
!       || has_analyzed_clone_p (node))
      {
        /* Clones don't need to be read.  */
        if (node->clone_of)
Index: lto/lto-partition.c
===================================================================
*** lto/lto-partition.c	(revision 199343)
--- lto/lto-partition.c	(working copy)
*************** get_symbol_class (symtab_node node)
*** 74,86 ****
           objects that can not be duplicated across partitions.  */
        if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
  	return SYMBOL_DUPLICATE;
!       gcc_checking_assert (vnode->analyzed);
      }
    /* Functions that are cloned may stay in callgraph even if they are unused.
       Handle them as external; compute_ltrans_boundary take care to make
       proper things to happen (i.e. to make them appear in the boundary but
       with body streamed, so clone can me materialized).  */
!   else if (!cgraph (node)->analyzed)
      return SYMBOL_EXTERNAL;
  
    /* Comdats are duplicated to every use unless they are keyed.
--- 74,86 ----
           objects that can not be duplicated across partitions.  */
        if (DECL_IN_CONSTANT_POOL (node->symbol.decl))
  	return SYMBOL_DUPLICATE;
!       gcc_checking_assert (vnode->symbol.definition);
      }
    /* Functions that are cloned may stay in callgraph even if they are unused.
       Handle them as external; compute_ltrans_boundary take care to make
       proper things to happen (i.e. to make them appear in the boundary but
       with body streamed, so clone can me materialized).  */
!   else if (!cgraph (node)->symbol.definition)
      return SYMBOL_EXTERNAL;
  
    /* Comdats are duplicated to every use unless they are keyed.
*************** lto_balanced_map (void)
*** 561,572 ****
  
  	      last_visited_node++;
  
! 	      gcc_assert (node->analyzed
  			  || lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)));
  
  	      /* Compute boundary cost of callgraph edges.  */
  	      for (edge = node->callees; edge; edge = edge->next_callee)
! 		if (edge->callee->analyzed)
  		  {
  		    int edge_cost = edge->frequency;
  		    int index;
--- 561,572 ----
  
  	      last_visited_node++;
  
! 	      gcc_assert (node->symbol.definition
  			  || lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl)));
  
  	      /* Compute boundary cost of callgraph edges.  */
  	      for (edge = node->callees; edge; edge = edge->next_callee)
! 		if (edge->callee->symbol.definition)
  		  {
  		    int edge_cost = edge->frequency;
  		    int index;
*************** lto_balanced_map (void)
*** 587,593 ****
  		  int edge_cost = edge->frequency;
  		  int index;
  
! 		  gcc_assert (edge->caller->analyzed);
  		  if (!edge_cost)
  		    edge_cost = 1;
  		  gcc_assert (edge_cost > 0);
--- 587,593 ----
  		  int edge_cost = edge->frequency;
  		  int index;
  
! 		  gcc_assert (edge->caller->symbol.definition);
  		  if (!edge_cost)
  		    edge_cost = 1;
  		  gcc_assert (edge_cost > 0);
*************** lto_balanced_map (void)
*** 614,620 ****
  		int index;
  
  		vnode = ipa_ref_varpool_node (ref);
! 		if (!vnode->finalized)
  		  continue;
  		if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
  		    && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
--- 614,620 ----
  		int index;
  
  		vnode = ipa_ref_varpool_node (ref);
! 		if (!vnode->symbol.definition)
  		  continue;
  		if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
  		    && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
*************** lto_balanced_map (void)
*** 632,638 ****
  		int index;
  
  		node = ipa_ref_node (ref);
! 		if (!node->analyzed)
  		  continue;
  		index = lto_symtab_encoder_lookup (partition->encoder,
  						   (symtab_node)node);
--- 632,638 ----
  		int index;
  
  		node = ipa_ref_node (ref);
! 		if (!node->symbol.definition)
  		  continue;
  		index = lto_symtab_encoder_lookup (partition->encoder,
  						   (symtab_node)node);
*************** lto_balanced_map (void)
*** 648,654 ****
  		int index;
  
  		vnode = ipa_ref_referring_varpool_node (ref);
! 		gcc_assert (vnode->finalized);
  		if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
  		    && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
  		  add_symbol_to_partition (partition, (symtab_node) vnode);
--- 648,654 ----
  		int index;
  
  		vnode = ipa_ref_referring_varpool_node (ref);
! 		gcc_assert (vnode->symbol.definition);
  		if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder
  		    && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION)
  		  add_symbol_to_partition (partition, (symtab_node) vnode);
*************** lto_balanced_map (void)
*** 665,671 ****
  		int index;
  
  		node = ipa_ref_referring_node (ref);
! 		gcc_assert (node->analyzed);
  		index = lto_symtab_encoder_lookup (partition->encoder,
  						   (symtab_node)node);
  		if (index != LCC_NOT_FOUND
--- 665,671 ----
  		int index;
  
  		node = ipa_ref_referring_node (ref);
! 		gcc_assert (node->symbol.definition);
  		index = lto_symtab_encoder_lookup (partition->encoder,
  						   (symtab_node)node);
  		if (index != LCC_NOT_FOUND
Index: ipa-prop.c
===================================================================
*** ipa-prop.c	(revision 199343)
--- ipa-prop.c	(working copy)
*************** ipa_compute_jump_functions (struct cgrap
*** 1521,1527 ****
  								  NULL);
        /* We do not need to bother analyzing calls to unknown
  	 functions unless they may become known during lto/whopr.  */
!       if (!callee->analyzed && !flag_lto)
  	continue;
        ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
      }
--- 1521,1527 ----
  								  NULL);
        /* We do not need to bother analyzing calls to unknown
  	 functions unless they may become known during lto/whopr.  */
!       if (!callee->symbol.definition && !flag_lto)
  	continue;
        ipa_compute_jump_functions_for_edge (parms_ainfo, cs);
      }
*************** ipa_print_node_params (FILE *f, struct c
*** 2978,2984 ****
    tree temp;
    struct ipa_node_params *info;
  
!   if (!node->analyzed)
      return;
    info = IPA_NODE_REF (node);
    fprintf (f, "  function  %s/%i parameter descriptors:\n",
--- 2978,2984 ----
    tree temp;
    struct ipa_node_params *info;
  
!   if (!node->symbol.definition)
      return;
    info = IPA_NODE_REF (node);
    fprintf (f, "  function  %s/%i parameter descriptors:\n",
*************** ipa_prop_read_section (struct lto_file_d
*** 3972,3978 ****
        index = streamer_read_uhwi (&ib_main);
        encoder = file_data->symtab_node_encoder;
        node = cgraph (lto_symtab_encoder_deref (encoder, index));
!       gcc_assert (node->analyzed);
        ipa_read_node_info (&ib_main, node, data_in);
      }
    lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
--- 3972,3978 ----
        index = streamer_read_uhwi (&ib_main);
        encoder = file_data->symtab_node_encoder;
        node = cgraph (lto_symtab_encoder_deref (encoder, index));
!       gcc_assert (node->symbol.definition);
        ipa_read_node_info (&ib_main, node, data_in);
      }
    lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
*************** ipa_update_after_lto_read (void)
*** 4016,4023 ****
    ipa_check_create_edge_args ();
  
    FOR_EACH_DEFINED_FUNCTION (node)
!     if (node->analyzed)
!       ipa_initialize_node_params (node);
  }
  
  void
--- 4016,4022 ----
    ipa_check_create_edge_args ();
  
    FOR_EACH_DEFINED_FUNCTION (node)
!     ipa_initialize_node_params (node);
  }
  
  void
*************** read_replacements_section (struct lto_fi
*** 4154,4160 ****
        index = streamer_read_uhwi (&ib_main);
        encoder = file_data->symtab_node_encoder;
        node = cgraph (lto_symtab_encoder_deref (encoder, index));
!       gcc_assert (node->analyzed);
        read_agg_replacement_chain (&ib_main, node, data_in);
      }
    lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
--- 4153,4159 ----
        index = streamer_read_uhwi (&ib_main);
        encoder = file_data->symtab_node_encoder;
        node = cgraph (lto_symtab_encoder_deref (encoder, index));
!       gcc_assert (node->symbol.definition);
        read_agg_replacement_chain (&ib_main, node, data_in);
      }
    lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
Index: varasm.c
===================================================================
*** varasm.c	(revision 199343)
--- varasm.c	(working copy)
*************** mark_decl_referenced (tree decl)
*** 2256,2262 ****
  	 definition.  */
        struct cgraph_node *node = cgraph_get_create_node (decl);
        if (!DECL_EXTERNAL (decl)
! 	  && !node->local.finalized)
  	cgraph_mark_force_output_node (node);
      }
    else if (TREE_CODE (decl) == VAR_DECL)
--- 2256,2262 ----
  	 definition.  */
        struct cgraph_node *node = cgraph_get_create_node (decl);
        if (!DECL_EXTERNAL (decl)
! 	  && !node->symbol.definition)
  	cgraph_mark_force_output_node (node);
      }
    else if (TREE_CODE (decl) == VAR_DECL)
*************** assemble_alias (tree decl, tree target)
*** 5595,5603 ****
  
    /* Allow aliases to aliases.  */
    if (TREE_CODE (decl) == FUNCTION_DECL)
!     cgraph_get_create_node (decl)->alias = true;
    else
!     varpool_node_for_decl (decl)->alias = true;
  
    /* If the target has already been emitted, we don't have to queue the
       alias.  This saves a tad of memory.  */
--- 5595,5603 ----
  
    /* Allow aliases to aliases.  */
    if (TREE_CODE (decl) == FUNCTION_DECL)
!     cgraph_get_create_node (decl)->symbol.alias = true;
    else
!     varpool_node_for_decl (decl)->symbol.alias = true;
  
    /* If the target has already been emitted, we don't have to queue the
       alias.  This saves a tad of memory.  */
*************** dump_tm_clone_pairs (vec<tm_alias_pair>
*** 5700,5711 ****
  	 TM_GETTMCLONE.  If neither of these are true, we didn't generate
  	 a clone, and we didn't call it indirectly... no sense keeping it
  	 in the clone table.  */
!       if (!dst_n || !dst_n->analyzed)
  	continue;
  
        /* This covers the case where we have optimized the original
  	 function away, and only access the transactional clone.  */
!       if (!src_n || !src_n->analyzed)
  	continue;
  
        if (!switched)
--- 5700,5711 ----
  	 TM_GETTMCLONE.  If neither of these are true, we didn't generate
  	 a clone, and we didn't call it indirectly... no sense keeping it
  	 in the clone table.  */
!       if (!dst_n || !dst_n->symbol.definition)
  	continue;
  
        /* This covers the case where we have optimized the original
  	 function away, and only access the transactional clone.  */
!       if (!src_n || !src_n->symbol.definition)
  	continue;
  
        if (!switched)
Index: tree-inline.c
===================================================================
*** tree-inline.c	(revision 199343)
--- tree-inline.c	(working copy)
*************** copy_bb (copy_body_data *id, basic_block
*** 1726,1732 ****
  	      if ((!edge
  		   || (edge->indirect_inlining_edge
  		       && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
! 		  && id->dst_node->analyzed
  		  && (fn = gimple_call_fndecl (stmt)) != NULL)
  		{
  		  struct cgraph_node *dest = cgraph_get_node (fn);
--- 1726,1732 ----
  	      if ((!edge
  		   || (edge->indirect_inlining_edge
  		       && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
! 		  && id->dst_node->symbol.definition
  		  && (fn = gimple_call_fndecl (stmt)) != NULL)
  		{
  		  struct cgraph_node *dest = cgraph_get_node (fn);
*************** copy_bb (copy_body_data *id, basic_block
*** 1737,1746 ****
  		     producing dead clone (for further cloning).  In all
  		     other cases we hit a bug (incorrect node sharing is the
  		     most common reason for missing edges).  */
! 		  gcc_assert (!dest->analyzed
  			      || dest->symbol.address_taken
! 		  	      || !id->src_node->analyzed
! 			      || !id->dst_node->analyzed);
  		  if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
  		    cgraph_create_edge_including_clones
  		      (id->dst_node, dest, orig_stmt, stmt, bb->count,
--- 1737,1746 ----
  		     producing dead clone (for further cloning).  In all
  		     other cases we hit a bug (incorrect node sharing is the
  		     most common reason for missing edges).  */
! 		  gcc_assert (!dest->symbol.definition
  			      || dest->symbol.address_taken
! 		  	      || !id->src_node->symbol.definition
! 			      || !id->dst_node->symbol.definition);
  		  if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)
  		    cgraph_create_edge_including_clones
  		      (id->dst_node, dest, orig_stmt, stmt, bb->count,
*************** estimate_num_insns (gimple stmt, eni_wei
*** 3611,3617 ****
  
  	/* Do not special case builtins where we see the body.
  	   This just confuse inliner.  */
! 	if (!decl || !(node = cgraph_get_node (decl)) || node->analyzed)
  	  ;
  	/* For buitins that are likely expanded to nothing or
  	   inlined do not account operand costs.  */
--- 3611,3617 ----
  
  	/* Do not special case builtins where we see the body.
  	   This just confuse inliner.  */
! 	if (!decl || !(node = cgraph_get_node (decl)) || node->symbol.definition)
  	  ;
  	/* For buitins that are likely expanded to nothing or
  	   inlined do not account operand costs.  */
*************** optimize_inline_calls (tree fn)
*** 4344,4350 ****
    memset (&id, 0, sizeof (id));
  
    id.src_node = id.dst_node = cgraph_get_node (fn);
!   gcc_assert (id.dst_node->analyzed);
    id.dst_fn = fn;
    /* Or any functions that aren't finished yet.  */
    if (current_function_decl)
--- 4344,4350 ----
    memset (&id, 0, sizeof (id));
  
    id.src_node = id.dst_node = cgraph_get_node (fn);
!   gcc_assert (id.dst_node->symbol.definition);
    id.dst_fn = fn;
    /* Or any functions that aren't finished yet.  */
    if (current_function_decl)
*************** tree_function_versioning (tree old_decl,
*** 5238,5244 ****
    pointer_set_destroy (id.statements_to_fold);
    fold_cond_expr_cond ();
    delete_unreachable_blocks_update_callgraph (&id);
!   if (id.dst_node->analyzed)
      cgraph_rebuild_references ();
    update_ssa (TODO_update_ssa);
  
--- 5238,5244 ----
    pointer_set_destroy (id.statements_to_fold);
    fold_cond_expr_cond ();
    delete_unreachable_blocks_update_callgraph (&id);
!   if (id.dst_node->symbol.definition)
      cgraph_rebuild_references ();
    update_ssa (TODO_update_ssa);
  
Index: symtab.c
===================================================================
*** symtab.c	(revision 199343)
--- symtab.c	(working copy)
*************** dump_symtab_base (FILE *f, symtab_node n
*** 473,481 ****
  	   node->symbol.order,
  	   symtab_node_name (node));
    dump_addr (f, " @", (void *)node);
!   fprintf (f, "\n  Type: %s\n", symtab_type_names[node->symbol.type]);
!   fprintf (f, "  Visibility:");
  
    if (node->symbol.in_other_partition)
      fprintf (f, " in_other_partition");
    if (node->symbol.used_from_other_partition)
--- 473,487 ----
  	   node->symbol.order,
  	   symtab_node_name (node));
    dump_addr (f, " @", (void *)node);
!   fprintf (f, "\n  Type: %s", symtab_type_names[node->symbol.type]);
  
+   if (node->symbol.definition)
+     fprintf (f, " definition");
+   if (node->symbol.analyzed)
+     fprintf (f, " analyzed");
+   if (node->symbol.alias)
+     fprintf (f, " alias");
+   fprintf (f, "\n  Visibility:");
    if (node->symbol.in_other_partition)
      fprintf (f, " in_other_partition");
    if (node->symbol.used_from_other_partition)
*************** verify_symtab_base (symtab_node node)
*** 653,658 ****
--- 659,670 ----
        && node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node)
      {
        error ("double linked list of assembler names corrupted");
+       error_found = true;
+     }
+   if (node->symbol.analyzed && !node->symbol.definition)
+     {
+       error ("node is analyzed byt it is not a definition");
+       error_found = true;
      }
    if (node->symbol.same_comdat_group)
      {
*************** symtab_make_decl_local (tree decl)
*** 783,786 ****
--- 795,834 ----
  
    SYMBOL_REF_WEAK (symbol) = DECL_WEAK (decl);
  }
+ 
+ /* Given NODE, walk the alias chain to return the symbol NODE is alias of.
+    If NODE is not an alias, return NODE.
+    When AVAILABILITY is non-NULL, get minimal availability in the chain.  */
+ 
+ symtab_node
+ symtab_alias_ultimate_target (symtab_node node, enum availability *availability)
+ {
+   if (availability)
+     {
+       if (is_a <cgraph_node> (node))
+         *availability = cgraph_function_body_availability (cgraph (node));
+       else
+         *availability = cgraph_variable_initializer_availability (varpool (node));
+     }
+   while (node)
+     {
+       if (node->symbol.alias && node->symbol.analyzed)
+ 	node = symtab_alias_target (node);
+       else
+ 	return node;
+       if (node && availability)
+ 	{
+ 	  enum availability a;
+ 	  if (is_a <cgraph_node> (node))
+ 	    a = cgraph_function_body_availability (cgraph (node));
+ 	  else
+ 	    a = cgraph_variable_initializer_availability (varpool (node));
+ 	  if (a < *availability)
+ 	    *availability = a;
+ 	}
+     }
+   if (availability)
+     *availability = AVAIL_NOT_AVAILABLE;
+   return NULL;
+ }
  #include "gt-symtab.h"
Index: tree-ssa-structalias.c
===================================================================
*** tree-ssa-structalias.c	(revision 199343)
--- tree-ssa-structalias.c	(working copy)
*************** get_constraint_for_ssa_var (tree t, vec<
*** 2874,2880 ****
        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
      {
        struct varpool_node *node = varpool_get_node (t);
!       if (node && node->alias)
  	{
  	  node = varpool_variable_node (node, NULL);
  	  t = node->symbol.decl;
--- 2874,2880 ----
        && (TREE_STATIC (t) || DECL_EXTERNAL (t)))
      {
        struct varpool_node *node = varpool_get_node (t);
!       if (node && node->symbol.alias && node->symbol.analyzed)
  	{
  	  node = varpool_variable_node (node, NULL);
  	  t = node->symbol.decl;
*************** create_variable_info_for (tree decl, con
*** 5751,5757 ****
  	  /* If this is a global variable with an initializer and we are in
  	     IPA mode generate constraints for it.  */
  	  if (DECL_INITIAL (decl)
! 	      && vnode->analyzed)
  	    {
  	      vec<ce_s> rhsc = vNULL;
  	      struct constraint_expr lhs, *rhsp;
--- 5751,5757 ----
  	  /* If this is a global variable with an initializer and we are in
  	     IPA mode generate constraints for it.  */
  	  if (DECL_INITIAL (decl)
! 	      && vnode->symbol.definition)
  	    {
  	      vec<ce_s> rhsc = vNULL;
  	      struct constraint_expr lhs, *rhsp;
*************** struct pt_solution ipa_escaped_pt
*** 7023,7029 ****
  static bool
  associate_varinfo_to_alias (struct cgraph_node *node, void *data)
  {
!   if (node->alias || node->thunk.thunk_p)
      insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
    return false;
  }
--- 7023,7030 ----
  static bool
  associate_varinfo_to_alias (struct cgraph_node *node, void *data)
  {
!   if ((node->symbol.alias || node->thunk.thunk_p)
!       && node->symbol.analyzed)
      insert_vi_for_tree (node->symbol.decl, (varinfo_t)data);
    return false;
  }
*************** ipa_pta_execute (void)
*** 7066,7072 ****
    /* Create constraints for global variables and their initializers.  */
    FOR_EACH_VARIABLE (var)
      {
!       if (var->alias)
  	continue;
  
        get_vi_for_tree (var->symbol.decl);
--- 7067,7073 ----
    /* Create constraints for global variables and their initializers.  */
    FOR_EACH_VARIABLE (var)
      {
!       if (var->symbol.alias && var->symbol.analyzed)
  	continue;
  
        get_vi_for_tree (var->symbol.decl);
Index: passes.c
===================================================================
*** passes.c	(revision 199343)
--- passes.c	(working copy)
*************** ipa_write_summaries (void)
*** 2492,2503 ****
  	  renumber_gimple_stmt_uids ();
  	  pop_cfun ();
  	}
!       if (node->analyzed)
          lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
      }
  
    FOR_EACH_DEFINED_VARIABLE (vnode)
!     if ((!vnode->alias || vnode->alias_of))
        lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
  
    ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
--- 2492,2503 ----
  	  renumber_gimple_stmt_uids ();
  	  pop_cfun ();
  	}
!       if (node->symbol.definition)
          lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
      }
  
    FOR_EACH_DEFINED_VARIABLE (vnode)
!     if ((!vnode->symbol.alias || vnode->alias_of))
        lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
  
    ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
*************** ipa_write_optimization_summaries (lto_sy
*** 2564,2570 ****
  
  	 For functions newly born at WPA stage we need to initialize
  	 the uids here.  */
!       if (node->analyzed
  	  && gimple_has_body_p (node->symbol.decl))
  	{
  	  push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
--- 2564,2570 ----
  
  	 For functions newly born at WPA stage we need to initialize
  	 the uids here.  */
!       if (node->symbol.definition
  	  && gimple_has_body_p (node->symbol.decl))
  	{
  	  push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
Index: config/i386/i386.c
===================================================================
*** config/i386/i386.c	(revision 199343)
--- config/i386/i386.c	(working copy)
*************** ix86_get_function_versions_dispatcher (v
*** 29468,29474 ****
        dispatcher_version_info
  	= insert_new_cgraph_node_version (dispatcher_node);
        dispatcher_version_info->next = default_version_info;
!       dispatcher_node->local.finalized = 1;
  
        /* Set the dispatcher for all the versions.  */
        it_v = default_version_info;
--- 29468,29474 ----
        dispatcher_version_info
  	= insert_new_cgraph_node_version (dispatcher_node);
        dispatcher_version_info->next = default_version_info;
!       dispatcher_node->symbol.definition = 1;
  
        /* Set the dispatcher for all the versions.  */
        it_v = default_version_info;
*************** ix86_generate_version_dispatcher_body (v
*** 29623,29629 ****
    default_ver_decl = node_version_info->next->this_node->symbol.decl;
  
    /* node is going to be an alias, so remove the finalized bit.  */
!   node->local.finalized = false;
  
    resolver_decl = make_resolver_func (default_ver_decl,
  				      node->symbol.decl, &empty_bb);
--- 29623,29629 ----
    default_ver_decl = node_version_info->next->this_node->symbol.decl;
  
    /* node is going to be an alias, so remove the finalized bit.  */
!   node->symbol.definition = false;
  
    resolver_decl = make_resolver_func (default_ver_decl,
  				      node->symbol.decl, &empty_bb);
*************** fold_builtin_cpu (tree fndecl, tree *arg
*** 29817,29822 ****
--- 29817,29825 ----
    tree __cpu_model_var = make_var_decl (__processor_model_type,
  					"__cpu_model");
  
+ 
+   varpool_add_new_variable (__cpu_model_var);
+ 
    gcc_assert ((args != NULL) && (*args != NULL));
  
    param_string_cst = *args;
Index: varpool.c
===================================================================
*** varpool.c	(revision 199343)
--- varpool.c	(working copy)
*************** void
*** 58,63 ****
--- 58,76 ----
  varpool_remove_node (struct varpool_node *node)
  {
    symtab_unregister_node ((symtab_node)node);
+ 
+   /* Because we remove references from external functions before final compilation,
+      we may end up removing useful constructors.
+      FIXME: We probably want to trace boundaries better.  */
+   if (!const_value_known_p (node->symbol.decl))
+     varpool_remove_initializer (node);
+   ggc_free (node);
+ }
+ 
+ /* Renove node initializer when it is no longer needed.  */
+ void
+ varpool_remove_initializer (struct varpool_node *node)
+ {
    if (DECL_INITIAL (node->symbol.decl)
        && !DECL_IN_CONSTANT_POOL (node->symbol.decl)
        /* Keep vtables for BINFO folding.  */
*************** varpool_remove_node (struct varpool_node
*** 65,71 ****
        /* FIXME: http://gcc.gnu.org/PR55395 */
        && debug_info_level == DINFO_LEVEL_NONE)
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
-   ggc_free (node);
  }
  
  /* Dump given cgraph node.  */
--- 78,83 ----
*************** dump_varpool_node (FILE *f, struct varpo
*** 80,89 ****
    fprintf (f, "  Varpool flags:");
    if (DECL_INITIAL (node->symbol.decl))
      fprintf (f, " initialized");
-   if (node->analyzed)
-     fprintf (f, " analyzed");
-   if (node->finalized)
-     fprintf (f, " finalized");
    if (node->output)
      fprintf (f, " output");
    if (TREE_READONLY (node->symbol.decl))
--- 92,97 ----
*************** struct varpool_node *
*** 117,125 ****
  varpool_node_for_asm (tree asmname)
  {
    if (symtab_node node = symtab_node_for_asm (asmname))
!     if (varpool_node *vnode = dyn_cast <varpool_node> (node))
!       return vnode;
!   return NULL;
  }
  
  /* Determine if variable DECL is needed.  That is, visible to something
--- 125,133 ----
  varpool_node_for_asm (tree asmname)
  {
    if (symtab_node node = symtab_node_for_asm (asmname))
!     return dyn_cast <varpool_node> (node);
!   else
!     return NULL;
  }
  
  /* Determine if variable DECL is needed.  That is, visible to something
*************** enum availability
*** 205,216 ****
  cgraph_variable_initializer_availability (struct varpool_node *node)
  {
    gcc_assert (cgraph_function_flags_ready);
!   if (!node->finalized)
      return AVAIL_NOT_AVAILABLE;
    if (!TREE_PUBLIC (node->symbol.decl))
      return AVAIL_AVAILABLE;
    /* If the variable can be overwritten, return OVERWRITABLE.  Takes
!      care of at least two notable extensions - the COMDAT variables
       used to share template instantiations in C++.  */
    if (!decl_replaceable_p (node->symbol.decl))
      return AVAIL_OVERWRITABLE;
--- 213,224 ----
  cgraph_variable_initializer_availability (struct varpool_node *node)
  {
    gcc_assert (cgraph_function_flags_ready);
!   if (!node->symbol.definition)
      return AVAIL_NOT_AVAILABLE;
    if (!TREE_PUBLIC (node->symbol.decl))
      return AVAIL_AVAILABLE;
    /* If the variable can be overwritten, return OVERWRITABLE.  Takes
!      care of at least one notable extension - the COMDAT variables
       used to share template instantiations in C++.  */
    if (!decl_replaceable_p (node->symbol.decl))
      return AVAIL_OVERWRITABLE;
*************** varpool_analyze_node (struct varpool_nod
*** 225,248 ****
    /* When reading back varpool at LTO time, we re-construct the queue in order
       to have "needed" list right by inserting all needed nodes into varpool.
       We however don't want to re-analyze already analyzed nodes.  */
!   if (!node->analyzed)
      {
        gcc_assert (!in_lto_p || cgraph_function_flags_ready);
        /* Compute the alignment early so function body expanders are
  	 already informed about increased alignment.  */
        align_variable (decl, 0);
      }
!   if (node->alias && node->alias_of)
      {
        struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
        struct varpool_node *n;
  
!       for (n = tgt; n && n->alias;
! 	   n = n->analyzed ? varpool_alias_aliased_node (n) : NULL)
  	if (n == node)
  	  {
  	    error ("variable %q+D part of alias cycle", node->symbol.decl);
! 	    node->alias = false;
  	    continue;
  	  }
        if (!vec_safe_length (node->symbol.ref_list.references))
--- 233,256 ----
    /* When reading back varpool at LTO time, we re-construct the queue in order
       to have "needed" list right by inserting all needed nodes into varpool.
       We however don't want to re-analyze already analyzed nodes.  */
!   if (!node->symbol.analyzed)
      {
        gcc_assert (!in_lto_p || cgraph_function_flags_ready);
        /* Compute the alignment early so function body expanders are
  	 already informed about increased alignment.  */
        align_variable (decl, 0);
      }
!   if (node->symbol.alias && node->alias_of)
      {
        struct varpool_node *tgt = varpool_node_for_decl (node->alias_of);
        struct varpool_node *n;
  
!       for (n = tgt; n && n->symbol.alias;
! 	   n = n->symbol.analyzed ? varpool_alias_target (n) : NULL)
  	if (n == node)
  	  {
  	    error ("variable %q+D part of alias cycle", node->symbol.decl);
! 	    node->symbol.alias = false;
  	    continue;
  	  }
        if (!vec_safe_length (node->symbol.ref_list.references))
*************** varpool_analyze_node (struct varpool_nod
*** 257,264 ****
  	}
      }
    else if (DECL_INITIAL (decl))
!     record_references_in_initializer (decl, node->analyzed);
!   node->analyzed = true;
  }
  
  /* Assemble thunks and aliases associated to NODE.  */
--- 265,272 ----
  	}
      }
    else if (DECL_INITIAL (decl))
!     record_references_in_initializer (decl, node->symbol.analyzed);
!   node->symbol.analyzed = true;
  }
  
  /* Assemble thunks and aliases associated to NODE.  */
*************** varpool_assemble_decl (struct varpool_no
*** 287,293 ****
  
    /* Aliases are outout when their target is produced or by
       output_weakrefs.  */
!   if (node->alias)
      return false;
  
    /* Constant pool is output from RTL land when the reference
--- 295,301 ----
  
    /* Aliases are outout when their target is produced or by
       output_weakrefs.  */
!   if (node->symbol.alias)
      return false;
  
    /* Constant pool is output from RTL land when the reference
*************** varpool_assemble_decl (struct varpool_no
*** 316,322 ****
      {
        assemble_variable (decl, 0, 1, 0);
        gcc_assert (TREE_ASM_WRITTEN (decl));
!       node->finalized = 1;
        assemble_aliases (node);
        return true;
      }
--- 324,330 ----
      {
        assemble_variable (decl, 0, 1, 0);
        gcc_assert (TREE_ASM_WRITTEN (decl));
!       node->symbol.definition = true;
        assemble_aliases (node);
        return true;
      }
*************** varpool_remove_unreferenced_decls (void)
*** 357,363 ****
      fprintf (cgraph_dump_file, "Trivially needed variables:");
    FOR_EACH_DEFINED_VARIABLE (node)
      {
!       if (node->analyzed
  	  && (!varpool_can_remove_if_no_refs (node)
  	      /* We just expanded all function bodies.  See if any of
  		 them needed the variable.  */
--- 365,371 ----
      fprintf (cgraph_dump_file, "Trivially needed variables:");
    FOR_EACH_DEFINED_VARIABLE (node)
      {
!       if (node->symbol.analyzed
  	  && (!varpool_can_remove_if_no_refs (node)
  	      /* We just expanded all function bodies.  See if any of
  		 them needed the variable.  */
*************** varpool_remove_unreferenced_decls (void)
*** 381,387 ****
  	       next = next->symbol.same_comdat_group)
  	    {
  	      varpool_node *vnext = dyn_cast <varpool_node> (next);
! 	      if (vnext && vnext->analyzed)
  		enqueue_node (vnext, &first);
  	    }
  	}
--- 389,395 ----
  	       next = next->symbol.same_comdat_group)
  	    {
  	      varpool_node *vnext = dyn_cast <varpool_node> (next);
! 	      if (vnext && vnext->symbol.analyzed)
  		enqueue_node (vnext, &first);
  	    }
  	}
*************** varpool_remove_unreferenced_decls (void)
*** 390,397 ****
  	  varpool_node *vnode = dyn_cast <varpool_node> (ref->referred);
  	  if (vnode
  	      && (!DECL_EXTERNAL (ref->referred->symbol.decl)
! 		  || vnode->alias)
! 	      && vnode->analyzed)
  	    enqueue_node (vnode, &first);
  	}
      }
--- 398,405 ----
  	  varpool_node *vnode = dyn_cast <varpool_node> (ref->referred);
  	  if (vnode
  	      && (!DECL_EXTERNAL (ref->referred->symbol.decl)
! 		  || vnode->symbol.alias)
! 	      && vnode->symbol.analyzed)
  	    enqueue_node (vnode, &first);
  	}
      }
*************** void
*** 419,425 ****
  varpool_finalize_named_section_flags (struct varpool_node *node)
  {
    if (!TREE_ASM_WRITTEN (node->symbol.decl)
!       && !node->alias
        && !node->symbol.in_other_partition
        && !DECL_EXTERNAL (node->symbol.decl)
        && TREE_CODE (node->symbol.decl) == VAR_DECL
--- 427,433 ----
  varpool_finalize_named_section_flags (struct varpool_node *node)
  {
    if (!TREE_ASM_WRITTEN (node->symbol.decl)
!       && !node->symbol.alias
        && !node->symbol.in_other_partition
        && !DECL_EXTERNAL (node->symbol.decl)
        && TREE_CODE (node->symbol.decl) == VAR_DECL
*************** varpool_create_variable_alias (tree alia
*** 484,491 ****
    gcc_assert (TREE_CODE (decl) == VAR_DECL);
    gcc_assert (TREE_CODE (alias) == VAR_DECL);
    alias_node = varpool_node_for_decl (alias);
!   alias_node->alias = 1;
!   alias_node->finalized = 1;
    alias_node->alias_of = decl;
  
    /* Extra name alias mechanizm creates aliases really late
--- 492,499 ----
    gcc_assert (TREE_CODE (decl) == VAR_DECL);
    gcc_assert (TREE_CODE (alias) == VAR_DECL);
    alias_node = varpool_node_for_decl (alias);
!   alias_node->symbol.alias = true;
!   alias_node->symbol.definition = true;
    alias_node->alias_of = decl;
  
    /* Extra name alias mechanizm creates aliases really late


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