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;
 }

Reply via email to