diff mbox

Chromium: LTO

Message ID 20150214184440.GC20469@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Feb. 14, 2015, 6:44 p.m. UTC
Hi,
Maritn has notced that we spend a lot of time in simple cgraph/varpool predicates. The patch bellow
reorganizes inlines so the fast paths get fast.
> perf report:
>
>     18.79%         lto1-wpa  lto1                 [.] do_estimate_growth_1(cgraph_node*, void*)
>     12.48%         lto1-wpa  lto1                 [.] cgraph_node::can_remove_if_no_direct_calls_and_refs_p()
>      5.86%         lto1-wpa  lto1                 [.] symtab_node::used_from_object_file_p_worker(symtab_node*)
>      5.69%         lto1-wpa  lto1                 [.] cgraph_node::call_for_symbol_and_aliases(bool (*)(cgraph_node*, void*), void*, bool)
>      5.01%  lto1-wpa-stream  lto1                 [.] streamer_tree_cache_lookup(streamer_tree_cache_d*, tree_node*, unsigned int*)
>      4.84%         lto1-wpa  lto1                 [.] cgraph_node::call_for_symbol_thunks_and_aliases(bool (*)(cgraph_node*, void*), void*, bool, bool)
>      2.44%         lto1-wpa  lto1                 [.] inflate_fast
>      2.10%  lto1-wpa-stream  lto1                 [.] DFS::DFS_write_tree(output_block*, DFS::sccs*, tree_node*, bool, bool, bool)
>      2.03%  lto1-wpa-stream  lto1                 [.] linemap_lookup(line_maps*, unsigned int)
>      1.30%  lto1-wpa-stream  [kernel.kallsyms]    [k] isolate_migratepages_range
>      1.27%         lto1-wpa  lto1                 [.] symtab_node::iterate_direct_aliases(unsigned int, ipa_ref*&)
>      1.21%  lto1-wpa-stream  lto1                 [.] DFS::DFS_write_tree_body(output_block*, tree_node*, DFS::sccs*, bool, bool)
>      1.19%  lto1-wpa-stream  lto1                 [.] streamer_write_uhwi_stream(lto_output_stream*, unsigned long)
>      0.85%         lto1-wpa  lto1                 [.] compare_tree_sccs_1(tree_node*, tree_node*, tree_node***)
>      0.83%         lto1-wpa  lto1                 [.] streamer_read_uhwi(lto_input_block*)
>      0.74%  lto1-wpa-stream  lto1                 [.] streamer_tree_cache_insert_1(streamer_tree_cache_d*, tree_node*, unsigned int, unsigned int*, bool)
>      0.72%         lto1-wpa  lto1                 [.] ht_lookup_with_hash(ht*, unsigned char const*, unsigned long, unsigned int, ht_lookup_option)
>      0.70%  lto1-wpa-stream  [kernel.kallsyms]    [k] compaction_alloc
>      0.68%         lto1-wpa  lto1                 [.] unify_scc(streamer_tree_cache_d*, unsigned int, unsigned int, unsigned int, unsigned int)
>      0.66%  lto1-wpa-stream  lto1                 [.] lto_output_tree(output_block*, tree_node*, bool, bool)
>      0.66%  lto1-wpa-stream  libc-2.19.so         [.] _int_malloc
>      0.66%  lto1-wpa-stream  lto1                 [.] hash_table<hash_map<tree_node*, unsigned int, default_hashmap_traits>::hash_entry, xcallocator, true>::expand()
>      0.62%  lto1-wpa-stream  lto1                 [.] streamer_write_tree_bitfields(output_block*, tree_node*)
>      0.61%         lto1-wpa  lto1                 [.] streamer_read_tree_bitfields(lto_input_block*, data_in*, tree_node*)
>      0.53%         lto1-wpa  lto1                 [.] lto_cgraph_replace_node(cgraph_node*, cgraph_node*)
>      0.49%         lto1-wpa  [kernel.kallsyms]    [k] copy_pte_range

Bootstrapped/regtested x86_64-linux, comitted.

Honza

	* ipa-chkp.c: Use iterate_direct_aliases.
	* symtab.c (resolution_used_from_other_file_p): Move inline.
	(symtab_node::create_reference): Fix formating.
	(symtab_node::has_aliases_p): Move inline; use iterate_direct_aliases.
	(symtab_node::iterate_reference): Move inline.
	(symtab_node::iterate_referring): Move inline.
	(symtab_node::iterate_direct_aliases): Move inline.
	(symtab_node::used_from_object_file_p_worker): Inline into ...
	(symtab_node::used_from_object_file_p): ... this one; move inline.
	(symtab_node::call_for_symbol_and_aliases): Move inline;
	use iterate_direct_aliases.
	(symtab_node::call_for_symbol_and_aliases_1): New method.
	(cgraph_node::call_for_symbol_and_aliases): Move inline;
	use iterate_direct_aliases.
	(cgraph_node::call_for_symbol_and_aliases_1): New method.
	(varpool_node::call_for_node_and_aliases): Rename to ...
	(varpool_node::call_for_symbol_and_aliases): ... this one; Move inline;
	use iterate_direct_aliases.
	(varpool_node::call_for_symbol_and_aliases_1): New method.
	* ipa.c (ipa_single_use): Use iterate_direct_aliases.
	(ipa_discover_readonly_nonaddressable_var): Update.
	* ipa-devirt.c: Fix formating.
	* cgraph.c (cgraph_node::can_remove_if_no_direct_calls_and_refs_p):
	Move inline.
	(cgraph_node::call_for_symbol_and_aliases): Move inline.
	(cgraph_node::call_for_symbol_and_aliases_1): New function..
	* cgraph.h (used_from_object_file_p_worker): Remove.
	(resolution_used_from_other_file_p): Move inline.
	(symtab_node::has_aliases_p): Move inline; use iterate_direct_aliases.
	(symtab_node::iterate_reference): Move inline.
	(symtab_node::iterate_referring): Move inline.
	(symtab_node::iterate_direct_aliases): Move inline.
	(symtab_node::used_from_object_file_p_worker): Inline into ...
	(symtab_node::used_from_object_file_p): Move inline.
	* tree-emutls.c (ipa_lower_emutls): Update.
	* varpool.c (varpool_node::call_for_symbol_and_aliases_1): New method.
	(varpool_node::call_for_node_and_aliases): Remove.

Comments

Trevor Saunders Feb. 15, 2015, 7:22 p.m. UTC | #1
Hi,

> +symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
> +{
> +  ref_list.referring.iterate (i, &ref);
> +
> +  if (ref && ref->use != IPA_REF_ALIAS)
> +    return NULL;
> +
> +  return ref;
> +}

it seems a little weird the out arg can return a non alias, and so if
you only want to look at aliases you have to check the return value.

> +
> +/* Return true if list contains an alias.  */
> +
> +inline bool
> +symtab_node::has_aliases_p (void)
> +{
> +  ipa_ref *ref = NULL;
> +  int i;
> +
> +  for (i = 0; iterate_direct_aliases (i, ref); i++)
> +    if (ref->use == IPA_REF_ALIAS)
> +      return true;
> +  return false;
> +}

can it ever be true there is an alias in the list but it isn't the first
thing? the function above suggests not.

