Atomic transactions marked as outer(-atomic) transactions can abort too
if they are calling functions whose type has the may_cancel_outer
attribute. Given that outer transactions are probably rare, this patch
just assumes that all outer transactions might abort irrespective of
whether they are actually calling may_cancel_outer functions.
Previously, there was no abort-handling code generated for outer
transactions, except if there was a __transaction_cancel in lexical
scope.

OK for branch?
commit 5ca679dfdc10038e6fe9bf9b3a73df5088d6cf21
Author: Torvald Riegel <trie...@redhat.com>
Date:   Fri Oct 28 17:01:25 2011 +0200

    Fix outer transactions to be considered abortable too.
    
        * trans-mem.c (lower_transaction): Also add an "over" laber for outer
        transactions.
        (expand_transactions): Do not set hasNoAbort for outer transactions.
        * testsuite/gcc.dg/tm/props-4.c: New file.

--- a/gcc/ChangeLog.tm
+++ b/gcc/ChangeLog.tm
@@ -1,3 +1,10 @@
+2011-10-28  Torvald Riegel  <trie...@redhat.com>
+
+       * trans-mem.c (lower_transaction): Also add an "over" laber for outer
+       transactions.
+       (expand_transactions): Do not set hasNoAbort for outer transactions.
+       * testsuite/gcc.dg/tm/props-4.c: New file.
+
 2011-10-27  Torvald Riegel  <trie...@redhat.com>
 
        * trans-mem.c (ipa_tm_transform_transaction): Insert explicit request
diff --git a/gcc/testsuite/gcc.dg/tm/props-4.c 
b/gcc/testsuite/gcc.dg/tm/props-4.c
new file mode 100644
index 0000000..c9d0c2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tm/props-4.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -fdump-tree-tmedge -fdump-tree-tmmark" } */
+
+int a, b;
+
+void __attribute((transaction_may_cancel_outer,noinline)) cancel1()
+{
+  __transaction_cancel [[outer]];
+}
+
+void
+foo(void)
+{
+  __transaction_atomic [[outer]] {
+    a = 2;
+    __transaction_atomic {
+      b = 2;
+      cancel1();
+    }
+  }
+}
+
+/* { dg-final { scan-tree-dump-times " instrumentedCode" 1 "tmedge" } } */
+/* { dg-final { scan-tree-dump-times "hasNoAbort" 0 "tmedge" } } */
+/* { dg-final { scan-tree-dump-times "LABEL=<L0>" 1 "tmmark" } } */
+/* { dg-final { cleanup-tree-dump "tmedge" } } */
+/* { dg-final { cleanup-tree-dump "tmmark" } } */
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 994cf09..bb98273 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -1603,8 +1603,10 @@ lower_transaction (gimple_stmt_iterator *gsi, struct 
walk_stmt_info *wi)
 
   gimple_transaction_set_body (stmt, NULL);
 
-  /* If the transaction calls abort, add an "over" label afterwards.  */
-  if (this_state & GTMA_HAVE_ABORT)
+  /* If the transaction calls abort or if this is an outer transaction,
+     add an "over" label afterwards.  */
+  if ((this_state & (GTMA_HAVE_ABORT))
+      || (gimple_transaction_subcode(stmt) & GTMA_IS_OUTER))
     {
       tree label = create_artificial_label (UNKNOWN_LOCATION);
       gimple_transaction_set_label (stmt, label);
@@ -2563,7 +2565,10 @@ expand_transaction (struct tm_region *region)
     flags = PR_INSTRUMENTEDCODE;
   if ((subcode & GTMA_MAY_ENTER_IRREVOCABLE) == 0)
     flags |= PR_HASNOIRREVOCABLE;
-  if ((subcode & GTMA_HAVE_ABORT) == 0)
+  /* If the transaction does not have an abort in lexical scope and is not
+     marked as an outer transaction, then it will never abort.  */
+  if ((subcode & GTMA_HAVE_ABORT) == 0
+      && (subcode & GTMA_IS_OUTER) == 0)
     flags |= PR_HASNOABORT;
   if ((subcode & GTMA_HAVE_STORE) == 0)
     flags |= PR_READONLY;

Reply via email to