This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC, PATCH]: Introduction of callgraph annotation class


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> 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<cgraph_unique_identifier, T>.
Every time a node is deleted, we remove corresponding data associated to the node.

What do you think about it?

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
+<http://www.gnu.org/licenses/>.  */
+
+#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<typename T>
+  static inline
+  bool is_deleted (T &e)
+  {
+    return e.m_key == ANNOTATION_DELETED_VALUE;
+  }
+
+  template<typename T>
+  static inline
+  bool is_empty (T &e)
+  {
+    return e.m_key == ANNOTATION_EMPTY_VALUE;
+  }
+
+  template<typename T>
+  static inline
+  void mark_deleted (T &e)
+  {
+    e.m_key = ANNOTATION_DELETED_VALUE;
+  }
+
+  template<typename T>
+  static inline
+  void mark_empty (T &e)
+  {
+    e.m_key = ANNOTATION_EMPTY_VALUE;
+  }
+};
+
+template <class T>
+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<int, T*, annotation_hashmap_traits>();
+
+    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 <void *, cgraph_annotation::release> (NULL);
+  }
+
+  /* Traverses all annotations with a function F called with
+     ARG as argument.  */
+  template<typename Arg, bool (*f)(const T &, Arg)>
+  void traverse (Arg a) const
+  {
+    m_map->traverse <f> (a);
+  }
+
+  /* Function for registering insertion hook.  */
+  template <void (*f) (const cgraph_node *, T *)>
+  inline void add_insertion_hook (void)
+  {
+    m_insertion_hooks.safe_push (f);
+  }
+
+  /* Function for registering removal hook.  */
+  template <void (*f) (const cgraph_node *, T *)>
+  inline void add_removal_hook (void)
+  {
+    m_removal_hooks.safe_push (f);
+  }
+
+  /* Function for registering duplication hook.  */
+  template <void (*f) (const cgraph_node *, const cgraph_node *, T *, T *)>
+  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 <T> *) (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 <T> *) (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 <T> *) (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 <int, T *, annotation_hashmap_traits> *m_map;
+
+  /* Inverse mapping structure used in cgraph deletion context.  */
+  hash_map <cgraph_node *, int> 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 <void (*) (cgraph_node *, T *)> m_insertion_hooks;
+  /* List of symbol removal hooks.  */
+  auto_vec <void (*) (cgraph_node *, T *)> m_removal_hooks;
+  /* List of symbol duplication hooks.  */
+  auto_vec <void (*) (const cgraph_node *, const cgraph_node *, T *, T *)>
+  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<size_time_entry, va_gc> *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 <struct ipa_node_params> *ipa_node_params_annotation = NULL;
 vec<ipa_node_params> ipa_node_params_vector;
 /* Vector of known aggregate values in cloned nodes.  */
 vec<ipa_agg_replacement_value_p, va_gc> *ipa_node_agg_replacements;
@@ -124,9 +125,7 @@ vec<ipa_edge_args, va_gc> *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<ipa_param_descriptor> 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> ipa_node_params_vector;
+extern cgraph_annotation <ipa_node_params> *ipa_node_params_annotation;
 /* Vector of known aggregate values in cloned nodes.  */
 extern GTY(()) vec<ipa_agg_replacement_value_p, va_gc> *ipa_node_agg_replacements;
 /* Vector where the parameter infos are actually stored. */
@@ -527,7 +530,7 @@ extern GTY(()) vec<ipa_edge_args, va_gc> *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, va_gc> *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 <ipa_node_params> (symtab);
+      ipa_node_params_annotation->add_duplication_hook <ipa_node_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 <symbol_table> ();
+  symtab = new (ggc_cleared_alloc <symbol_table> ()) symbol_table ();
 
   statistics_early_init ();
   finish_params ();

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