> +symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
> +							    void *),
> +					  void *data,
> +					  bool include_overwritable)
> +{
> +  ipa_ref *ref;
> +
> +  if (callback (this, data))
> +    return true;
> +  if (iterate_direct_aliases (0, ref))

wouldn't has_aliases_p be a little more clear?

Trev
On Sat, Feb 14, 2015 at 07:44:40PM +0100, Jan Hubicka wrote:
> Hi,
> Maritn has notced that we spend a lot of time in simple cgraph/varpool predicates. The patch bellow
> reorganizes inlines so the fast paths get fast.
> > perf report:
> >
> >     18.79%         lto1-wpa  lto1                 [.] do_estimate_growth_1(cgraph_node*, void*)
> >     12.48%         lto1-wpa  lto1                 [.] cgraph_node::can_remove_if_no_direct_calls_and_refs_p()
> >      5.86%         lto1-wpa  lto1                 [.] symtab_node::used_from_object_file_p_worker(symtab_node*)
> >      5.69%         lto1-wpa  lto1                 [.] cgraph_node::call_for_symbol_and_aliases(bool (*)(cgraph_node*, void*), void*, bool)
> >      5.01%  lto1-wpa-stream  lto1                 [.] streamer_tree_cache_lookup(streamer_tree_cache_d*, tree_node*, unsigned int*)
> >      4.84%         lto1-wpa  lto1                 [.] cgraph_node::call_for_symbol_thunks_and_aliases(bool (*)(cgraph_node*, void*), void*, bool, bool)
> >      2.44%         lto1-wpa  lto1                 [.] inflate_fast
> >      2.10%  lto1-wpa-stream  lto1                 [.] DFS::DFS_write_tree(output_block*, DFS::sccs*, tree_node*, bool, bool, bool)
> >      2.03%  lto1-wpa-stream  lto1                 [.] linemap_lookup(line_maps*, unsigned int)
> >      1.30%  lto1-wpa-stream  [kernel.kallsyms]    [k] isolate_migratepages_range
> >      1.27%         lto1-wpa  lto1                 [.] symtab_node::iterate_direct_aliases(unsigned int, ipa_ref*&)
> >      1.21%  lto1-wpa-stream  lto1                 [.] DFS::DFS_write_tree_body(output_block*, tree_node*, DFS::sccs*, bool, bool)
> >      1.19%  lto1-wpa-stream  lto1                 [.] streamer_write_uhwi_stream(lto_output_stream*, unsigned long)
> >      0.85%         lto1-wpa  lto1                 [.] compare_tree_sccs_1(tree_node*, tree_node*, tree_node***)
> >      0.83%         lto1-wpa  lto1                 [.] streamer_read_uhwi(lto_input_block*)
> >      0.74%  lto1-wpa-stream  lto1                 [.] streamer_tree_cache_insert_1(streamer_tree_cache_d*, tree_node*, unsigned int, unsigned int*, bool)
> >      0.72%         lto1-wpa  lto1                 [.] ht_lookup_with_hash(ht*, unsigned char const*, unsigned long, unsigned int, ht_lookup_option)
> >      0.70%  lto1-wpa-stream  [kernel.kallsyms]    [k] compaction_alloc
> >      0.68%         lto1-wpa  lto1                 [.] unify_scc(streamer_tree_cache_d*, unsigned int, unsigned int, unsigned int, unsigned int)
> >      0.66%  lto1-wpa-stream  lto1                 [.] lto_output_tree(output_block*, tree_node*, bool, bool)
> >      0.66%  lto1-wpa-stream  libc-2.19.so         [.] _int_malloc
> >      0.66%  lto1-wpa-stream  lto1                 [.] hash_table<hash_map<tree_node*, unsigned int, default_hashmap_traits>::hash_entry, xcallocator, true>::expand()
> >      0.62%  lto1-wpa-stream  lto1                 [.] streamer_write_tree_bitfields(output_block*, tree_node*)
> >      0.61%         lto1-wpa  lto1                 [.] streamer_read_tree_bitfields(lto_input_block*, data_in*, tree_node*)
> >      0.53%         lto1-wpa  lto1                 [.] lto_cgraph_replace_node(cgraph_node*, cgraph_node*)
> >      0.49%         lto1-wpa  [kernel.kallsyms]    [k] copy_pte_range
> 
> Bootstrapped/regtested x86_64-linux, comitted.
> 
> Honza
> 
> 	* ipa-chkp.c: Use iterate_direct_aliases.
> 	* symtab.c (resolution_used_from_other_file_p): Move inline.
> 	(symtab_node::create_reference): Fix formating.
> 	(symtab_node::has_aliases_p): Move inline; use iterate_direct_aliases.
> 	(symtab_node::iterate_reference): Move inline.
> 	(symtab_node::iterate_referring): Move inline.
> 	(symtab_node::iterate_direct_aliases): Move inline.
> 	(symtab_node::used_from_object_file_p_worker): Inline into ...
> 	(symtab_node::used_from_object_file_p): ... this one; move inline.
> 	(symtab_node::call_for_symbol_and_aliases): Move inline;
> 	use iterate_direct_aliases.
> 	(symtab_node::call_for_symbol_and_aliases_1): New method.
> 	(cgraph_node::call_for_symbol_and_aliases): Move inline;
> 	use iterate_direct_aliases.
> 	(cgraph_node::call_for_symbol_and_aliases_1): New method.
> 	(varpool_node::call_for_node_and_aliases): Rename to ...
> 	(varpool_node::call_for_symbol_and_aliases): ... this one; Move inline;
> 	use iterate_direct_aliases.
> 	(varpool_node::call_for_symbol_and_aliases_1): New method.
> 	* ipa.c (ipa_single_use): Use iterate_direct_aliases.
> 	(ipa_discover_readonly_nonaddressable_var): Update.
> 	* ipa-devirt.c: Fix formating.
> 	* cgraph.c (cgraph_node::can_remove_if_no_direct_calls_and_refs_p):
> 	Move inline.
> 	(cgraph_node::call_for_symbol_and_aliases): Move inline.
> 	(cgraph_node::call_for_symbol_and_aliases_1): New function..
> 	* cgraph.h (used_from_object_file_p_worker): Remove.
> 	(resolution_used_from_other_file_p): Move inline.
> 	(symtab_node::has_aliases_p): Move inline; use iterate_direct_aliases.
> 	(symtab_node::iterate_reference): Move inline.
> 	(symtab_node::iterate_referring): Move inline.
> 	(symtab_node::iterate_direct_aliases): Move inline.
> 	(symtab_node::used_from_object_file_p_worker): Inline into ...
> 	(symtab_node::used_from_object_file_p): Move inline.
> 	* tree-emutls.c (ipa_lower_emutls): Update.
> 	* varpool.c (varpool_node::call_for_symbol_and_aliases_1): New method.
> 	(varpool_node::call_for_node_and_aliases): Remove.
> Index: tree-emutls.c
> ===================================================================
> --- tree-emutls.c	(revision 220606)
> +++ tree-emutls.c	(working copy)
> @@ -787,7 +787,7 @@ ipa_lower_emutls (void)
>        if (var->alias && !var->analyzed)
>  	any_aliases = true;
>        else if (!var->alias)
> -	var->call_for_node_and_aliases (create_emultls_var, &ctor_body, true);
> +	var->call_for_symbol_and_aliases (create_emultls_var, &ctor_body, true);
>      }
>  
>    /* If there were any aliases, then frob the alias_pairs vector.  */
> Index: ipa-devirt.c
> ===================================================================
> --- ipa-devirt.c	(revision 220606)
> +++ ipa-devirt.c	(working copy)
> @@ -1710,7 +1710,6 @@ referenced_from_vtable_p (struct cgraph_
>      return true;
>  
>    for (i = 0; node->iterate_referring (i, ref); i++)
> -	
>      if ((ref->use == IPA_REF_ALIAS
>  	 && referenced_from_vtable_p (dyn_cast<cgraph_node *> (ref->referring)))
>  	|| (ref->use == IPA_REF_ADDR
> Index: ipa-chkp.c
> ===================================================================
> --- ipa-chkp.c	(revision 220606)
> +++ ipa-chkp.c	(working copy)
> @@ -534,14 +534,13 @@ chkp_maybe_create_clone (tree fndecl)
>  	symtab->call_cgraph_insertion_hooks (clone);
>  
>        /* Clone all aliases.  */
> -      for (i = 0; node->iterate_referring (i, ref); i++)
> -	if (ref->use == IPA_REF_ALIAS)
> -	  {
> -	    struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
> -	    struct cgraph_node *chkp_alias
> -	      = chkp_maybe_create_clone (alias->decl);
> -	    chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
> -	  }
> +      for (i = 0; node->iterate_direct_aliases (i, ref); i++)
> +	{
> +	  struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
> +	  struct cgraph_node *chkp_alias
> +	    = chkp_maybe_create_clone (alias->decl);
> +	  chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
> +	}
>  
>        /* Clone all thunks.  */
>        for (e = node->callers; e; e = e->next_caller)
> Index: symtab.c
> ===================================================================
> --- symtab.c	(revision 220630)
> +++ symtab.c	(working copy)
> @@ -313,18 +313,6 @@ symbol_table::change_decl_assembler_name
>      }
>  }
>  
> -/* Return true when RESOLUTION indicate that linker will use
> -   the symbol from non-LTO object files.  */
> -
> -bool
> -resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
> -{
> -  return (resolution == LDPR_PREVAILING_DEF
> -	  || resolution == LDPR_PREEMPTED_REG
> -	  || resolution == LDPR_RESOLVED_EXEC
> -	  || resolution == LDPR_RESOLVED_DYN);
> -}
> -
>  /* Hash sections by their names.  */
>  
>  hashval_t
> @@ -527,18 +515,18 @@ symtab_node::create_reference (symtab_no
>  
>    /* IPA_REF_ALIAS is always inserted at the beginning of the list.   */
>    if(use_type == IPA_REF_ALIAS)
> -  {
> -    list2->referring.safe_insert (0, ref);
> -    ref->referred_index = 0;
> -
> -    for (unsigned int i = 1; i < list2->referring.length (); i++)
> -      list2->referring[i]->referred_index = i;
> -  }
> +    {
> +      list2->referring.safe_insert (0, ref);
> +      ref->referred_index = 0;
> +
> +      for (unsigned int i = 1; i < list2->referring.length (); i++)
> +	list2->referring[i]->referred_index = i;
> +    }
>    else
> -  {
> -    list2->referring.safe_push (ref);
> -    ref->referred_index = list2->referring.length () - 1;
> -  }
> +    {
> +      list2->referring.safe_push (ref);
> +      ref->referred_index = list2->referring.length () - 1;
> +    }
>  
>    ref->referring = this;
>    ref->referred = referred_node;
> @@ -743,52 +731,6 @@ symtab_node::dump_referring (FILE *file)
>    fprintf (file, "\n");
>  }
>  
> -/* Return true if list contains an alias.  */
> -bool
> -symtab_node::has_aliases_p (void)
> -{
> -  ipa_ref *ref = NULL;
> -  int i;
> -
> -  for (i = 0; iterate_referring (i, ref); i++)
> -    if (ref->use == IPA_REF_ALIAS)
> -      return true;
> -  return false;
> -}
> -
> -/* Iterates I-th reference in the list, REF is also set.  */
> -
> -ipa_ref *
> -symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
> -{
> -  vec_safe_iterate (ref_list.references, i, &ref);
> -
> -  return ref;
> -}
> -
> -/* Iterates I-th referring item in the list, REF is also set.  */
> -
> -ipa_ref *
> -symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
> -{
> -  ref_list.referring.iterate (i, &ref);
> -
> -  return ref;
> -}
> -
> -/* Iterates I-th referring alias item in the list, REF is also set.  */
> -
> -ipa_ref *
> -symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
> -{
> -  ref_list.referring.iterate (i, &ref);
> -
> -  if (ref && ref->use != IPA_REF_ALIAS)
> -    return NULL;
> -
> -  return ref;
> -}
> -
>  static const char * const symtab_type_names[] = {"symbol", "function", "variable"};
>  
>  /* Dump base fields of symtab nodes to F.  Not to be used directly.  */
> @@ -1196,29 +1138,6 @@ symtab_node::verify_symtab_nodes (void)
>      }
>  }
>  
> -/* Return true when NODE is known to be used from other (non-LTO)
> -   object file. Known only when doing LTO via linker plugin.  */
> -
> -bool
> -symtab_node::used_from_object_file_p_worker (symtab_node *node)
> -{
> -  if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))
> -    return false;
> -  if (resolution_used_from_other_file_p (node->resolution))
> -    return true;
> -  return false;
> -}
> -
> -
> -/* Return true when symtab_node is known to be used from other (non-LTO)
> -   object file. Known only when doing LTO via linker plugin.  */
> -
> -bool
> -symtab_node::used_from_object_file_p (void)
> -{
> -  return symtab_node::used_from_object_file_p_worker (this);
> -}
> -
>  /* Make DECL local.  FIXME: We shouldn't need to mess with rtl this early,
>     but other code such as notice_global_symbol generates rtl.  */
>  
> @@ -1260,20 +1179,13 @@ symtab_node::make_decl_local (void)
>  
>  /* 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.  */
> +   Assumes NODE is known to be alias.  */
>  
>  symtab_node *
> -symtab_node::ultimate_alias_target (enum availability *availability)
> +symtab_node::ultimate_alias_target_1 (enum availability *availability)
>  {
>    bool weakref_p = false;
>  
> -  if (!alias)
> -    {
> -      if (availability)
> -	*availability = get_availability ();
> -      return this;
> -    }
> -
>    /* To determine visibility of the target, we follow ELF semantic of aliases.
>       Here alias is an alternative assembler name of a given definition. Its
>       availability prevails the availability of its target (i.e. static alias of
> @@ -1453,16 +1365,6 @@ symtab_node::get_init_priority ()
>    return h ? h->init : DEFAULT_INIT_PRIORITY;
>  }
>  
> -/* Return availability of NODE.  */
> -enum availability symtab_node::get_availability (void)
> -{
> -  if (is_a <cgraph_node *> (this))
> -    return dyn_cast <cgraph_node *> (this)->get_availability ();
> -  else
> -    return dyn_cast <varpool_node *> (this)->get_availability ();;
> -}
> -
> -
>  /* Return the finalization priority.  */
>  
>  priority_type
> @@ -1608,33 +1510,6 @@ symtab_node::resolve_alias (symtab_node
>    return true;
>  }
>  
> -/* Call calback on symtab node and aliases associated to this node.
> -   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
> -   skipped. */
> -
> -bool
> -symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
> -							  void *),
> -					void *data, bool include_overwritable)
> -{
> -  int i;
> -  ipa_ref *ref;
> -
> -  if (callback (this, data))
> -    return true;
> -  for (i = 0; iterate_referring (i, ref); i++)
> -    if (ref->use == IPA_REF_ALIAS)
> -      {
> -	symtab_node *alias = ref->referring;
> -	if (include_overwritable
> -	    || alias->get_availability () > AVAIL_INTERPOSABLE)
> -	  if (alias->call_for_symbol_and_aliases (callback, data,
> -						include_overwritable))
> -	    return true;
> -      }
> -  return false;
> -}
> -
>  /* Worker searching noninterposable alias.  */
>  
>  bool
> @@ -1961,3 +1836,24 @@ symtab_node::equal_address_to (symtab_no
>  
>    return 2;
>  }
> +
> +/* Worker for call_for_symbol_and_aliases.  */
> +
> +bool
> +symtab_node::call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *,
> +							      void *),
> +					    void *data,
> +					    bool include_overwritable)
> +{
> +  ipa_ref *ref;
> +  FOR_EACH_ALIAS (this, ref)
> +    {
> +      symtab_node *alias = ref->referring;
> +      if (include_overwritable
> +	  || alias->get_availability () > AVAIL_INTERPOSABLE)
> +	if (alias->call_for_symbol_and_aliases (callback, data,
> +					      include_overwritable))
> +	  return true;
> +    }
> +  return false;
> +}
> Index: ipa.c
> ===================================================================
> --- ipa.c	(revision 220630)
> +++ ipa.c	(working copy)
> @@ -808,8 +808,8 @@ ipa_discover_readonly_nonaddressable_var
>  	  {
>  	    if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
>  	      fprintf (dump_file, " %s (non-addressable)", vnode->name ());
> -	    vnode->call_for_node_and_aliases (clear_addressable_bit, NULL,
> -					      true);
> +	    vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL,
> +					        true);
>  	  }
>  	if (!address_taken && !written
>  	    /* Making variable in explicit section readonly can cause section
> @@ -819,14 +819,14 @@ ipa_discover_readonly_nonaddressable_var
>  	  {
>  	    if (!TREE_READONLY (vnode->decl) && dump_file)
>  	      fprintf (dump_file, " %s (read-only)", vnode->name ());
> -	    vnode->call_for_node_and_aliases (set_readonly_bit, NULL, true);
> +	    vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true);
>  	  }
>  	if (!vnode->writeonly && !read && !address_taken && written)
>  	  {
>  	    if (dump_file)
>  	      fprintf (dump_file, " %s (write-only)", vnode->name ());
> -	    vnode->call_for_node_and_aliases (set_writeonly_bit, &remove_p, 
> -					     true);
> +	    vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p, 
> +					        true);
>  	  }
>        }
>    if (dump_file)
> @@ -1343,9 +1343,8 @@ ipa_single_use (void)
>  	  single_user_map.put (var, user);
>  
>  	  /* Enqueue all aliases for re-processing.  */
> -	  for (i = 0; var->iterate_referring (i, ref); i++)
> -	    if (ref->use == IPA_REF_ALIAS
> -		&& !ref->referring->aux)
> +	  for (i = 0; var->iterate_direct_aliases (i, ref); i++)
> +	    if (!ref->referring->aux)
>  	      {
>  		ref->referring->aux = first;
>  		first = dyn_cast <varpool_node *> (ref->referring);
> Index: cgraph.c
> ===================================================================
> --- cgraph.c	(revision 220608)
> +++ cgraph.c	(working copy)
> @@ -2215,33 +2215,6 @@ cgraph_node::call_for_symbol_thunks_and_
>    return false;
>  }
>  
> -/* Call callback on function and aliases associated to the function.
> -   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
> -   skipped.  */
> -
> -bool
> -cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
> -							    void *),
> -					  void *data,
> -					  bool include_overwritable)
> -{
> -  ipa_ref *ref;
> -
> -  if (callback (this, data))
> -    return true;
> -
> -  FOR_EACH_ALIAS (this, ref)
> -    {
> -      cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
> -      if (include_overwritable
> -	  || alias->get_availability () > AVAIL_INTERPOSABLE)
> -	if (alias->call_for_symbol_and_aliases (callback, data,
> -						include_overwritable))
> -	  return true;
> -    }
> -  return false;
> -}
> -
>  /* Worker to bring NODE local.  */
>  
>  bool
> @@ -2430,37 +2403,6 @@ cgraph_edge::maybe_hot_p (void)
>    return true;
>  }
>  
> -/* Return true when function can be removed from callgraph
> -   if all direct calls are eliminated.  */
> -
> -bool
> -cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
> -{
> -  gcc_assert (!global.inlined_to);
> -  /* Instrumentation clones should not be removed before
> -     instrumentation happens.  New callers may appear after
> -     instrumentation.  */
> -  if (instrumentation_clone
> -      && !chkp_function_instrumented_p (decl))
> -    return false;
> -  /* Extern inlines can always go, we will use the external definition.  */
> -  if (DECL_EXTERNAL (decl))
> -    return true;
> -  /* When function is needed, we can not remove it.  */
> -  if (force_output || used_from_other_partition)
> -    return false;
> -  if (DECL_STATIC_CONSTRUCTOR (decl)
> -      || DECL_STATIC_DESTRUCTOR (decl))
> -    return false;
> -  /* Only COMDAT functions can be removed if externally visible.  */
> -  if (externally_visible
> -      && (!DECL_COMDAT (decl)
> -	  || forced_by_abi
> -	  || used_from_object_file_p ()))
> -    return false;
> -  return true;
> -}
> -
>  /* Worker for cgraph_can_remove_if_no_direct_calls_p.  */
>  
>  static bool
> @@ -3363,4 +3305,24 @@ cgraph_c_finalize (void)
>    version_info_node = NULL;
>  }
>  
> +/* A wroker for call_for_symbol_and_aliases.  */
> +
> +bool
> +cgraph_node::call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
> +							      void *),
> +					    void *data,
> +					    bool include_overwritable)
> +{
> +  ipa_ref *ref;
> +  FOR_EACH_ALIAS (this, ref)
> +    {
> +      cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
> +      if (include_overwritable
> +	  || alias->get_availability () > AVAIL_INTERPOSABLE)
> +	if (alias->call_for_symbol_and_aliases (callback, data,
> +						include_overwritable))
> +	  return true;
> +    }
> +  return false;
> +}
>  #include "gt-cgraph.h"
> Index: cgraph.h
> ===================================================================
> --- cgraph.h	(revision 220608)
> +++ cgraph.h	(working copy)
> @@ -377,10 +377,6 @@ public:
>    /* Verify symbol table for internal consistency.  */
>    static DEBUG_FUNCTION void verify_symtab_nodes (void);
>  
> -  /* Return true when NODE is known to be used from other (non-LTO)
> -     object file. Known only when doing LTO via linker plugin.  */
> -  static bool used_from_object_file_p_worker (symtab_node *node);
> -
>    /* Type of the symbol.  */
>    ENUM_BITFIELD (symtab_type) type : 8;
>  
> @@ -523,6 +519,10 @@ protected:
>       allocated structure is returned.  */
>    struct symbol_priority_map *priority_info (void);
>  
> +  /* Worker for call_for_symbol_and_aliases_1.  */
> +  bool call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *, void *),
> +				      void *data,
> +				      bool include_overwrite);
>  private:
>    /* Worker for set_section.  */
>    static bool set_section (symtab_node *n, void *s);
> @@ -532,6 +532,9 @@ private:
>  
>    /* Worker searching noninterposable alias.  */
>    static bool noninterposable_alias (symtab_node *node, void *data);
> +
> +  /* Worker for ultimate_alias_target.  */
> +  symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL);
>  };
>  
>  /* Walk all aliases for NODE.  */
> @@ -1291,6 +1294,12 @@ public:
>    unsigned nonfreeing_fn : 1;
>    /* True if there was multiple COMDAT bodies merged by lto-symtab.  */
>    unsigned merged : 1;
> +
> +private:
> +  /* Worker for call_for_symbol_and_aliases.  */
> +  bool call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
> +						        void *),
> +				      void *data, bool include_overwritable);
>  };
>  
>  /* A cgraph node set is a collection of cgraph nodes.  A cgraph node
> @@ -1670,9 +1679,9 @@ public:
>    /* Call calback on varpool symbol and aliases associated to varpool symbol.
>       When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
>       skipped. */
> -  bool call_for_node_and_aliases (bool (*callback) (varpool_node *, void *),
> -				  void *data,
> -				   bool include_overwritable);
> +  bool call_for_symbol_and_aliases (bool (*callback) (varpool_node *, void *),
> +				    void *data,
> +				    bool include_overwritable);
>  
>    /* Return true when variable should be considered externally visible.  */
>    bool externally_visible_p (void);
> @@ -1747,6 +1756,11 @@ public:
>  private:
>    /* Assemble thunks and aliases associated to varpool node.  */
>    void assemble_aliases (void);
> +
> +  /* Worker for call_for_node_and_aliases.  */
> +  bool call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, void *),
> +				      void *data,
> +				      bool include_overwritable);
>  };
>  
>  /* Every top level asm statement is put into a asm_node.  */
> @@ -2181,7 +2195,6 @@ bool cgraph_function_possibly_inlined_p
>  const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
>  cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t);
>  
> -bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
>  extern bool gimple_check_call_matching_types (gimple, tree, bool);
>  
>  /* In cgraphunit.c  */
> @@ -2209,6 +2222,9 @@ bool ipa_discover_readonly_nonaddressabl
>  /* In varpool.c  */
>  tree ctor_for_folding (tree);
>  
> +/* In tree-chkp.c  */
> +extern bool chkp_function_instrumented_p (tree fndecl);
> +
>  /* Return true when the symbol is real symbol, i.e. it is not inline clone
>     or abstract function kept for debug info purposes only.  */
>  inline bool
> @@ -2270,6 +2286,7 @@ symtab_node::get_alias_target (void)
>  }
>  
>  /* Return next reachable static symbol with initializer after the node.  */
> +
>  inline symtab_node *
>  symtab_node::next_defined_symbol (void)
>  {
> @@ -2282,6 +2299,78 @@ symtab_node::next_defined_symbol (void)
>    return NULL;
>  }
>  
> +/* Iterates I-th reference in the list, REF is also set.  */
> +
> +inline ipa_ref *
> +symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
> +{
> +  vec_safe_iterate (ref_list.references, i, &ref);
> +
> +  return ref;
> +}
> +
> +/* Iterates I-th referring item in the list, REF is also set.  */
> +
> +inline ipa_ref *
> +symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
> +{
> +  ref_list.referring.iterate (i, &ref);
> +
> +  return ref;
> +}
> +
> +/* Iterates I-th referring alias item in the list, REF is also set.  */
> +
> +inline ipa_ref *
diff mbox

