diff mbox

IPA REF: alias refactoring

Message ID 53B1D3E7.30508@suse.cz
State New
Headers show

Commit Message

Martin Liška June 30, 2014, 9:17 p.m. UTC
On 06/28/2014 08:49 AM, Jan Hubicka wrote:
>> 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.
> I missed it last time around, I think first_alias/last_alias are better names.
> first_alias is unused. If you added it I guess FOR_EACH_ALIAS should use it.

Hello,
    I renamed these functions as you suggested and has_aliases_p 
predication was also added.
Previous patch has an error in ipa_ref::remove_refence, this patch has 
been regtested and the problem is removed.

>
> We probably also can bring has_aliases_p inline and implement it using
> first_referring_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_referring_alias ();
> You can avoid walking to last alias when the removed item is not IPA_REF_ALIAS.
>
>> +
>> +  /* IPA_REF_ALIAS is always put at the beginning of the list.   */
> inserted?
Type fixed.

If no other comments will come, I consider the patch as preapproved.

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_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.

gcc/lto/ChangeLog:

     * lto-partition.c (add_symbol_to_partition_1): Usage of
     FOR_EACH_ALIAS added.

>
> OK with these changes (or if you already comitted, just do them incrementally)
>
> Honza

Comments

Jan Hubicka June 30, 2014, 10:21 p.m. UTC | #1
> 
> 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_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.
> 
> gcc/lto/ChangeLog:
> 
>     * lto-partition.c (add_symbol_to_partition_1): Usage of
>     FOR_EACH_ALIAS added.

OK, thanks!

Honza
Martin Liška July 1, 2014, 6:48 a.m. UTC | #2
On 07/01/2014 12:21 AM, Jan Hubicka wrote:
>> 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_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.
>>
>> gcc/lto/ChangeLog:
>>
>>      * lto-partition.c (add_symbol_to_partition_1): Usage of
>>      FOR_EACH_ALIAS added.
> OK, thanks!
>
> Honza
Thanks,
patch has been just commited.

Martin
diff mbox

Patch

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 43428be..41dcaf9 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 <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;
 }
 
@@ -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 <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 d7e8038..f7980ed 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..3c10011 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 d2de006..b8b1f9e 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/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..80ea94a 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 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;
 }