From patchwork Thu Jul 9 09:13:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Martin_Li=C5=A1ka?= X-Patchwork-Id: 493374 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 771D5140295 for ; Thu, 9 Jul 2015 21:08:28 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=uNfx7egs; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :resent-from:resent-to:resent-date:resent-message-id:message-id :in-reply-to:references:from:date:subject:to; q=dns; s=default; b= pBB+yIXXExK1KlnPt8/KU+i5UEWCld3LGIFpcZRki1W1XJ/DSY6jjn7wNfW7cP3O tOS2+MEAWXoMU6Il71aosthgsvm7WXvtzNhtNldvIMif0Ppv7o3acH1mPi9fLyvG Wkl8A54MMqUaub/2T1YcOX12o8ZAxm3LvNnFJcUrmSc= 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 :resent-from:resent-to:resent-date:resent-message-id:message-id :in-reply-to:references:from:date:subject:to; s=default; bh=pIS+ PpCobNbjVxLLsQzGhyvZBuo=; b=uNfx7egslGmgCAh2Di++QCuBwzUqapmZcsZm XcU34c6T91/xrG1rG89/o0yKd+L94ySDEH0rt5jRaUkakyx0l8ijmU8OOepZTBlA gT59StCzj3233oXM4SJbDBOIi181RHYuCmVhsClT9WxPRHlqiasN30aEwUs0vPTe z53IkNA= Received: (qmail 61044 invoked by alias); 9 Jul 2015 11:08:08 -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 60955 invoked by uid 89); 9 Jul 2015 11:08:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.9 required=5.0 tests=AWL, BAYES_05, KAM_LAZY_DOMAIN_SECURITY, KAM_STOCKGEN autolearn=no version=3.3.2 X-HELO: mx2.suse.de Received: from cantor2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 09 Jul 2015 11:07:57 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id CF4ACACF7 for ; Thu, 9 Jul 2015 11:07:53 +0000 (UTC) Resent-From: =?UTF-8?B?TWFydGluIExpxaFrYQ==?= Resent-To: GCC Patches Resent-Date: Thu, 9 Jul 2015 13:07:40 +0200 Resent-Message-ID: <559E55FC.2060200@suse.cz> Resent-User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 Message-Id: <7267a56ab77ff35fa4d77ea6d4eba9d924187be1.1436438929.git.mliska@suse.cz> In-Reply-To: References: From: mliska Date: Thu, 9 Jul 2015 11:13:52 +0200 Subject: [PATCH 2/6] Introduce new edge_summary class and replace ipa_edge_args_sum. To: gcc-patches@gcc.gnu.org X-IsSubscribed: yes gcc/ChangeLog: 2015-07-03 Martin Liska * cgraph.c (symbol_table::create_edge): Introduce summary_uid for cgraph_edge. * cgraph.h (struct GTY): Likewise. * ipa-inline-analysis.c (estimate_function_body_sizes): Use new data structure. * ipa-profile.c (ipa_profile): Likewise. * ipa-prop.c (ipa_print_node_jump_functions): (ipa_propagate_indirect_call_infos): Likewise. (ipa_free_edge_args_substructures): Likewise. (ipa_free_all_edge_args): Likewise. (ipa_edge_args_t::remove): Likewise. (ipa_edge_removal_hook): Likewise. (ipa_edge_args_t::duplicate): Likewise. (ipa_register_cgraph_hooks): Likewise. (ipa_unregister_cgraph_hooks): Likewise. * ipa-prop.h (ipa_check_create_edge_args): Likewise. (ipa_edge_args_info_available_for_edge_p): Likewise. * symbol-summary.h (gt_ggc_mx): Indent properly. (gt_pch_nx): Likewise. (edge_summary): New class. --- gcc/cgraph.c | 2 + gcc/cgraph.h | 5 +- gcc/ipa-inline-analysis.c | 2 +- gcc/ipa-profile.c | 2 +- gcc/ipa-prop.c | 71 +++------------- gcc/ipa-prop.h | 44 ++++++---- gcc/symbol-summary.h | 208 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 252 insertions(+), 82 deletions(-) diff --git a/gcc/cgraph.c b/gcc/cgraph.c index d13bcd3..d7b6257 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -851,6 +851,8 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee, edge->uid = edges_max_uid++; } + edge->summary_uid = edge_max_summary_uid++; + edges_count++; edge->aux = NULL; diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 0fe58e1..ef71958 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1593,6 +1593,8 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"), int frequency; /* Unique id of the edge. */ int uid; + /* Not recycled unique id of the node. */ + int summary_uid; /* Whether this edge was made direct by indirect inlining. */ unsigned int indirect_inlining_edge : 1; /* Whether this edge describes an indirect call with an undetermined @@ -1874,7 +1876,7 @@ public: friend class cgraph_node; friend class cgraph_edge; - symbol_table (): cgraph_max_summary_uid (1) + symbol_table (): cgraph_max_summary_uid (1), edge_max_summary_uid (1) { } @@ -2078,6 +2080,7 @@ public: int edges_count; int edges_max_uid; + int edge_max_summary_uid; symtab_node* GTY(()) nodes; asm_node* GTY(()) asmnodes; diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index d5dbfbd..c11dc9c 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2852,7 +2852,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) { if (!early) loop_optimizer_finalize (); - else if (!ipa_edge_args_vector) + else if (!ipa_edge_args_sum) ipa_free_all_node_params (); free_dominance_info (CDI_DOMINATORS); } diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index 698729b..6d6afb3 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -627,7 +627,7 @@ ipa_profile (void) "Not speculating: target is overwritable " "and can be discarded.\n"); } - else if (ipa_node_params_sum && ipa_edge_args_vector + else if (ipa_node_params_sum && ipa_edge_args_sum && !IPA_NODE_REF (n2)->descriptors.is_empty () && ipa_get_param_count (IPA_NODE_REF (n2)) != ipa_get_cs_argument_count (IPA_EDGE_REF (e)) diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 6074194..9750a26 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -125,12 +125,10 @@ struct func_body_info ipa_node_params_t *ipa_node_params_sum = NULL; /* Vector of IPA-CP transformation data for each clone. */ vec *ipcp_transformations; -/* Vector where the parameter infos are actually stored. */ -vec *ipa_edge_args_vector; + +edge_summary *ipa_edge_args_sum; /* Holders of ipa cgraph hooks: */ -static struct cgraph_edge_hook_list *edge_removal_hook_holder; -static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; static struct cgraph_node_hook_list *function_insertion_hook_holder; /* Description of a reference to an IPA constant. */ @@ -386,9 +384,6 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) node->order); for (cs = node->callees; cs; cs = cs->next_callee) { - if (!ipa_edge_args_info_available_for_edge_p (cs)) - continue; - fprintf (f, " callsite %s/%i -> %s/%i : \n", xstrdup_for_dump (node->name ()), node->order, xstrdup_for_dump (cs->callee->name ()), @@ -399,8 +394,6 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) for (cs = node->indirect_calls; cs; cs = cs->next_callee) { struct cgraph_indirect_call_info *ii; - if (!ipa_edge_args_info_available_for_edge_p (cs)) - continue; ii = cs->indirect_info; if (ii->agg_contents) @@ -3330,7 +3323,7 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, (i.e. during early inlining). */ if (!ipa_node_params_sum) return false; - gcc_assert (ipa_edge_args_vector); + gcc_assert (ipa_edge_args_sum); propagate_controlled_uses (cs); changed = propagate_info_to_inlined_callees (cs, cs->callee, new_edges); @@ -3338,16 +3331,6 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, return changed; } -/* Frees all dynamically allocated structures that the argument info points - to. */ - -void -ipa_free_edge_args_substructures (struct ipa_edge_args *args) -{ - vec_free (args->jump_functions); - memset (args, 0, sizeof (*args)); -} - /* Free all ipa_edge structures. */ void @@ -3356,13 +3339,11 @@ ipa_free_all_edge_args (void) int i; struct ipa_edge_args *args; - if (!ipa_edge_args_vector) + if (!ipa_edge_args_sum) return; - FOR_EACH_VEC_ELT (*ipa_edge_args_vector, i, args) - ipa_free_edge_args_substructures (args); - - vec_free (ipa_edge_args_vector); + ipa_edge_args_sum->release (); + ipa_edge_args_sum = NULL; } /* Frees all dynamically allocated structures that the param info points @@ -3414,18 +3395,9 @@ ipa_set_node_agg_value_chain (struct cgraph_node *node, (*ipcp_transformations)[node->uid].agg_values = aggvals; } -/* Hook that is called by cgraph.c when an edge is removed. */ - -static void -ipa_edge_removal_hook (struct cgraph_edge *cs, void *data ATTRIBUTE_UNUSED) +void +ipa_edge_args_t::remove (cgraph_edge *edge, ipa_edge_args *args) { - struct ipa_edge_args *args; - - /* During IPA-CP updating we can be called on not-yet analyzed clones. */ - if (vec_safe_length (ipa_edge_args_vector) <= (unsigned)cs->uid) - return; - - args = IPA_EDGE_REF (cs); if (args->jump_functions) { struct ipa_jump_func *jf; @@ -3436,28 +3408,19 @@ ipa_edge_removal_hook (struct cgraph_edge *cs, void *data ATTRIBUTE_UNUSED) try_decrement_rdesc_refcount (jf); if (jf->type == IPA_JF_CONST && (rdesc = ipa_get_jf_constant_rdesc (jf)) - && rdesc->cs == cs) + && rdesc->cs == edge) rdesc->cs = NULL; } } - - ipa_free_edge_args_substructures (IPA_EDGE_REF (cs)); } -/* Hook that is called by cgraph.c when an edge is duplicated. */ - -static void -ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, - void *) +void +ipa_edge_args_t::duplicate (cgraph_edge *src, cgraph_edge *dst, + ipa_edge_args *old_args, ipa_edge_args *new_args) { - struct ipa_edge_args *old_args, *new_args; unsigned int i; - ipa_check_create_edge_args (); - old_args = IPA_EDGE_REF (src); - new_args = IPA_EDGE_REF (dst); - new_args->jump_functions = vec_safe_copy (old_args->jump_functions); if (old_args->polymorphic_call_contexts) new_args->polymorphic_call_contexts @@ -3607,12 +3570,6 @@ ipa_register_cgraph_hooks (void) { ipa_check_create_node_params (); - if (!edge_removal_hook_holder) - edge_removal_hook_holder = - symtab->add_edge_removal_hook (&ipa_edge_removal_hook, NULL); - if (!edge_duplication_hook_holder) - edge_duplication_hook_holder = - symtab->add_edge_duplication_hook (&ipa_edge_duplication_hook, NULL); function_insertion_hook_holder = symtab->add_cgraph_insertion_hook (&ipa_add_new_function, NULL); } @@ -3622,10 +3579,6 @@ ipa_register_cgraph_hooks (void) static void ipa_unregister_cgraph_hooks (void) { - symtab->remove_edge_removal_hook (edge_removal_hook_holder); - edge_removal_hook_holder = NULL; - symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); - edge_duplication_hook_holder = NULL; symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder); function_insertion_hook_holder = NULL; } diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index e6725aa..f0af9b2 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -493,13 +493,36 @@ public: extern ipa_node_params_t *ipa_node_params_sum; /* Vector of IPA-CP transformation data for each clone. */ extern GTY(()) vec *ipcp_transformations; -/* Vector where the parameter infos are actually stored. */ -extern GTY(()) vec *ipa_edge_args_vector; + +/* Function summary for ipa_node_params. */ +class GTY((user)) ipa_edge_args_t: public edge_summary +{ +public: + ipa_edge_args_t (symbol_table *symtab): + edge_summary (symtab, true) { } + + static ipa_edge_args_t *create_ggc (symbol_table *symtab) + { + ipa_edge_args_t *summary = new (ggc_cleared_alloc ()) + ipa_edge_args_t (symtab); + return summary; + } + + /* Hook that is called by summary when a node is duplicated. */ + virtual void duplicate (cgraph_edge *edge, + cgraph_edge *edge2, + ipa_edge_args *data, + ipa_edge_args *data2); + + virtual void remove (cgraph_edge *edge, ipa_edge_args *data); +}; + +extern GTY(()) edge_summary *ipa_edge_args_sum; /* Return the associated parameter/argument info corresponding to the given node/edge. */ #define IPA_NODE_REF(NODE) (ipa_node_params_sum->get (NODE)) -#define IPA_EDGE_REF(EDGE) (&(*ipa_edge_args_vector)[(EDGE)->uid]) +#define IPA_EDGE_REF(EDGE) (ipa_edge_args_sum->get (EDGE)) /* This macro checks validity of index returned by ipa_get_param_decl_index function. */ #define IS_VALID_JUMP_FUNC_INDEX(I) ((I) != -1) @@ -532,19 +555,8 @@ ipa_check_create_node_params (void) static inline void ipa_check_create_edge_args (void) { - if (vec_safe_length (ipa_edge_args_vector) - <= (unsigned) symtab->edges_max_uid) - vec_safe_grow_cleared (ipa_edge_args_vector, symtab->edges_max_uid + 1); -} - -/* Returns true if the array of edge infos is large enough to accommodate an - info for EDGE. The main purpose of this function is that debug dumping - function can check info availability without causing reallocations. */ - -static inline bool -ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge) -{ - return ((unsigned) edge->uid < vec_safe_length (ipa_edge_args_vector)); + if (ipa_edge_args_sum == NULL) + ipa_edge_args_sum = ipa_edge_args_t::create_ggc (symtab); } static inline ipcp_transformation_summary * diff --git a/gcc/symbol-summary.h b/gcc/symbol-summary.h index eefbfd9..5799443 100644 --- a/gcc/symbol-summary.h +++ b/gcc/symbol-summary.h @@ -108,7 +108,7 @@ public: /* Allocates new data that are stored within map. */ T* allocate_new () { - return m_ggc ? new (ggc_alloc ()) T() : new T () ; + return m_ggc ? new (ggc_alloc ()) T () : new T () ; } /* Release an item that is stored within map. */ @@ -234,7 +234,7 @@ private: template void -gt_ggc_mx(function_summary* const &summary) +gt_ggc_mx (function_summary* const &summary) { gcc_checking_assert (summary->m_ggc); gt_ggc_mx (&summary->m_map); @@ -242,7 +242,7 @@ gt_ggc_mx(function_summary* const &summary) template void -gt_pch_nx(function_summary* const &summary) +gt_pch_nx (function_summary* const &summary) { gcc_checking_assert (summary->m_ggc); gt_pch_nx (&summary->m_map); @@ -250,11 +250,211 @@ gt_pch_nx(function_summary* const &summary) template void -gt_pch_nx(function_summary* const& summary, gt_pointer_operator op, +gt_pch_nx (function_summary* const& summary, gt_pointer_operator op, void *cookie) { gcc_checking_assert (summary->m_ggc); gt_pch_nx (&summary->m_map, op, cookie); } +/* We want to pass just pointer types as argument for edge_summary + template class. */ + +template +class edge_summary +{ +private: + edge_summary (); +}; + +template +class GTY((user)) edge_summary +{ +public: + /* Default construction takes SYMTAB as an argument. */ + edge_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc), + m_map (13, ggc), m_symtab (symtab) + { +#ifdef ENABLE_CHECKING + cgraph_node *node; + + FOR_EACH_FUNCTION (node) + { + gcc_checking_assert (node->summary_uid > 0); + } +#endif + + m_symtab_removal_hook = + symtab->add_edge_removal_hook + (edge_summary::symtab_removal, this); + m_symtab_duplication_hook = + symtab->add_edge_duplication_hook + (edge_summary::symtab_duplication, this); + } + + /* Destructor. */ + virtual ~edge_summary () + { + release (); + } + + /* Destruction method that can be called for GGT purpose. */ + void release () + { + if (m_symtab_removal_hook) + m_symtab->remove_edge_removal_hook (m_symtab_removal_hook); + + if (m_symtab_duplication_hook) + m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook); + + m_symtab_removal_hook = NULL; + m_symtab_duplication_hook = NULL; + + /* Release all summaries. */ + typedef typename hash_map ::iterator map_iterator; + for (map_iterator it = m_map.begin (); it != m_map.end (); ++it) + release ((*it).second); + } + + /* Traverses all summarys with a function F called with + ARG as argument. */ + template + void traverse (Arg a) const + { + m_map.traverse (a); + } + + /* Initializer is called after we allocate a new node. */ + virtual void initialize (cgraph_edge *, T *) {} + + /* Basic implementation of removal operation. */ + virtual void remove (cgraph_edge *, T *) {} + + /* Basic implementation of duplication operation. */ + virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {} + + /* Allocates new data that are stored within map. */ + T* allocate_new (cgraph_edge *edge) + { + T *v = m_ggc ? new (ggc_alloc ()) T () : new T () ; + initialize (edge, v); + + return v; + } + + /* Release an item that is stored within map. */ + void release (T *item) + { + if (m_ggc) + { + item->~T (); + ggc_free (item); + } + else + delete item; + } + + /* Getter for summary edge node pointer. */ + T* get (cgraph_edge *edge) + { + bool existed; + T **v = &m_map.get_or_insert (edge->summary_uid, &existed); + if (!existed) + *v = allocate_new (edge); + + return *v; + } + + /* Return number of elements handled by data structure. */ + size_t elements () + { + return m_map.elements (); + } + + /* Symbol removal hook that is registered to symbol table. */ + static void symtab_removal (cgraph_edge *node, void *data) + { + gcc_checking_assert (node->summary_uid); + edge_summary *summary = (edge_summary *) (data); + + int summary_uid = node->summary_uid; + T **v = summary->m_map.get (summary_uid); + + if (v) + { + summary->remove (node, *v); + + if (!summary->m_ggc) + delete (*v); + + summary->m_map.remove (summary_uid); + } + } + + /* Symbol duplication hook that is registered to symbol table. */ + static void symtab_duplication (cgraph_edge *edge, cgraph_edge *edge2, + void *data) + { + edge_summary *summary = (edge_summary *) (data); + T *s = summary->get (edge); + + gcc_checking_assert (s); + gcc_checking_assert (edge2->summary_uid > 0); + + /* This load is necessary, because we insert a new value! */ + T *duplicate = summary->allocate_new (edge2); + summary->m_map.put (edge2->summary_uid, duplicate); + summary->duplicate (edge, edge2, s, duplicate); + } + +protected: + /* Indication if we use ggc summary. */ + bool m_ggc; + +private: + typedef int_hash map_hash; + + /* Main summary store, where summary ID is used as key. */ + hash_map m_map; + /* Internal summary insertion hook pointer. */ + cgraph_edge_hook_list *m_symtab_insertion_hook; + /* Internal summary removal hook pointer. */ + cgraph_edge_hook_list *m_symtab_removal_hook; + /* Internal summary duplication hook pointer. */ + cgraph_2edge_hook_list *m_symtab_duplication_hook; + /* Symbol table the summary is registered to. */ + symbol_table *m_symtab; + + template friend void gt_ggc_mx (edge_summary * const &); + template friend void gt_pch_nx (edge_summary * const &); + template friend void gt_pch_nx (edge_summary * const &, + gt_pointer_operator, void *); +}; + +template +void +gt_ggc_mx (edge_summary* const &summary) +{ + gcc_checking_assert (summary->m_ggc); + gt_ggc_mx (&summary->m_map); +} + +template +void +gt_pch_nx (edge_summary* const &summary) +{ + gcc_checking_assert (summary->m_ggc); + gt_pch_nx (&summary->m_map); +} + +template +void +gt_pch_nx (edge_summary* const& summary, gt_pointer_operator op, + void *cookie) +{ + gcc_checking_assert (summary->m_ggc); + gt_pch_nx (&summary->m_map, op, cookie); +} + + #endif /* GCC_SYMBOL_SUMMARY_H */