Patch

Index: tree-emutls.c
===================================================================
--- tree-emutls.c	(revision 220606)
+++ tree-emutls.c	(working copy)
@@ -787,7 +787,7 @@  ipa_lower_emutls (void)
       if (var->alias && !var->analyzed)
 	any_aliases = true;
       else if (!var->alias)
-	var->call_for_node_and_aliases (create_emultls_var, &ctor_body, true);
+	var->call_for_symbol_and_aliases (create_emultls_var, &ctor_body, true);
     }
 
   /* If there were any aliases, then frob the alias_pairs vector.  */
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 220606)
+++ ipa-devirt.c	(working copy)
@@ -1710,7 +1710,6 @@  referenced_from_vtable_p (struct cgraph_
     return true;
 
   for (i = 0; node->iterate_referring (i, ref); i++)
-	
     if ((ref->use == IPA_REF_ALIAS
 	 && referenced_from_vtable_p (dyn_cast<cgraph_node *> (ref->referring)))
 	|| (ref->use == IPA_REF_ADDR
Index: ipa-chkp.c
===================================================================
--- ipa-chkp.c	(revision 220606)
+++ ipa-chkp.c	(working copy)
@@ -534,14 +534,13 @@  chkp_maybe_create_clone (tree fndecl)
 	symtab->call_cgraph_insertion_hooks (clone);
 
       /* Clone all aliases.  */
-      for (i = 0; node->iterate_referring (i, ref); i++)
-	if (ref->use == IPA_REF_ALIAS)
-	  {
-	    struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
-	    struct cgraph_node *chkp_alias
-	      = chkp_maybe_create_clone (alias->decl);
-	    chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
-	  }
+      for (i = 0; node->iterate_direct_aliases (i, ref); i++)
+	{
+	  struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+	  struct cgraph_node *chkp_alias
+	    = chkp_maybe_create_clone (alias->decl);
+	  chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
+	}
 
       /* Clone all thunks.  */
       for (e = node->callers; e; e = e->next_caller)
Index: symtab.c
===================================================================
--- symtab.c	(revision 220630)
+++ symtab.c	(working copy)
@@ -313,18 +313,6 @@  symbol_table::change_decl_assembler_name
     }
 }
 
-/* Return true when RESOLUTION indicate that linker will use
-   the symbol from non-LTO object files.  */
-
-bool
-resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
-{
-  return (resolution == LDPR_PREVAILING_DEF
-	  || resolution == LDPR_PREEMPTED_REG
-	  || resolution == LDPR_RESOLVED_EXEC
-	  || resolution == LDPR_RESOLVED_DYN);
-}
-
 /* Hash sections by their names.  */
 
 hashval_t
@@ -527,18 +515,18 @@  symtab_node::create_reference (symtab_no
 
   /* IPA_REF_ALIAS is always inserted at the beginning of the list.   */
   if(use_type == IPA_REF_ALIAS)
-  {
-    list2->referring.safe_insert (0, ref);
-    ref->referred_index = 0;
-
-    for (unsigned int i = 1; i < list2->referring.length (); i++)
-      list2->referring[i]->referred_index = i;
-  }
+    {
+      list2->referring.safe_insert (0, ref);
+      ref->referred_index = 0;
+
+      for (unsigned int i = 1; i < list2->referring.length (); i++)
+	list2->referring[i]->referred_index = i;
+    }
   else
-  {
-    list2->referring.safe_push (ref);
-    ref->referred_index = list2->referring.length () - 1;
-  }
+    {
+      list2->referring.safe_push (ref);
+      ref->referred_index = list2->referring.length () - 1;
+    }
 
   ref->referring = this;
   ref->referred = referred_node;
@@ -743,52 +731,6 @@  symtab_node::dump_referring (FILE *file)
   fprintf (file, "\n");
 }
 
-/* Return true if list contains an alias.  */
-bool
-symtab_node::has_aliases_p (void)
-{
-  ipa_ref *ref = NULL;
-  int i;
-
-  for (i = 0; iterate_referring (i, ref); i++)
-    if (ref->use == IPA_REF_ALIAS)
-      return true;
-  return false;
-}
-
-/* Iterates I-th reference in the list, REF is also set.  */
-
-ipa_ref *
-symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
-{
-  vec_safe_iterate (ref_list.references, i, &ref);
-
-  return ref;
-}
-
-/* Iterates I-th referring item in the list, REF is also set.  */
-
-ipa_ref *
-symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
-{
-  ref_list.referring.iterate (i, &ref);
-
-  return ref;
-}
-
-/* Iterates I-th referring alias item in the list, REF is also set.  */
-
-ipa_ref *
-symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
-{
-  ref_list.referring.iterate (i, &ref);
-
-  if (ref && ref->use != IPA_REF_ALIAS)
-    return NULL;
-
-  return ref;
-}
-
 static const char * const symtab_type_names[] = {"symbol", "function", "variable"};
 
 /* Dump base fields of symtab nodes to F.  Not to be used directly.  */
@@ -1196,29 +1138,6 @@  symtab_node::verify_symtab_nodes (void)
     }
 }
 
