diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b769bf022e14..f5a242641a8c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2014-07-01 Martin Liska + + IPA REF alias refactoring + * 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_alias): New function. + (last_alias): Likewise. + (has_aliases_p): 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. + 2014-06-28 Jan Hubicka Revert: diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 43428be7bb42..41dcaf9e4a18 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2198,8 +2198,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; @@ -2210,16 +2209,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 (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 (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; } @@ -2233,21 +2232,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 (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 (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 0761e266a146..3ab051615e3b 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 d7e8038ec64e..f7980ed51151 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 (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 (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 81030f3a01a3..c4095ec9b4fd 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 (ref->referring)); + + FOR_EACH_ALIAS (where, ref) + reset_edge_caches (dyn_cast (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 (ref->referring); - update_caller_keys (heap, alias, updated_nodes, check_inlinablity_for); - } + FOR_EACH_ALIAS (node, ref) + { + struct cgraph_node *alias = dyn_cast (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 1be173a1b448..3c1001102bbf 100644 --- a/gcc/ipa-ref.c +++ b/gcc/ipa-ref.c @@ -38,12 +38,33 @@ ipa_ref::remove_reference () struct ipa_ref *last; gcc_assert (list->referring[referred_index] == this); + last = list->referring.last (); if (this != last) { + if (use == IPA_REF_ALIAS) + { + /* 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_alias (); + + if (last_alias && referred_index < last_alias->referred_index + && last_alias != last) + { + unsigned last_alias_index = last_alias->referred_index; + + list->referring[referred_index] = last_alias; + list->referring[referred_index]->referred_index = referred_index; + + /* New position for replacement is previous index + of the last_alias. */ + referred_index = last_alias_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 (); @@ -54,7 +75,7 @@ ipa_ref::remove_reference () if (ref != last) { *ref = *last; - referred_ref_list ()->referring[referred_index] = ref; + ref->referred_ref_list ()->referring[referred_index] = ref; } list2->references->pop (); gcc_assert (list2->references == old_references); diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h index d2de006b3ca5..b8b1f9e4216c 100644 --- a/gcc/ipa-ref.h +++ b/gcc/ipa-ref.h @@ -82,6 +82,32 @@ public: return referring[0]; } + /* Return first referring alias. */ + struct ipa_ref *first_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_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]; + } + + /* Return true if the symbol has an alias. */ + bool inline has_aliases_p (void) + { + return first_alias (); + } + /* Clear reference list. */ void clear (void) { diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 4a5d265c5ce7..78e32edaf95a 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,9 @@ +2014-07-01 Martin Liska + + IPA REF alias refactoring + * lto-partition.c (add_symbol_to_partition_1): Usage of + FOR_EACH_ALIAS added. + 2014-06-28 Jan Hubicka Revert: diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index 4d19ef6de614..944943cf1cc5 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 89591ee3ac71..80ea94abbd38 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 inserted 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 af8bc09e187f..12c0b3579b18 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 04ac87041880..79f07bfd2ff3 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 (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 (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 (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 (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; }