Patchwork [trans-mem,2/3] Update to handle same_body_aliases.

login
register
mail settings
Submitter Richard Henderson
Date Oct. 28, 2011, 11:30 p.m.
Message ID <1319844656-1558-2-git-send-email-rth@redhat.com>
Download mbox | patch
Permalink /patch/122514/
State New
Headers show

Comments

Richard Henderson - Oct. 28, 2011, 11:30 p.m.
* trans-mem.c (ipa_tm_mayenterirr_function): Recurse for aliases.
        (ipa_tm_mark_needed_node): Split out of callback_mark_needed.
        (ipa_tm_create_version_alias): Rename from callback_mark_needed.
        Handle comdat groups properly.
        (ipa_tm_create_version): Use ipa_tm_mark_needed_node.
        (ipa_tm_execute): Queue the base of an alias.  Propagate irrevokable
        backward across alias references.  Don't clone aliases directly.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/transactional-memory@180636 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog.tm |    8 +++
 gcc/trans-mem.c  |  148 ++++++++++++++++++++++++++++++++++++++----------------
 2 files changed, 113 insertions(+), 43 deletions(-)

Patch

diff --git a/gcc/ChangeLog.tm b/gcc/ChangeLog.tm
index b63f6f0..dfdf9ee 100644
--- a/gcc/ChangeLog.tm
+++ b/gcc/ChangeLog.tm
@@ -1,5 +1,13 @@ 
 2011-10-28  Richard Henderson  <rth@redhat.com>
 
+	* trans-mem.c (ipa_tm_mayenterirr_function): Recurse for aliases.
+	(ipa_tm_mark_needed_node): Split out of callback_mark_needed.
+	(ipa_tm_create_version_alias): Rename from callback_mark_needed.
+	Handle comdat groups properly.
+	(ipa_tm_create_version): Use ipa_tm_mark_needed_node.
+	(ipa_tm_execute): Queue the base of an alias.  Propagate irrevokable
+	backward across alias references.  Don't clone aliases directly.
+
 	* trans-mem.c (struct tm_ipa_cg_data): Add transaction_blocks_normal.
 	(bb_in_TM_region): Remove.
 	(ipa_tm_scan_calls_block): New.
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 332fb1b..d0b984c 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -3967,6 +3967,12 @@  ipa_tm_mayenterirr_function (struct cgraph_node *node)
   if (node->local.tm_may_enter_irr)
     return true;
 
+  /* Recurse on the main body for aliases.  In general, this will
+     result in one of the bits above being set so that we will not
+     have to recurse next time.  */
+  if (node->alias)
+    return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias));
+
   /* What remains is unmarked local functions without items that force
      the function to go irrevocable.  */
   return false;
@@ -4120,50 +4126,70 @@  tm_mangle (tree old_asm_id)
   return new_asm_id;
 }
 
-/* Callback data for callback_mark_needed.  */
-struct mark_needed_info
+static inline void
+ipa_tm_mark_needed_node (struct cgraph_node *node)
+{
+  cgraph_mark_needed_node (node);
+  /* ??? function_and_variable_visibility will reset
+     the needed bit, without actually checking.  */
+  node->analyzed = 1;
+}
+
+/* Callback data for ipa_tm_create_version_alias.  */
+struct create_version_alias_info
 {
   struct cgraph_node *old_node;
   tree new_decl;
 };
 
+/* A subrontine of ipa_tm_create_version, called via
+   cgraph_for_node_and_aliases.  Create new tm clones for each of
+   the existing aliases.  */
 static bool