-/* Return true when NODE is known to be used from other (non-LTO)
-   object file. Known only when doing LTO via linker plugin.  */
-
-bool
-symtab_node::used_from_object_file_p_worker (symtab_node *node)
-{
-  if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))
-    return false;
-  if (resolution_used_from_other_file_p (node->resolution))
-    return true;
-  return false;
-}
-
-
-/* Return true when symtab_node is known to be used from other (non-LTO)
-   object file. Known only when doing LTO via linker plugin.  */
-
-bool
-symtab_node::used_from_object_file_p (void)
-{
-  return symtab_node::used_from_object_file_p_worker (this);
-}
-
 /* Make DECL local.  FIXME: We shouldn't need to mess with rtl this early,
    but other code such as notice_global_symbol generates rtl.  */
 
@@ -1260,20 +1179,13 @@  symtab_node::make_decl_local (void)
 
 /* 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.  */
+   Assumes NODE is known to be alias.  */
 
 symtab_node *
-symtab_node::ultimate_alias_target (enum availability *availability)
+symtab_node::ultimate_alias_target_1 (enum availability *availability)
 {
   bool weakref_p = false;
 
-  if (!alias)
-    {
-      if (availability)
-	*availability = get_availability ();
-      return this;
-    }
-
   /* To determine visibility of the target, we follow ELF semantic of aliases.
      Here alias is an alternative assembler name of a given definition. Its
      availability prevails the availability of its target (i.e. static alias of
@@ -1453,16 +1365,6 @@  symtab_node::get_init_priority ()
   return h ? h->init : DEFAULT_INIT_PRIORITY;
 }
 
-/* Return availability of NODE.  */
-enum availability symtab_node::get_availability (void)
-{
-  if (is_a <cgraph_node *> (this))
-    return dyn_cast <cgraph_node *> (this)->get_availability ();
-  else
-    return dyn_cast <varpool_node *> (this)->get_availability ();;
-}
-
-
 /* Return the finalization priority.  */
 
 priority_type
@@ -1608,33 +1510,6 @@  symtab_node::resolve_alias (symtab_node
   return true;
 }
 
-/* Call calback on symtab node and aliases associated to this node.
-   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
-   skipped. */
-
-bool
-symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
-							  void *),
-					void *data, bool include_overwritable)
-{
-  int i;
-  ipa_ref *ref;
-
-  if (callback (this, data))
-    return true;
-  for (i = 0; iterate_referring (i, ref); i++)
-    if (ref->use == IPA_REF_ALIAS)
-      {
-	symtab_node *alias = ref->referring;
-	if (include_overwritable
-	    || alias->get_availability () > AVAIL_INTERPOSABLE)
-	  if (alias->call_for_symbol_and_aliases (callback, data,
-						include_overwritable))
-	    return true;
-      }
-  return false;
-}
-
 /* Worker searching noninterposable alias.  */
 
 bool
