From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1700 invoked by alias); 16 Oct 2014 14:15:59 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 1688 invoked by uid 89); 16 Oct 2014 14:15:59 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.0 required=5.0 tests=AWL,BAYES_00 autolearn=ham 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, 16 Oct 2014 14:15:54 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 55E4CACA7; Thu, 16 Oct 2014 14:15:51 +0000 (UTC) Date: Thu, 16 Oct 2014 14:16:00 -0000 From: Martin Jambor To: Martin =?utf-8?B?TGnFoWth?= Cc: GCC Patches , Jan Hubicka Subject: Re: [RFC, PATCH]: Introduction of callgraph annotation class Message-ID: <20141016141550.GB14611@virgil.suse> Mail-Followup-To: Martin =?utf-8?B?TGnFoWth?= , GCC Patches , Jan Hubicka References: <543EA03A.7000000@suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <543EA03A.7000000@suse.cz> User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes X-SW-Source: 2014-10/txt/msg01574.txt.bz2 Hi, On Wed, Oct 15, 2014 at 06:26:34PM +0200, Martin Liska wrote: > Hello. > > Following patch introduces a new class called callgraph_annotation. Idea behind the patch is to provide a generic interface one can use to register custom info related to a cgraph_node. As you know, symbol_table provides hooks for creation, deletion and duplication of a cgraph_node. If you have a pass, you need to handle all these hooks and store custom data in your data structure. > > As an example, after discussion with Martin, I chose usage in ipa-prop.h: > > data structure: > vec ipa_node_params_vector > > if the pass handles an event, following chunk is executed: > if (ipa_node_params_vector.length () <= (unsigned) symtab->cgraph_max_uid) > ipa_node_params_vector.safe_grow_cleared (symtab->cgraph_max_uid + 1); > > The problem is that you can have sparse UIDs of cgraph_nodes and every time you have to allocate a vector of size equal to cgraph_max_uid. > > As a replacement, I implemented first version of cgraph_annotation that internally uses hash_map. > Every time a node is deleted, we remove corresponding data associated to the node. > > What do you think about it? It is clearly an improvement over how we manage our annotations now. However, I do have a few comments/suggestions: 1. I do not think we need multiple hooks for the same event for one kind of annotations. So I think they need not be stored in a vector. In fact, I thought that these would be converted to virtual functions with some default implementation (i.e. nothing for creation/deletion, memcpy for duplication) and one would only register the annotation, not its hooks, and redefine the virtual methods if need be. 2. I think you want to keep a deletion hook (or virtual method), rather than relying on destructors of types you keep in annotations. One reason is that it may be useful to be able to store a POD and still be notified when its life is over, another is that once you attempt to store garbage collected data then destructors really won't make any sense. Of course it is very nice if the using destructors also works. 3. If you change a line with "struct cgraph_node" in ipa-prop.[ch], don't worry about keeping the struct part and omit it as you do in other files. The good old C times are gone forever and I am doing the same in my patches too. 4. I believe that the reverse map should not be necessary if we change timing of deletion hook calls which should not cause any problems. 5. I am no C++ expert but can't annotation_hashmap_traits be a private type of class cgraph_annotation template? 6. I know that an operator overload is a bold proposal but given this is supposed to be an important part of IPA infrastructure I think that eventually it would be appropriate and convenient to overload [] and use that instead of calling get_or_add method. 7. I certainly hope that after we convert all annotations, UID can become unique and not recycled again and we can use that instead of the new annotation_uid. (And use it in dumps too!) Thanks, Martin > > Thank you, > Martin > diff --git a/gcc/Makefile.in b/gcc/Makefile.in > index 04ce0c0..bf34c96 100644 > --- a/gcc/Makefile.in > +++ b/gcc/Makefile.in > @@ -1171,6 +1171,7 @@ OBJS = \ > cfgrtl.o \ > symtab.o \ > cgraph.o \ > + annotation.o \ > cgraphbuild.o \ > cgraphunit.o \ > cgraphclones.o \ > diff --git a/gcc/annotation.c b/gcc/annotation.c > new file mode 100644 > index 0000000..a8b6053 > --- /dev/null > +++ b/gcc/annotation.c > @@ -0,0 +1 @@ > +#include "annotation.h" > diff --git a/gcc/annotation.h b/gcc/annotation.h > new file mode 100644 > index 0000000..7520677 > --- /dev/null > +++ b/gcc/annotation.h > @@ -0,0 +1,285 @@ > +/* Annotations handling code. > + Copyright (C) 2014 Free Software Foundation, Inc. > + Contributed by Martin Liska > + > +This file is part of GCC. > + > +GCC is free software; you can redistribute it and/or modify it under > +the terms of the GNU General Public License as published by the Free > +Software Foundation; either version 3, or (at your option) any later > +version. > + > +GCC is distributed in the hope that it will be useful, but WITHOUT ANY > +WARRANTY; without even the implied warranty of MERCHANTABILITY or > +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > +for more details. > + > +You should have received a copy of the GNU General Public License > +along with GCC; see the file COPYING3. If not see > +. */ > + > +#ifndef GCC_ANNOTATION_H > +#define GCC_ANNOTATION_H > + > +#include "config.h" > +#include "system.h" > +#include "coretypes.h" > +#include "tm.h" > +#include "tree.h" > +#include "varasm.h" > +#include "calls.h" > +#include "print-tree.h" > +#include "tree-inline.h" > +#include "langhooks.h" > +#include "hashtab.h" > +#include "toplev.h" > +#include "flags.h" > +#include "debug.h" > +#include "target.h" > +#include "cgraph.h" > +#include "hash-map.h" > + > +#define ANNOTATION_DELETED_VALUE -1 > +#define ANNOTATION_EMPTY_VALUE 0 > + > +struct annotation_hashmap_traits: default_hashmap_traits > +{ > + static inline > + hashval_t hash (const int v) > + { > + return (hashval_t)v; > + } > + > + template > + static inline > + bool is_deleted (T &e) > + { > + return e.m_key == ANNOTATION_DELETED_VALUE; > + } > + > + template > + static inline > + bool is_empty (T &e) > + { > + return e.m_key == ANNOTATION_EMPTY_VALUE; > + } > + > + template > + static inline > + void mark_deleted (T &e) > + { > + e.m_key = ANNOTATION_DELETED_VALUE; > + } > + > + template > + static inline > + void mark_empty (T &e) > + { > + e.m_key = ANNOTATION_EMPTY_VALUE; > + } > +}; > + > +template > +class cgraph_annotation > +{ > +public: > + /* Default construction takes SYMTAB as an argument. */ > + cgraph_annotation (symbol_table *symtab): m_symtab (symtab) > + { > + cgraph_node *node; > + > + FOR_EACH_FUNCTION (node) > + { > + gcc_assert (node->annotation_uid > 0); > + m_reverse_map.put (node, node->annotation_uid); > + } > + > + m_map = new hash_map(); > + > + m_symtab_insertion_hook = > + symtab->add_cgraph_insertion_hook > + (cgraph_annotation::symtab_insertion, this); > + > + m_symtab_removal_hook = > + symtab->add_cgraph_removal_hook > + (cgraph_annotation::symtab_removal, this); > + m_symtab_duplication_hook = > + symtab->add_cgraph_duplication_hook > + (cgraph_annotation::symtab_duplication, this); > + > + } > + > + /* Destructor. */ > + ~cgraph_annotation () > + { > + m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook); > + m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook); > + m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook); > + > + m_map->traverse (NULL); > + } > + > + /* Traverses all annotations with a function F called with > + ARG as argument. */ > + template > + void traverse (Arg a) const > + { > + m_map->traverse (a); > + } > + > + /* Function for registering insertion hook. */ > + template > + inline void add_insertion_hook (void) > + { > + m_insertion_hooks.safe_push (f); > + } > + > + /* Function for registering removal hook. */ > + template > + inline void add_removal_hook (void) > + { > + m_removal_hooks.safe_push (f); > + } > + > + /* Function for registering duplication hook. */ > + template > + inline void add_duplication_hook (void) > + { > + m_duplication_hooks.safe_push (f); > + } > + > + /* Getter for annotation callgraph ID. */ > + inline T* get_or_add (int uid) > + { > + T **v = m_map->get (uid); > + if (!v) > + { > + T *new_value = new T(); > + m_map->put (uid, new_value); > + > + v = &new_value; > + } > + > + return *v; > + } > + > + /* Getter for annotation callgraph node pointer. */ > + inline T *get_or_add (cgraph_node *node) > + { > + return get_or_add (node->annotation_uid); > + } > + > + /* Symbol insertion hook that is registered to symbol table. */ > + static void symtab_insertion (cgraph_node *node, void *data) > + { > + cgraph_annotation *annotation = (cgraph_annotation *) (data); > + annotation->call_insertion_hooks (node); > + } > + > + /* Symbol removal hook that is registered to symbol table. */ > + static void symtab_removal (cgraph_node *node, void *data) > + { > + cgraph_annotation *annotation = (cgraph_annotation *) (data); > + int *annotation_uid_ptr = annotation->m_reverse_map.get (node); > + > + if (!annotation_uid_ptr) > + return; > + > + int annotation_uid = *annotation_uid_ptr; > + > + T **v = annotation->m_map->get (annotation_uid); > + > + if (v) > + annotation->call_removal_hooks (node, *v); > + > + annotation->m_reverse_map.remove (node); > + > + if (annotation->m_map->get (annotation_uid)) > + annotation->m_map->remove (annotation_uid); > + > + } > + > + /* Symbol duplication hook that is registered to symbol table. */ > + static void symtab_duplication (cgraph_node *node, cgraph_node *node2, > + void *data) > + { > + cgraph_annotation *annotation = (cgraph_annotation *) (data); > + T **v = annotation->m_map->get (node->annotation_uid); > + > + gcc_assert (node2->annotation_uid > 0); > + annotation->m_reverse_map.put (node2, node2->annotation_uid); > + > + if (v) > + { > + T *data = *v; > + T *duplicate = new T(); > + annotation->m_map->put (node2->annotation_uid, duplicate); > + annotation->call_duplication_hooks (node, node2, data); > + } > + > + } > + > + /* Main annotation store, where annotation ID is used as key. */ > + hash_map *m_map; > + > + /* Inverse mapping structure used in cgraph deletion context. */ > + hash_map m_reverse_map; > + > +private: > + /* Remove annotation for annotation UID. */ > + inline void remove (int uid) > + { > + T *v = m_map->get (uid); > + > + if (v) > + m_map->erase (uid); > + } > + > + /* Annotation class release function called by traverse method. */ > + static bool release (int const &, T * const &v, void *) > + { > + delete (v); > + return true; > + } > + > + /* Call insertion hook for callgraph NODE. */ > + inline void call_insertion_hooks (cgraph_node *node) > + { > + for (unsigned int i = 0; i < m_insertion_hooks.length (); i++) > + m_insertion_hooks[i] (node, get_or_add (node)); > + } > + > + /* Call removal hook for callgraph NODE. */ > + inline void call_removal_hooks (cgraph_node *node, T *v) > + { > + for (unsigned int i = 0; i < m_removal_hooks.length (); i++) > + m_removal_hooks[i] (node, v); > + } > + > + /* Call duplication hook for callgraph NODE. */ > + inline void call_duplication_hooks (cgraph_node *node, cgraph_node *node2, T *v) > + { > + for (unsigned int i = 0; i < m_duplication_hooks.length (); i++) > + m_duplication_hooks[i] (node, node2, v, get_or_add (node2)); > + } > + > + /* List of symbol insertion hooks. */ > + auto_vec m_insertion_hooks; > + /* List of symbol removal hooks. */ > + auto_vec m_removal_hooks; > + /* List of symbol duplication hooks. */ > + auto_vec > + m_duplication_hooks; > + > + /* Internal annotation insertion hook pointer. */ > + cgraph_node_hook_list *m_symtab_insertion_hook; > + /* Internal annotation removal hook pointer. */ > + cgraph_node_hook_list *m_symtab_removal_hook; > + /* Internal annotation duplication hook pointer. */ > + cgraph_2node_hook_list *m_symtab_duplication_hook; > + > + /* Symbol table the annotation is registered to. */ > + symbol_table *m_symtab; > +}; > + > +#endif /* GCC_ANNOTATION_H */ > diff --git a/gcc/cgraph.h b/gcc/cgraph.h > index a5777c2..32a770a 100644 > --- a/gcc/cgraph.h > +++ b/gcc/cgraph.h > @@ -1219,6 +1219,8 @@ public: > int count_materialization_scale; > /* Unique id of the node. */ > int uid; > + /* Annotation unique id of the node. */ > + int annotation_uid; > /* ID assigned by the profiling. */ > unsigned int profile_id; > /* Time profiler: first run of function. */ > @@ -1771,6 +1773,10 @@ public: > friend class cgraph_node; > friend class cgraph_edge; > > + symbol_table (): cgraph_max_annotation_uid (1) > + { > + } > + > /* Initialize callgraph dump file. */ > inline void > initialize (void) > @@ -1972,6 +1978,7 @@ public: > > int cgraph_count; > int cgraph_max_uid; > + int cgraph_max_annotation_uid; > > int edges_count; > int edges_max_uid; > @@ -2268,6 +2275,9 @@ symbol_table::create_empty (void) > { > cgraph_node *node = allocate_cgraph_symbol (); > > + gcc_assert (cgraph_max_annotation_uid); > + node->annotation_uid = cgraph_max_annotation_uid++; > + > node->type = SYMTAB_FUNCTION; > node->frequency = NODE_FREQUENCY_NORMAL; > node->count_materialization_scale = REG_BR_PROB_BASE; > diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c > index 38f56d2..e2576b3 100644 > --- a/gcc/ipa-inline-analysis.c > +++ b/gcc/ipa-inline-analysis.c > @@ -895,7 +895,7 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool inline_p, > if (known_binfos_ptr) > known_binfos_ptr->create (0); > > - if (ipa_node_params_vector.exists () > + if (ipa_node_params_annotation > && !e->call_stmt_cannot_inline_p > && ((clause_ptr && info->conds) || known_vals_ptr || known_binfos_ptr)) > { > @@ -1115,7 +1115,7 @@ inline_node_duplication_hook (struct cgraph_node *src, > > /* When there are any replacements in the function body, see if we can figure > out that something was optimized out. */ > - if (ipa_node_params_vector.exists () && dst->clone.tree_map) > + if (ipa_node_params_annotation && dst->clone.tree_map) > { > vec *entry = info->entry; > /* Use SRC parm info since it may not be copied yet. */ > @@ -2462,7 +2462,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) > calculate_dominance_info (CDI_DOMINATORS); > loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); > > - if (ipa_node_params_vector.exists ()) > + if (ipa_node_params_annotation) > { > parms_info = IPA_NODE_REF (node); > nonconstant_names.safe_grow_cleared > @@ -2610,7 +2610,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) > nonconstant_names[SSA_NAME_VERSION (gimple_call_lhs (stmt))] > = false_p; > } > - if (ipa_node_params_vector.exists ()) > + if (ipa_node_params_annotation) > { > int count = gimple_call_num_args (stmt); > int i; > @@ -3353,7 +3353,7 @@ static void > remap_edge_change_prob (struct cgraph_edge *inlined_edge, > struct cgraph_edge *edge) > { > - if (ipa_node_params_vector.exists ()) > + if (ipa_node_params_annotation) > { > int i; > struct ipa_edge_args *args = IPA_EDGE_REF (edge); > @@ -3509,7 +3509,7 @@ inline_merge_summary (struct cgraph_edge *edge) > else > toplev_predicate = true_predicate (); > > - if (ipa_node_params_vector.exists () && callee_info->conds) > + if (ipa_node_params_annotation && callee_info->conds) > { > struct ipa_edge_args *args = IPA_EDGE_REF (edge); > int count = ipa_get_cs_argument_count (args); > diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c > index 9ac1929..ad98467 100644 > --- a/gcc/ipa-inline.c > +++ b/gcc/ipa-inline.c > @@ -2408,7 +2408,7 @@ pass_early_inline::execute (function *fun) > it. This may confuse ourself when early inliner decide to inline call to > function clone, because function clones don't have parameter list in > ipa-prop matching their signature. */ > - if (ipa_node_params_vector.exists ()) > + if (ipa_node_params_annotation) > return 0; > > #ifdef ENABLE_CHECKING > diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c > index 62db327..743d9ff 100644 > --- a/gcc/ipa-prop.c > +++ b/gcc/ipa-prop.c > @@ -115,7 +115,8 @@ struct func_body_info > unsigned int aa_walked; > }; > > -/* Vector where the parameter infos are actually stored. */ > +/* Callgraph annotation where the parameter infos are actually stored. */ > +cgraph_annotation *ipa_node_params_annotation = NULL; > vec ipa_node_params_vector; > /* Vector of known aggregate values in cloned nodes. */ > vec *ipa_node_agg_replacements; > @@ -124,9 +125,7 @@ vec *ipa_edge_args_vector; > > /* Holders of ipa cgraph hooks: */ > static struct cgraph_edge_hook_list *edge_removal_hook_holder; > -static struct cgraph_node_hook_list *node_removal_hook_holder; > static struct cgraph_2edge_hook_list *edge_duplication_hook_holder; > -static struct cgraph_2node_hook_list *node_duplication_hook_holder; > static struct cgraph_node_hook_list *function_insertion_hook_holder; > > /* Description of a reference to an IPA constant. */ > @@ -3554,7 +3553,7 @@ ipa_propagate_indirect_call_infos (struct cgraph_edge *cs, > bool changed; > /* Do nothing if the preparation phase has not been carried out yet > (i.e. during early inlining). */ > - if (!ipa_node_params_vector.exists ()) > + if (!ipa_node_params_annotation) > return false; > gcc_assert (ipa_edge_args_vector); > > @@ -3594,15 +3593,21 @@ ipa_free_all_edge_args (void) > /* Frees all dynamically allocated structures that the param info points > to. */ > > -void > -ipa_free_node_params_substructures (struct ipa_node_params *info) > +ipa_node_params::~ipa_node_params () > { > - info->descriptors.release (); > - free (info->lattices); > + descriptors.release (); > + free (lattices); > /* Lattice values and their sources are deallocated with their alocation > pool. */ > - info->known_vals.release (); > - memset (info, 0, sizeof (*info)); > + known_vals.release (); > + > + lattices = NULL; > + ipcp_orig_node = NULL; > + analysis_done = 0; > + node_enqueued = 0; > + do_clone_for_all_contexts = 0; > + is_all_contexts_clone = 0; > + node_dead = 0; > } > > /* Free all ipa_node_params structures. */ > @@ -3610,11 +3615,8 @@ ipa_free_node_params_substructures (struct ipa_node_params *info) > void > ipa_free_all_node_params (void) > { > - int i; > - struct ipa_node_params *info; > - > - FOR_EACH_VEC_ELT (ipa_node_params_vector, i, info) > - ipa_free_node_params_substructures (info); > + delete ipa_node_params_annotation; > + ipa_node_params_annotation = NULL; > > ipa_node_params_vector.release (); > } > @@ -3622,7 +3624,7 @@ ipa_free_all_node_params (void) > /* Set the aggregate replacements of NODE to be AGGVALS. */ > > void > -ipa_set_node_agg_value_chain (struct cgraph_node *node, > +ipa_set_node_agg_value_chain (const struct cgraph_node *node, > struct ipa_agg_replacement_value *aggvals) > { > if (vec_safe_length (ipa_node_agg_replacements) > @@ -3663,18 +3665,6 @@ ipa_edge_removal_hook (struct cgraph_edge *cs, void *data ATTRIBUTE_UNUSED) > ipa_free_edge_args_substructures (IPA_EDGE_REF (cs)); > } > > -/* Hook that is called by cgraph.c when a node is removed. */ > - > -static void > -ipa_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) > -{ > - /* During IPA-CP updating we can be called on not-yet analyze clones. */ > - if (ipa_node_params_vector.length () > (unsigned)node->uid) > - ipa_free_node_params_substructures (IPA_NODE_REF (node)); > - if (vec_safe_length (ipa_node_agg_replacements) > (unsigned)node->uid) > - (*ipa_node_agg_replacements)[(unsigned)node->uid] = NULL; > -} > - > /* Hook that is called by cgraph.c when an edge is duplicated. */ > > static void > @@ -3779,18 +3769,22 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, > } > } > > -/* Hook that is called by cgraph.c when a node is duplicated. */ > +/* Analyze newly added function into callgraph. */ > > static void > -ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, > - ATTRIBUTE_UNUSED void *data) > +ipa_add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) > { > - struct ipa_node_params *old_info, *new_info; > - struct ipa_agg_replacement_value *old_av, *new_av; > + if (node->has_gimple_body_p ()) > + ipa_analyze_node (node); > +} > > - ipa_check_create_node_params (); > - old_info = IPA_NODE_REF (src); > - new_info = IPA_NODE_REF (dst); > +/* Hook that is called by cgraph.c when a node is duplicated. */ > + > +void > +ipa_node_duplication_hook (const struct cgraph_node *src, const struct cgraph_node *dst, > + struct ipa_node_params *old_info, struct ipa_node_params *new_info) > +{ > + struct ipa_agg_replacement_value *old_av, *new_av; > > new_info->descriptors = old_info->descriptors.copy (); > new_info->lattices = NULL; > @@ -3817,33 +3811,19 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, > ipa_set_node_agg_value_chain (dst, new_av); > } > > - > -/* Analyze newly added function into callgraph. */ > - > -static void > -ipa_add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) > -{ > - if (node->has_gimple_body_p ()) > - ipa_analyze_node (node); > -} > - > /* Register our cgraph hooks if they are not already there. */ > > void > 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 (!node_removal_hook_holder) > - node_removal_hook_holder = > - symtab->add_cgraph_removal_hook (&ipa_node_removal_hook, NULL); > if (!edge_duplication_hook_holder) > edge_duplication_hook_holder = > symtab->add_edge_duplication_hook (&ipa_edge_duplication_hook, NULL); > - if (!node_duplication_hook_holder) > - node_duplication_hook_holder = > - symtab->add_cgraph_duplication_hook (&ipa_node_duplication_hook, NULL); > function_insertion_hook_holder = > symtab->add_cgraph_insertion_hook (&ipa_add_new_function, NULL); > } > @@ -3855,12 +3835,8 @@ ipa_unregister_cgraph_hooks (void) > { > symtab->remove_edge_removal_hook (edge_removal_hook_holder); > edge_removal_hook_holder = NULL; > - symtab->remove_cgraph_removal_hook (node_removal_hook_holder); > - node_removal_hook_holder = NULL; > symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); > edge_duplication_hook_holder = NULL; > - symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder); > - node_duplication_hook_holder = NULL; > symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder); > function_insertion_hook_holder = NULL; > } > @@ -5030,8 +5006,7 @@ ipa_prop_write_jump_functions (void) > lto_symtab_encoder_iterator lsei; > lto_symtab_encoder_t encoder; > > - > - if (!ipa_node_params_vector.exists ()) > + if (!ipa_node_params_annotation) > return; > > ob = create_output_block (LTO_section_jump_functions); > diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h > index 7a06af9..6a3772d 100644 > --- a/gcc/ipa-prop.h > +++ b/gcc/ipa-prop.h > @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see > #include "vec.h" > #include "cgraph.h" > #include "alloc-pool.h" > +#include "annotation.h" > > /* The following definitions and interfaces are used by > interprocedural analyses or parameters. */ > @@ -359,6 +360,8 @@ struct ipcp_lattice; > > struct ipa_node_params > { > + ~ipa_node_params (); > + > /* Information about individual formal parameters that are gathered when > summaries are generated. */ > vec descriptors; > @@ -473,7 +476,7 @@ struct GTY(()) ipa_agg_replacement_value > > typedef struct ipa_agg_replacement_value *ipa_agg_replacement_value_p; > > -void ipa_set_node_agg_value_chain (struct cgraph_node *node, > +void ipa_set_node_agg_value_chain (const struct cgraph_node *node, > struct ipa_agg_replacement_value *aggvals); > > /* ipa_edge_args stores information related to a callsite and particularly its > @@ -519,7 +522,7 @@ ipa_get_ith_polymorhic_call_context (struct ipa_edge_args *args, int i) > /* Types of vectors holding the infos. */ > > /* Vector where the parameter infos are actually stored. */ > -extern vec ipa_node_params_vector; > +extern cgraph_annotation *ipa_node_params_annotation; > /* Vector of known aggregate values in cloned nodes. */ > extern GTY(()) vec *ipa_node_agg_replacements; > /* Vector where the parameter infos are actually stored. */ > @@ -527,7 +530,7 @@ extern GTY(()) vec *ipa_edge_args_vector; > > /* Return the associated parameter/argument info corresponding to the given > node/edge. */ > -#define IPA_NODE_REF(NODE) (&ipa_node_params_vector[(NODE)->uid]) > +#define IPA_NODE_REF(NODE) (ipa_node_params_annotation->get_or_add (NODE)) > #define IPA_EDGE_REF(EDGE) (&(*ipa_edge_args_vector)[(EDGE)->uid]) > /* This macro checks validity of index returned by > ipa_get_param_decl_index function. */ > @@ -537,11 +540,15 @@ extern GTY(()) vec *ipa_edge_args_vector; > void ipa_create_all_node_params (void); > void ipa_create_all_edge_args (void); > void ipa_free_edge_args_substructures (struct ipa_edge_args *); > -void ipa_free_node_params_substructures (struct ipa_node_params *); > void ipa_free_all_node_params (void); > void ipa_free_all_edge_args (void); > void ipa_free_all_structures_after_ipa_cp (void); > void ipa_free_all_structures_after_iinln (void); > +void ipa_node_duplication_hook (const struct cgraph_node *src, > + const struct cgraph_node *dst, > + struct ipa_node_params *old_info, > + struct ipa_node_params *new_info); > + > void ipa_register_cgraph_hooks (void); > int count_formal_params (tree fndecl); > > @@ -551,11 +558,11 @@ int count_formal_params (tree fndecl); > static inline void > ipa_check_create_node_params (void) > { > - if (!ipa_node_params_vector.exists ()) > - ipa_node_params_vector.create (symtab->cgraph_max_uid); > - > - if (ipa_node_params_vector.length () <= (unsigned) symtab->cgraph_max_uid) > - ipa_node_params_vector.safe_grow_cleared (symtab->cgraph_max_uid + 1); > + if (!ipa_node_params_annotation) > + { > + ipa_node_params_annotation = new cgraph_annotation (symtab); > + ipa_node_params_annotation->add_duplication_hook (); > + } > } > > /* This function ensures the array of edge arguments infos is big enough to > @@ -582,7 +589,7 @@ ipa_edge_args_info_available_for_edge_p (struct cgraph_edge *edge) > /* Return the aggregate replacements for NODE, if there are any. */ > > static inline struct ipa_agg_replacement_value * > -ipa_get_agg_replacements_for_node (struct cgraph_node *node) > +ipa_get_agg_replacements_for_node (const struct cgraph_node *node) > { > if ((unsigned) node->uid >= vec_safe_length (ipa_node_agg_replacements)) > return NULL; > diff --git a/gcc/toplev.c b/gcc/toplev.c > index f7a5035..5e31ec2 100644 > --- a/gcc/toplev.c > +++ b/gcc/toplev.c > @@ -1176,7 +1176,7 @@ general_init (const char *argv0) > /* Create the singleton holder for global state. > Doing so also creates the pass manager and with it the passes. */ > g = new gcc::context (); > - symtab = ggc_cleared_alloc (); > + symtab = new (ggc_cleared_alloc ()) symbol_table (); > > statistics_early_init (); > finish_params ();