[trans-mem] expand transactions inside cloned functions

Aldy Hernandez aldyh@redhat.com
Thu May 6 19:14:00 GMT 2010


Howdy!

Cloned functions have an outermost transaction that encompasses the
entire function (see gate_tm_init()).  This outermost transaction has no
exit blocks, which causes execute_tm_edges() to skip expanding any
transactions therein.

The problem/ICE can be seen in either a recursive transaction call, or
while compiling a clone of a function which itself is transaction
callable.  See both tests below.

Fixed by looking in the inner transaction (the actual transaction) when
analyzing a clone.

OK for branch?

	* trans-mem.c (execute_tm_edges): Look for transactions inside
	cloned functions.

Index: testsuite/c-c++-common/tm/recurse.c
===================================================================
--- testsuite/c-c++-common/tm/recurse.c	(revision 0)
+++ testsuite/c-c++-common/tm/recurse.c	(revision 0)
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm" } */
+
+void foobar(void)
+{
+    __transaction {
+	foobar();
+    }
+}
+
+void doit(void) __attribute__((transaction_safe));
+
+__attribute__((transaction_callable))
+void callable(void)
+{
+  __transaction {
+    doit();
+  }
+}
Index: trans-mem.c
===================================================================
--- trans-mem.c	(revision 159008)
+++ trans-mem.c	(working copy)
@@ -2449,27 +2449,37 @@ expand_transaction (struct tm_region *re
 static unsigned int
 execute_tm_edges (void)
 {
-  struct tm_region *region;
+  struct tm_region *region, *r;
   VEC (basic_block, heap) *queue;
 
   for (region = all_tm_regions; region ; region = region->next)
-    if (region->exit_blocks)
-      {
-	unsigned int i;
-	basic_block bb;
+    {
+      /* If this is a clone, the outermost region is the entire
+	 transaction and has no exit block.  Look inside for the
+	 actual region.  */
+      if (region->transaction_stmt == NULL && region->inner&&0)
+	r = region->inner;
+      else
+	r = region;
 
-	/* Collect the set of blocks in this region.  Do this before
-	   splitting edges, so that we don't have to play with the
-	   dominator tree in the middle.  */
-	queue = get_tm_region_blocks (region->entry_block,
-				      region->exit_blocks,
-				      region->irr_blocks,
-				      /*stop_at_irr_p=*/false);
-	expand_transaction (region);
-	for (i = 0; VEC_iterate (basic_block, queue, i, bb); ++i)
-	  expand_block_edges (region, bb);
-	VEC_free (basic_block, heap, queue);
-      }
+      if (r->exit_blocks)
+	{
+	  unsigned int i;
+	  basic_block bb;
+
+	  /* Collect the set of blocks in this region.  Do this before
+	     splitting edges, so that we don't have to play with the
+	     dominator tree in the middle.  */
+	  queue = get_tm_region_blocks (r->entry_block,
+					r->exit_blocks,
+					r->irr_blocks,
+					/*stop_at_irr_p=*/false);
+	  expand_transaction (r);
+	  for (i = 0; VEC_iterate (basic_block, queue, i, bb); ++i)
+	    expand_block_edges (r, bb);
+	  VEC_free (basic_block, heap, queue);
+	}
+    }
   tm_log_delete ();
 
   /* We've got to release the dominance info now, to indicate that it



More information about the Gcc-patches mailing list