@@ -1961,3 +1836,24 @@  symtab_node::equal_address_to (symtab_no
 
   return 2;
 }
+
+/* Worker for call_for_symbol_and_aliases.  */
+
+bool
+symtab_node::call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *,
+							      void *),
+					    void *data,
+					    bool include_overwritable)
+{
+  ipa_ref *ref;
+  FOR_EACH_ALIAS (this, ref)
+    {
+      symtab_node *alias = ref->referring;
+      if (include_overwritable
+	  || alias->get_availability () > AVAIL_INTERPOSABLE)
+	if (alias->call_for_symbol_and_aliases (callback, data,
+					      include_overwritable))
+	  return true;
+    }
+  return false;
+}
Index: ipa.c
===================================================================
--- ipa.c	(revision 220630)
+++ ipa.c	(working copy)
@@ -808,8 +808,8 @@  ipa_discover_readonly_nonaddressable_var
 	  {
 	    if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
 	      fprintf (dump_file, " %s (non-addressable)", vnode->name ());
-	    vnode->call_for_node_and_aliases (clear_addressable_bit, NULL,
-					      true);
+	    vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL,
+					        true);
 	  }
 	if (!address_taken && !written
 	    /* Making variable in explicit section readonly can cause section
@@ -819,14 +819,14 @@  ipa_discover_readonly_nonaddressable_var
 	  {
 	    if (!TREE_READONLY (vnode->decl) && dump_file)
 	      fprintf (dump_file, " %s (read-only)", vnode->name ());
-	    vnode->call_for_node_and_aliases (set_readonly_bit, NULL, true);
+	    vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true);
 	  }
 	if (!vnode->writeonly && !read && !address_taken && written)
 	  {
 	    if (dump_file)
 	      fprintf (dump_file, " %s (write-only)", vnode->name ());
-	    vnode->call_for_node_and_aliases (set_writeonly_bit, &remove_p, 
-					     true);
+	    vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p, 
+					        true);
 	  }
       }
   if (dump_file)
@@ -1343,9 +1343,8 @@  ipa_single_use (void)
 	  single_user_map.put (var, user);
 
 	  /* Enqueue all aliases for re-processing.  */
-	  for (i = 0; var->iterate_referring (i, ref); i++)
-	    if (ref->use == IPA_REF_ALIAS
-		&& !ref->referring->aux)
+	  for (i = 0; var->iterate_direct_aliases (i, ref); i++)
+	    if (!ref->referring->aux)
 	      {
 		ref->referring->aux = first;
 		first = dyn_cast <varpool_node *> (ref->referring);
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 220608)
+++ cgraph.c	(working copy)
@@ -2215,33 +2215,6 @@  cgraph_node::call_for_symbol_thunks_and_
   return false;
 }
 
