From patchwork Sat Feb 14 18:44:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 439788 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 061BC14027F for ; Sun, 15 Feb 2015 05:44:56 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=qogNhqbs8hK20rQir BZ+PR39hlw4guBW3eaQw9zJQEQ+UgM8Fun5CFW6qXprSguY0aFDq4MksPmZ39GVg F3Uh+h5E17kip89ZctfdvivSJ/I+wYC6Ang3KbvBZFrawSrg9N9y8hdH1MMEEjy0 mqoRHfutrc6FtrLplR1Ntqg4V8= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:references:mime-version :content-type:in-reply-to; s=default; bh=gmr1+S0qfUX+KLzEKg53uG/ Nwyo=; b=qLy+uYltoIsCUNzbvz4OVBiDgMKxv69jYKch754AfFFuW7xKYCQYW/1 vUaZ04CkfghSVyXjv+I9YnGOkJXlbecDGfERCszc3MP8avWaVtC1xcOzSzqc141o +7IH5L06g6ojMlnd6fJtqHeorqfpW9/rsuJqGw90XqhuzW+1M5GM= Received: (qmail 31885 invoked by alias); 14 Feb 2015 18:44:48 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 31867 invoked by uid 89); 14 Feb 2015 18:44:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_50, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: nikam.ms.mff.cuni.cz Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sat, 14 Feb 2015 18:44:44 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 8598054332E; Sat, 14 Feb 2015 19:44:40 +0100 (CET) Date: Sat, 14 Feb 2015 19:44:40 +0100 From: Jan Hubicka To: Martin =?iso-8859-2?Q?Li=B9ka?= , gcc-patches@gcc.gnu.org Cc: "hubicka >> Jan Hubicka" Subject: Re: Chromium: LTO Message-ID: <20150214184440.GC20469@kam.mff.cuni.cz> References: <54DE7CE2.8040202@suse.cz> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <54DE7CE2.8040202@suse.cz> User-Agent: Mutt/1.5.21 (2010-09-15) 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_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 (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 (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 (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 (this)) - return dyn_cast (this)->get_availability (); - else - return dyn_cast (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 (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 (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 (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 (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 (symtab_node::ultimate_alias_target - (availability)); + cgraph_node *n = dyn_cast + (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 (this)) + return dyn_cast (this)->get_availability (); + else + return dyn_cast (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 (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;