-callback_mark_needed (struct cgraph_node *node, void *data)
+ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
 {
-  struct mark_needed_info *info = (struct mark_needed_info *)data;
-  if (node->alias || node->thunk.thunk_p)
-    {
-      tree tm_name = tm_mangle (DECL_ASSEMBLER_NAME (node->decl));
-      tree tm_alias = build_decl (DECL_SOURCE_LOCATION (node->decl),
-				  TREE_CODE (node->decl), tm_name,
-				  TREE_TYPE (node->decl));
+  struct create_version_alias_info *info
+    = (struct create_version_alias_info *)data;
+  tree old_decl, new_decl, tm_name;
+  struct cgraph_node *new_node;
 
-      SET_DECL_ASSEMBLER_NAME (tm_alias, tm_name);
-      SET_DECL_RTL (tm_alias, NULL);
+  if (!node->same_body_alias)
+    return false;
 
-      /* Based loosely on C++'s make_alias_for().  */
-      TREE_PUBLIC (tm_alias) = TREE_PUBLIC (node->decl);
-      DECL_CONTEXT (tm_alias) = NULL;
-      TREE_READONLY (tm_alias) = TREE_READONLY (node->decl);
-      DECL_EXTERNAL (tm_alias) = 0;
-      DECL_ARTIFICIAL (tm_alias) = 1;
-      TREE_ADDRESSABLE (tm_alias) = 1;
-      TREE_USED (tm_alias) = 1;
-      TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tm_alias)) = 1;
+  old_decl = node->decl;
+  tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl));
+  new_decl = build_decl (DECL_SOURCE_LOCATION (old_decl),
+			 TREE_CODE (old_decl), tm_name,
+			 TREE_TYPE (old_decl));
 
-      cgraph_same_body_alias (NULL, tm_alias, info->new_decl);
+  SET_DECL_ASSEMBLER_NAME (new_decl, tm_name);
+  SET_DECL_RTL (new_decl, NULL);
 
-      record_tm_clone_pair (node->decl, tm_alias);
+  /* Based loosely on C++'s make_alias_for().  */
+  TREE_PUBLIC (new_decl) = TREE_PUBLIC (old_decl);
+  DECL_CONTEXT (new_decl) = NULL;
+  TREE_READONLY (new_decl) = TREE_READONLY (old_decl);
+  DECL_EXTERNAL (new_decl) = 0;
+  DECL_ARTIFICIAL (new_decl) = 1;
+  TREE_ADDRESSABLE (new_decl) = 1;
+  TREE_USED (new_decl) = 1;
+  TREE_SYMBOL_REFERENCED (tm_name) = 1;
 
-      if (info->old_node->needed)
-	{
-	  struct cgraph_node *alias = cgraph_get_node (tm_alias);
-	  cgraph_mark_needed_node (alias);
-	  /* Needed so function_and_variable_visibility() won't reset
-	     the needed bit.  */
-	  alias->analyzed = 1;
-	}
-    }
+  /* Perform the same remapping to the comdat group.  */
+  if (DECL_COMDAT (new_decl))
+    DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl));
+
+  /* ??? We should be able to remove DECL_IS_TM_CLONE.  We have enough
+     bits in cgraph to calculate all this.  */
+  DECL_IS_TM_CLONE (new_decl) = 1;
+
+  new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl);
+  get_cg_data (node)->clone = new_node;
+
+  record_tm_clone_pair (old_decl, new_decl);
+
+  if (info->old_node->needed)
+    ipa_tm_mark_needed_node (new_node);
   return false;
 }
 
@@ -4185,11 +4211,16 @@  ipa_tm_create_version (struct cgraph_node *old_node)
   tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl));
   SET_DECL_ASSEMBLER_NAME (new_decl, tm_name);
   SET_DECL_RTL (new_decl, NULL);
+  TREE_SYMBOL_REFERENCED (tm_name) = 1;
 
   /* Perform the same remapping to the comdat group.  */
   if (DECL_COMDAT (new_decl))
     DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl));
 
+  /* ??? We should be able to remove DECL_IS_TM_CLONE.  We have enough
+     bits in cgraph to calculate all this.  */
+  DECL_IS_TM_CLONE (new_decl) = 1;
+
   new_node = cgraph_copy_node_for_versioning (old_node, new_decl, NULL, NULL);
   get_cg_data (old_node)->clone = new_node;
 
@@ -4207,22 +4238,19 @@  ipa_tm_create_version (struct cgraph_node *old_node)
 				NULL, NULL);
     }
 