-/* Call callback on function and aliases associated to the function.
-   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
-   skipped.  */
-
-bool
-cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
-							    void *),
-					  void *data,
-					  bool include_overwritable)
-{
-  ipa_ref *ref;
-
-  if (callback (this, data))
-    return true;
-
-  FOR_EACH_ALIAS (this, ref)
-    {
-      cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
-      if (include_overwritable
-	  || alias->get_availability () > AVAIL_INTERPOSABLE)
-	if (alias->call_for_symbol_and_aliases (callback, data,
-						include_overwritable))
-	  return true;
-    }
-  return false;
-}
-
 /* Worker to bring NODE local.  */
 
 bool
@@ -2430,37 +2403,6 @@  cgraph_edge::maybe_hot_p (void)
   return true;
 }
 
-/* Return true when function can be removed from callgraph
-   if all direct calls are eliminated.  */
-
-bool
-cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
-{
-  gcc_assert (!global.inlined_to);
-  /* Instrumentation clones should not be removed before
-     instrumentation happens.  New callers may appear after
-     instrumentation.  */
-  if (instrumentation_clone
-      && !chkp_function_instrumented_p (decl))
-    return false;
-  /* Extern inlines can always go, we will use the external definition.  */
-  if (DECL_EXTERNAL (decl))
-    return true;
-  /* When function is needed, we can not remove it.  */
-  if (force_output || used_from_other_partition)
-    return false;
-  if (DECL_STATIC_CONSTRUCTOR (decl)
-      || DECL_STATIC_DESTRUCTOR (decl))
-    return false;
-  /* Only COMDAT functions can be removed if externally visible.  */
-  if (externally_visible
-      && (!DECL_COMDAT (decl)
-	  || forced_by_abi
-	  || used_from_object_file_p ()))
-    return false;
-  return true;
-}
-
 /* Worker for cgraph_can_remove_if_no_direct_calls_p.  */
 
 static bool
