This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] IPA REF: alias refactoring
- From: Martin Liška <mliska at suse dot cz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 27 Jun 2014 12:05:47 +0200
- Subject: [PATCH] IPA REF: alias refactoring
- Authentication-results: sourceware.org; auth=none
Hi,
this patch enhances alias manipulation for symtab_node. Honza suggested following changes.
Patch is pre approved, will be committed if no comments and regressions.
Bootstrapped on x86_64-pc-linux-gnu, regression tests have been running.
Thanks,
Martin
gcc/ChangeLog:
* cgraph.h (iterate_direct_aliases): New function.
(FOR_EACH_ALIAS): New macro iterates all direct aliases for a node.
* cgraph.c (cgraph_for_node_thunks_and_aliases): Usage of
FOR_EACH_ALIAS added.
(cgraph_for_node_and_aliases): Likewise.
* cgraphunit.c (assemble_thunks_and_aliases): Likewise.
* ipa-inline.c (reset_edge_caches): Likewise.
(update_caller_keys): Likewise.
* trans-mem.c (ipa_tm_execute): Likewise.
*varpool.c (varpool_analyze_node): Likewise.
(varpool_for_node_and_aliases): Likewise.
* ipa-ref.h (first_referring_alias): New function.
(last_referring_alias): Likewise.
* ipa-ref.c (ipa_ref::remove_reference): Removal function
is sensitive to IPA_REF_ALIASes.
* symtab.c (symtab_node::add_reference): Node of IPA_REF_ALIAS type
are put at the beginning of the list.
(symtab_node::iterate_direct_aliases): New function.
gcc/lto/ChangeLog:
* lto-partition.c (add_symbol_to_partition_1): Usage of
FOR_EACH_ALIAS added.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 7360f77..568eb45 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2194,8 +2194,7 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
bool include_overwritable)
{
struct cgraph_edge *e;
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
if (callback (node, data))
return true;
@@ -2206,16 +2205,16 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node,
if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data,
include_overwritable))
return true;
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- if (include_overwritable
- || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
- if (cgraph_for_node_thunks_and_aliases (alias, callback, data,
- include_overwritable))
- return true;
- }
+
+ FOR_EACH_ALIAS (node, ref)
+ {
+ struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ if (include_overwritable
+ || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
+ if (cgraph_for_node_thunks_and_aliases (alias, callback, data,
+ include_overwritable))
+ return true;
+ }
return false;
}
@@ -2229,21 +2228,20 @@ cgraph_for_node_and_aliases (struct cgraph_node *node,
void *data,
bool include_overwritable)
{
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
if (callback (node, data))
return true;
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- if (include_overwritable
- || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
- if (cgraph_for_node_and_aliases (alias, callback, data,
- include_overwritable))
- return true;
- }
+
+ FOR_EACH_ALIAS (node, ref)
+ {
+ struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ if (include_overwritable
+ || cgraph_function_body_availability (alias) > AVAIL_OVERWRITABLE)
+ if (cgraph_for_node_and_aliases (alias, callback, data,
+ include_overwritable))
+ return true;
+ }
return false;
}
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0761e26..3ab0516 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -254,6 +254,9 @@ public:
/* Iterates I-th referring item in the list, REF is also set. */
struct ipa_ref *iterate_referring (unsigned i, struct ipa_ref *&ref);
+ /* Iterates I-th referring alias item in the list, REF is also set. */
+ struct ipa_ref *iterate_direct_aliases (unsigned i, struct ipa_ref *&ref);
+
/* Vectors of referring and referenced entities. */
struct ipa_ref_list ref_list;
@@ -281,6 +284,10 @@ public:
priority_type get_init_priority ();
};
+/* Walk all aliases for NODE. */
+#define FOR_EACH_ALIAS(node, alias) \
+ for (unsigned x_i = 0; node->iterate_direct_aliases (x_i, alias); x_i++)
+
enum availability
{
/* Not yet set by cgraph_function_body_availability. */
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 76b2fda1..b0478cb 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1711,8 +1711,7 @@ static void
assemble_thunks_and_aliases (struct cgraph_node *node)
{
struct cgraph_edge *e;
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
for (e = node->callers; e;)
if (e->caller->thunk.thunk_p)
@@ -1725,20 +1724,20 @@ assemble_thunks_and_aliases (struct cgraph_node *node)
}
else
e = e->next_caller;
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- bool saved_written = TREE_ASM_WRITTEN (node->decl);
-
- /* Force assemble_alias to really output the alias this time instead
- of buffering it in same alias pairs. */
- TREE_ASM_WRITTEN (node->decl) = 1;
- do_assemble_alias (alias->decl,
- DECL_ASSEMBLER_NAME (node->decl));
- assemble_thunks_and_aliases (alias);
- TREE_ASM_WRITTEN (node->decl) = saved_written;
- }
+
+ FOR_EACH_ALIAS (node, ref)
+ {
+ struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ bool saved_written = TREE_ASM_WRITTEN (node->decl);
+
+ /* Force assemble_alias to really output the alias this time instead
+ of buffering it in same alias pairs. */
+ TREE_ASM_WRITTEN (node->decl) = 1;
+ do_assemble_alias (alias->decl,
+ DECL_ASSEMBLER_NAME (node->decl));
+ assemble_thunks_and_aliases (alias);
+ TREE_ASM_WRITTEN (node->decl) = saved_written;
+ }
}
/* Expand function specified by NODE. */
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 81030f3..c4095ec 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1119,8 +1119,7 @@ reset_edge_caches (struct cgraph_node *node)
struct cgraph_edge *edge;
struct cgraph_edge *e = node->callees;
struct cgraph_node *where = node;
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
if (where->global.inlined_to)
where = where->global.inlined_to;
@@ -1131,9 +1130,9 @@ reset_edge_caches (struct cgraph_node *node)
for (edge = where->callers; edge; edge = edge->next_caller)
if (edge->inline_failed)
reset_edge_growth_cache (edge);
- for (i = 0; where->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- reset_edge_caches (dyn_cast <cgraph_node *> (ref->referring));
+
+ FOR_EACH_ALIAS (where, ref)
+ reset_edge_caches (dyn_cast <cgraph_node *> (ref->referring));
if (!e)
return;
@@ -1172,8 +1171,7 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
struct cgraph_edge *check_inlinablity_for)
{
struct cgraph_edge *edge;
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
if ((!node->alias && !inline_summary (node)->inlinable)
|| node->global.inlined_to)
@@ -1181,12 +1179,11 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
if (!bitmap_set_bit (updated_nodes, node->uid))
return;
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- update_caller_keys (heap, alias, updated_nodes, check_inlinablity_for);
- }
+ FOR_EACH_ALIAS (node, ref)
+ {
+ struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ update_caller_keys (heap, alias, updated_nodes, check_inlinablity_for);
+ }
for (edge = node->callers; edge; edge = edge->next_caller)
if (edge->inline_failed)
diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c
index 1be173a..8df6b81 100644
--- a/gcc/ipa-ref.c
+++ b/gcc/ipa-ref.c
@@ -38,12 +38,23 @@ ipa_ref::remove_reference ()
struct ipa_ref *last;
gcc_assert (list->referring[referred_index] == this);
+
last = list->referring.last ();
if (this != last)
{
+ /* If deleted item is IPA_REF_ALIAS, we have to move last
+ item of IPA_REF_LIST type to the deleted position. After that
+ we replace last node with deletion slot. */
+ struct ipa_ref *last_alias = list->last_referring_alias ();
+
+ if (last_alias && referred_index < last_alias->referred_index)
+ {
+ list->referring[referred_index] = last_alias;
+ list->referring[referred_index]->referred_index = referred_index;
+ }
+
list->referring[referred_index] = list->referring.last ();
- list->referring[referred_index]->referred_index
- = referred_index;
+ list->referring[referred_index]->referred_index= referred_index;
}
list->referring.pop ();
diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
index d2de006..65f1f30 100644
--- a/gcc/ipa-ref.h
+++ b/gcc/ipa-ref.h
@@ -82,6 +82,26 @@ public:
return referring[0];
}
+ /* Return first referring alias. */
+ struct ipa_ref *first_referring_alias (void)
+ {
+ struct ipa_ref *r = first_referring ();
+
+ return r && r->use == IPA_REF_ALIAS ? r : NULL;
+ }
+
+ /* Return last referring alias. */
+ struct ipa_ref *last_referring_alias (void)
+ {
+ unsigned int i = 0;
+
+ for(i = 0; i < referring.length (); i++)
+ if (referring[i]->use != IPA_REF_ALIAS)
+ break;
+
+ return i == 0 ? NULL : referring[i - 1];
+ }
+
/* Clear reference list. */
void clear (void)
{
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 4d19ef6..944943c 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -113,8 +113,7 @@ static bool
add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
{
enum symbol_partitioning_class c = symtab_get_symbol_partitioning_class (node);
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
symtab_node *node1;
/* If NODE is already there, we have nothing to do. */
@@ -168,8 +167,9 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node)
add_references_to_partition (part, node);
/* Add all aliases associated with the symbol. */
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS && !node->weakref)
+
+ FOR_EACH_ALIAS (node, ref)
+ if (!node->weakref)
add_symbol_to_partition_1 (part, ref->referring);
/* Ensure that SAME_COMDAT_GROUP lists all allways added in a group. */
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 89591ee..fd83604 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -558,8 +558,22 @@ symtab_node::add_reference (symtab_node *referred_node,
ref = &list->references->last ();
list2 = &referred_node->ref_list;
- list2->referring.safe_push (ref);
- ref->referred_index = list2->referring.length () - 1;
+
+ /* IPA_REF_ALIAS is always put 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;
+ }
+ else
+ {
+ list2->referring.safe_push (ref);
+ ref->referred_index = list2->referring.length () - 1;
+ }
+
ref->referring = this;
ref->referred = referred_node;
ref->stmt = stmt;
@@ -796,6 +810,20 @@ symtab_node::iterate_referring (unsigned i, struct ipa_ref *&ref)
return ref;
}
+/* Iterates I-th referring alias item in the list, REF is also set. */
+
+struct ipa_ref *
+symtab_node::iterate_direct_aliases (unsigned i, struct 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. Not to be used directly. */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index af8bc09..12c0b35 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -5439,8 +5439,7 @@ ipa_tm_execute (void)
{
struct cgraph_node *caller;
struct cgraph_edge *e;
- struct ipa_ref *ref = NULL;
- unsigned j;
+ struct ipa_ref *ref;
if (i > 256 && i == irr_worklist.length () / 8)
{
@@ -5466,11 +5465,10 @@ ipa_tm_execute (void)
}
/* Propagate back to referring aliases as well. */
- for (j = 0; node->iterate_referring (j, ref); j++)
+ FOR_EACH_ALIAS (node, ref)
{
caller = cgraph (ref->referring);
- if (ref->use == IPA_REF_ALIAS
- && !caller->local.tm_may_enter_irr)
+ if (!caller->local.tm_may_enter_irr)
{
/* ?? Do not traverse aliases here. */
d = get_cg_data (&caller, false);
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 04ac870..79f07bf 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -424,17 +424,15 @@ varpool_analyze_node (varpool_node *node)
static void
assemble_aliases (varpool_node *node)
{
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
- do_assemble_alias (alias->decl,
- DECL_ASSEMBLER_NAME (node->decl));
- assemble_aliases (alias);
- }
+ FOR_EACH_ALIAS (node, ref)
+ {
+ varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
+ do_assemble_alias (alias->decl,
+ DECL_ASSEMBLER_NAME (node->decl));
+ assemble_aliases (alias);
+ }
}
/* Output one variable, if necessary. Return whether we output it. */
@@ -694,20 +692,19 @@ varpool_for_node_and_aliases (varpool_node *node,
void *data,
bool include_overwritable)
{
- int i;
- struct ipa_ref *ref = NULL;
+ struct ipa_ref *ref;
if (callback (node, data))
return true;
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
- if (include_overwritable
- || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE)
- if (varpool_for_node_and_aliases (alias, callback, data,
- include_overwritable))
- return true;
- }
+
+ FOR_EACH_ALIAS (node, ref)
+ {
+ varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
+ if (include_overwritable
+ || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE)
+ if (varpool_for_node_and_aliases (alias, callback, data,
+ include_overwritable))
+ return true;
+ }
return false;
}