-  /* ?? We should be able to remove DECL_IS_TM_CLONE.  We have enough
-     bits in cgraph to calculate all this.  */
-  DECL_IS_TM_CLONE (new_decl) = 1;
-
   record_tm_clone_pair (old_decl, new_decl);
 
   cgraph_call_function_insertion_hooks (new_node);
   if (old_node->needed)
-    cgraph_mark_needed_node (new_node);
+    ipa_tm_mark_needed_node (new_node);
 
   /* Do the same thing, but for any aliases of the original node.  */
   {
-    struct mark_needed_info data;
+    struct create_version_alias_info data;
     data.old_node = old_node;
     data.new_decl = new_decl;
-    cgraph_for_node_and_aliases (old_node, callback_mark_needed, &data, true);
+    cgraph_for_node_and_aliases (old_node, ipa_tm_create_version_alias,
+				 &data, true);
   }
 }
 
@@ -4600,7 +4628,6 @@  ipa_tm_execute (void)
   /* For all local functions marked tm_callable, queue them.  */
   for (node = cgraph_nodes; node; node = node->next)
     if (is_tm_callable (node->decl)
-	&& !node->alias
 	&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
       {
 	d = get_cg_data (node);
@@ -4676,6 +4703,16 @@  ipa_tm_execute (void)
 	    ipa_tm_note_irrevocable (node, &irr_worklist);
 	  else if (!d->is_irrevocable)
 	    {
+	      /* If this is an alias, make sure its base is queued as well.
+		 we need not scan the callees now, as the base will do.  */
+	      if (node->alias)
+		{
+		  node = cgraph_get_node (node->thunk.alias);
+		  d = get_cg_data (node);
+		  maybe_push_queue (node, &tm_callees, &d->in_callee_queue);
+		  continue;
+		}
+
 	      /* Add all nodes called by this function into
 		 tm_callees as well.  */
 	      ipa_tm_scan_calls_clone (node, &tm_callees);
@@ -4726,7 +4763,10 @@  ipa_tm_execute (void)
   /* Propagate the tm_may_enter_irr bit to callers until stable.  */
   for (i = 0; i < VEC_length (cgraph_node_p, irr_worklist); ++i)
     {
+      struct cgraph_node *caller;
       struct cgraph_edge *e;
+      struct ipa_ref *ref;
+      unsigned j;
 
       if (i > 256 && i == VEC_length (cgraph_node_p, irr_worklist) / 8)
 	{
@@ -4739,10 +4779,29 @@  ipa_tm_execute (void)
       d->in_worklist = false;
       node->local.tm_may_enter_irr = true;
 
+      /* Propagate back to normal callers.  */
       for (e = node->callers; e ; e = e->next_caller)
-	if (!is_tm_safe_or_pure (e->caller->decl)
-	    && !e->caller->local.tm_may_enter_irr)
-	  maybe_push_queue (e->caller, &irr_worklist, &d->in_worklist);
+	{
+	  caller = e->caller;
+	  if (!is_tm_safe_or_pure (caller->decl)
+	      && !caller->local.tm_may_enter_irr)
+	    {
+	      d = get_cg_data (caller);
+	      maybe_push_queue (caller, &irr_worklist, &d->in_worklist);
+	    }
+	}
+
+      /* Propagate back to referring aliases as well.  */
+      for (j = 0; ipa_ref_list_refering_iterate (&node->ref_list, j, ref); j++)
+	{
+	  caller = ref->refering.cgraph_node;
+	  if (ref->use == IPA_REF_ALIAS
+	      && !caller->local.tm_may_enter_irr)
+	    {
+	      d = get_cg_data (caller);
+	      maybe_push_queue (caller, &irr_worklist, &d->in_worklist);
+	    }
+	}
     }
 
   /* Now validate all tm_safe functions, and all atomic regions in
@@ -4766,6 +4825,9 @@  ipa_tm_execute (void)
       bool doit = false;
 
       node = VEC_index (cgraph_node_p, tm_callees, i);
+      if (node->same_body_alias)
+	continue;
+
       a = cgraph_function_body_availability (node);
       d = get_cg_data (node);