@@ -3363,4 +3305,24 @@  cgraph_c_finalize (void)
   version_info_node = NULL;
 }
 
+/* A wroker for call_for_symbol_and_aliases.  */
+
+bool
+cgraph_node::call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
+							      void *),
+					    void *data,
+					    bool include_overwritable)
+{
+  ipa_ref *ref;
+  FOR_EACH_ALIAS (this, ref)
+    {
+      cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+      if (include_overwritable
+	  || alias->get_availability () > AVAIL_INTERPOSABLE)
+	if (alias->call_for_symbol_and_aliases (callback, data,
+						include_overwritable))
+	  return true;
+    }
+  return false;
+}
 #include "gt-cgraph.h"
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 220608)
+++ cgraph.h	(working copy)
@@ -377,10 +377,6 @@  public:
   /* Verify symbol table for internal consistency.  */
   static DEBUG_FUNCTION void verify_symtab_nodes (void);
 
-  /* Return true when NODE is known to be used from other (non-LTO)
-     object file. Known only when doing LTO via linker plugin.  */
-  static bool used_from_object_file_p_worker (symtab_node *node);
-
   /* Type of the symbol.  */
   ENUM_BITFIELD (symtab_type) type : 8;
 
@@ -523,6 +519,10 @@  protected:
      allocated structure is returned.  */
   struct symbol_priority_map *priority_info (void);
 
+  /* Worker for call_for_symbol_and_aliases_1.  */
+  bool call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *, void *),
+				      void *data,
+				      bool include_overwrite);
 private:
   /* Worker for set_section.  */
   static bool set_section (symtab_node *n, void *s);
@@ -532,6 +532,9 @@  private:
 
   /* Worker searching noninterposable alias.  */
   static bool noninterposable_alias (symtab_node *node, void *data);
+
+  /* Worker for ultimate_alias_target.  */
+  symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL);
 };
 
 /* Walk all aliases for NODE.  */
@@ -1291,6 +1294,12 @@  public:
   unsigned nonfreeing_fn : 1;
   /* True if there was multiple COMDAT bodies merged by lto-symtab.  */
   unsigned merged : 1;
+
+private:
+  /* Worker for call_for_symbol_and_aliases.  */
+  bool call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
+						        void *),
+				      void *data, bool include_overwritable);
 };
 
 /* A cgraph node set is a collection of cgraph nodes.  A cgraph node
@@ -1670,9 +1679,9 @@  public:
   /* Call calback on varpool symbol and aliases associated to varpool symbol.
      When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
      skipped. */
-  bool call_for_node_and_aliases (bool (*callback) (varpool_node *, void *),
-				  void *data,
-				   bool include_overwritable);
+  bool call_for_symbol_and_aliases (bool (*callback) (varpool_node *, void *),
+				    void *data,
+				    bool include_overwritable);
 
   /* Return true when variable should be considered externally visible.  */
   bool externally_visible_p (void);
@@ -1747,6 +1756,11 @@  public:
 private:
   /* Assemble thunks and aliases associated to varpool node.  */
   void assemble_aliases (void);
+
+  /* Worker for call_for_node_and_aliases.  */
+  bool call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, void *),
+				      void *data,
+				      bool include_overwritable);
 };
 
 /* Every top level asm statement is put into a asm_node.  */
@@ -2181,7 +2195,6 @@  bool cgraph_function_possibly_inlined_p
 const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
 cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t);
 
-bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
 extern bool gimple_check_call_matching_types (gimple, tree, bool);
 
 /* In cgraphunit.c  */
@@ -2209,6 +2222,9 @@  bool ipa_discover_readonly_nonaddressabl
 /* In varpool.c  */
 tree ctor_for_folding (tree);
 
+/* In tree-chkp.c  */
+extern bool chkp_function_instrumented_p (tree fndecl);
+
 /* Return true when the symbol is real symbol, i.e. it is not inline clone
    or abstract function kept for debug info purposes only.  */
 inline bool
@@ -2270,6 +2286,7 @@  symtab_node::get_alias_target (void)
 }
 
 /* Return next reachable static symbol with initializer after the node.  */
+
 inline symtab_node *
 symtab_node::next_defined_symbol (void)
 {
@@ -2282,6 +2299,78 @@  symtab_node::next_defined_symbol (void)
   return NULL;
 }
 
