On 07/09/2015 07:15 PM, Jeff Law wrote:
On 07/09/2015 03:13 AM, mliska wrote:
gcc/ChangeLog:
2015-07-03 Martin Liska <mli...@suse.cz>
* 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(-)
}
+
+ /* Destruction method that can be called for GGT purpose. */
GGT stands for?
Hi.
Should be 'GGC', fixed in attached patch.
Thanks,
Martin
OK for the trunk.
Thanks,
Jeff
>From 86a698b6fe9a0bbb55a0e2fa090d74cb02677d2f Mon Sep 17 00:00:00 2001
From: mliska <mli...@suse.cz>
Date: Thu, 9 Jul 2015 11:13:52 +0200
Subject: [PATCH 2/6] Introduce new edge_summary class and replace
ipa_edge_args_sum.
gcc/ChangeLog:
2015-07-03 Martin Liska <mli...@suse.cz>
* 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_transformation_summary, va_gc> *ipcp_transformations;
-/* Vector where the parameter infos are actually stored. */
-vec<ipa_edge_args, va_gc> *ipa_edge_args_vector;
+
+edge_summary <ipa_edge_args *> *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_transformation_summary, va_gc> *ipcp_transformations;
-/* Vector where the parameter infos are actually stored. */
-extern GTY(()) vec<ipa_edge_args, va_gc> *ipa_edge_args_vector;
+
+/* Function summary for ipa_node_params. */
+class GTY((user)) ipa_edge_args_t: public edge_summary <ipa_edge_args *>
+{
+public:
+ ipa_edge_args_t (symbol_table *symtab):
+ edge_summary <ipa_edge_args*> (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> ())
+ 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 *> *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..3e36dd8 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> ()) T() : new T () ;
+ return m_ggc ? new (ggc_alloc <T> ()) T () : new T () ;
}
/* Release an item that is stored within map. */
@@ -234,7 +234,7 @@ private:
template <typename T>
void
-gt_ggc_mx(function_summary<T *>* const &summary)
+gt_ggc_mx (function_summary<T *>* const &summary)
{
gcc_checking_assert (summary->m_ggc);
gt_ggc_mx (&summary->m_map);
@@ -242,7 +242,7 @@ gt_ggc_mx(function_summary<T *>* const &summary)
template <typename T>
void
-gt_pch_nx(function_summary<T *>* const &summary)
+gt_pch_nx (function_summary<T *>* const &summary)
{
gcc_checking_assert (summary->m_ggc);
gt_pch_nx (&summary->m_map);
@@ -250,11 +250,211 @@ gt_pch_nx(function_summary<T *>* const &summary)
template <typename T>
void
-gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
+gt_pch_nx (function_summary<T *>* 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 T>
+class edge_summary
+{
+private:
+ edge_summary ();
+};
+
+template <class T>
+class GTY((user)) edge_summary <T *>
+{
+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 GGC 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 <map_hash, T *>::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<typename Arg, bool (*f)(const T &, Arg)>
+ void traverse (Arg a) const
+ {
+ m_map.traverse <f> (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> ()) 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 <T *> *) (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 <T *> *) (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 <int, 0, -1> map_hash;
+
+ /* Main summary store, where summary ID is used as key. */
+ hash_map <map_hash, T *> 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 <typename U> friend void gt_ggc_mx (edge_summary <U *> * const &);
+ template <typename U> friend void gt_pch_nx (edge_summary <U *> * const &);
+ template <typename U> friend void gt_pch_nx (edge_summary <U *> * const &,
+ gt_pointer_operator, void *);
+};
+
+template <typename T>
+void
+gt_ggc_mx (edge_summary<T *>* const &summary)
+{
+ gcc_checking_assert (summary->m_ggc);
+ gt_ggc_mx (&summary->m_map);
+}
+
+template <typename T>
+void
+gt_pch_nx (edge_summary<T *>* const &summary)
+{
+ gcc_checking_assert (summary->m_ggc);
+ gt_pch_nx (&summary->m_map);
+}
+
+template <typename T>
+void
+gt_pch_nx (edge_summary<T *>* 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 */
--
2.4.5