+/* Iterates I-th reference in the list, REF is also set.  */
+
+inline ipa_ref *
+symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
+{
+  vec_safe_iterate (ref_list.references, i, &ref);
+
+  return ref;
+}
+
+/* Iterates I-th referring item in the list, REF is also set.  */
+
+inline ipa_ref *
+symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
+{
+  ref_list.referring.iterate (i, &ref);
+
+  return ref;
+}
+
+/* Iterates I-th referring alias item in the list, REF is also set.  */
+
+inline ipa_ref *
+symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
+{
+  ref_list.referring.iterate (i, &ref);
+
+  if (ref && ref->use != IPA_REF_ALIAS)
+    return NULL;
+
+  return ref;
+}
+
+/* Return true if list contains an alias.  */
+
+inline bool
+symtab_node::has_aliases_p (void)
+{
+  ipa_ref *ref = NULL;
+  int i;
+
+  for (i = 0; iterate_direct_aliases (i, ref); i++)
+    if (ref->use == IPA_REF_ALIAS)
+      return true;
+  return false;
+}
+
+/* Return true when RESOLUTION indicate that linker will use
+   the symbol from non-LTO object files.  */
+
+inline bool
+resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
+{
+  return (resolution == LDPR_PREVAILING_DEF
+	  || resolution == LDPR_PREEMPTED_REG
+	  || resolution == LDPR_RESOLVED_EXEC
+	  || resolution == LDPR_RESOLVED_DYN);
+}
+
+/* Return true when symtab_node is known to be used from other (non-LTO)
+   object file. Known only when doing LTO via linker plugin.  */
+
+inline bool
+symtab_node::used_from_object_file_p (void)
+{
+  if (!TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+    return false;
+  if (resolution_used_from_other_file_p (resolution))
+    return true;
+  return false;
+}
+
 /* Return varpool node for given symbol and check it is a function. */
 
 inline varpool_node *
@@ -2644,6 +2733,37 @@  cgraph_node::only_called_directly_or_ali
 	  && !externally_visible);
 }
 
+/* Return true when function can be removed from callgraph
+   if all direct calls are eliminated.  */
+
+inline bool
+cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
+{
+  gcc_checking_assert (!global.inlined_to);
+  /* Instrumentation clones should not be removed before
+     instrumentation happens.  New callers may appear after
+     instrumentation.  */
+  if (instrumentation_clone
+      && !chkp_function_instrumented_p (decl))
+    return false;
+  /* Extern inlines can always go, we will use the external definition.  */
+  if (DECL_EXTERNAL (decl))
+    return true;
+  /* When function is needed, we can not remove it.  */
+  if (force_output || used_from_other_partition)
+    return false;
+  if (DECL_STATIC_CONSTRUCTOR (decl)
+      || DECL_STATIC_DESTRUCTOR (decl))
+    return false;
+  /* Only COMDAT functions can be removed if externally visible.  */
+  if (externally_visible
+      && (!DECL_COMDAT (decl)
+	  || forced_by_abi
+	  || used_from_object_file_p ()))
+    return false;
+  return true;
+}
+
 /* Return true when variable can be removed from variable pool
    if all direct calls are eliminated.  */
 
@@ -2699,6 +2819,23 @@  varpool_node::get_alias_target (void)
   return dyn_cast <varpool_node *> (symtab_node::get_alias_target ());
 }
 
+/* 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.  */
+
+inline symtab_node *
+symtab_node::ultimate_alias_target (enum availability *availability)
+{
+  if (!alias)
+    {
+      if (availability)
+	*availability = get_availability ();
+      return this;
+    }
+
+  return ultimate_alias_target_1 (availability);
+}
+
 /* Given function symbol, 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.  */
@@ -2706,8 +2843,8 @@  varpool_node::get_alias_target (void)
 inline cgraph_node *
 cgraph_node::ultimate_alias_target (enum availability *availability)
 {
-  cgraph_node *n = dyn_cast <cgraph_node *> (symtab_node::ultimate_alias_target
-    (availability));
+  cgraph_node *n = dyn_cast <cgraph_node *>
+    (symtab_node::ultimate_alias_target (availability));
   if (!n && availability)
     *availability = AVAIL_NOT_AVAILABLE;
   return n;
@@ -2756,6 +2893,7 @@  cgraph_edge::redirect_callee (cgraph_nod
 }
 
 /* Return true when the edge represents a direct recursion.  */
+
 inline bool
 cgraph_edge::recursive_p (void)
 {
@@ -2813,7 +2951,11 @@  cgraph_node::optimize_for_size_p (void)
     return false;
 }
 
-inline symtab_node * symtab_node::get_create (tree node)
+/* Return symtab_node for NODE or create one if it is not present
+   in symtab.  */
+
+inline symtab_node *
+symtab_node::get_create (tree node)
 {
   if (TREE_CODE (node) == VAR_DECL)
     return varpool_node::get_create (node);
@@ -2821,6 +2963,76 @@  inline symtab_node * symtab_node::get_cr
     return cgraph_node::get_create (node);
 }
 
+/* Return availability of NODE.  */
+
+inline enum availability
+symtab_node::get_availability (void)
+{
+  if (is_a <cgraph_node *> (this))
+    return dyn_cast <cgraph_node *> (this)->get_availability ();
+  else
+    return dyn_cast <varpool_node *> (this)->get_availability ();;
+}
+
+/* Call calback on symtab node and aliases associated to this node.
+   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+   skipped. */
+
+inline bool
+symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
+							    void *),
+					  void *data,
+					  bool include_overwritable)
+{
+  ipa_ref *ref;
+
+  if (callback (this, data))
+    return true;
+  if (iterate_direct_aliases (0, ref))
+    return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+  return false;
+}
+
+/* Call callback on function and aliases associated to the function.
+   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+   skipped.  */
+
+inline bool
+cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
+							    void *),
+					  void *data,
+					  bool include_overwritable)
+{
+  ipa_ref *ref;
+
+  if (callback (this, data))
+    return true;
+  if (iterate_direct_aliases (0, ref))
+    return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+
+  return false;
+}
+
+/* Call calback on varpool symbol and aliases associated to varpool symbol.
+   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+   skipped. */
+
+inline bool
+varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
+							     void *),
+					   void *data,
+					   bool include_overwritable)
+{
+  ipa_ref *ref;
+
+  if (callback (this, data))
+    return true;
+  if (iterate_direct_aliases (0, ref))
+    return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+
+  return false;
+}
+
 /* Build polymorphic call context for indirect call E.  */
 
 inline
Index: varpool.c
===================================================================
--- varpool.c	(revision 220606)
+++ varpool.c	(working copy)
@@ -817,28 +817,23 @@  varpool_node::create_extra_name_alias (t
   return alias_node;
 }
 
-/* Call calback on varpool symbol and aliases associated to varpool symbol.
-   When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
-   skipped. */
+/* Worker for call_for_symbol_and_aliases.  */
 
 bool
-varpool_node::call_for_node_and_aliases (bool (*callback) (varpool_node *,
-							   void *),
-					 void *data,
-					 bool include_overwritable)
+varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
+							       void *),
+					     void *data,
+					     bool include_overwritable)
 {
   ipa_ref *ref;
 
-  if (callback (this, data))
-    return true;
-
   FOR_EACH_ALIAS (this, ref)
     {
       varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
       if (include_overwritable
 	  || alias->get_availability () > AVAIL_INTERPOSABLE)
-	if (alias->call_for_node_and_aliases (callback, data,
-					      include_overwritable))
+	if (alias->call_for_symbol_and_aliases (callback, data,
+					        include_overwritable))
 	  return true;
     }
   return false;