Without this patch, transaction commits of different transactions get
potentially merged, which breaks how we handle transactional regions.
Patch provided by Richard Henderson.

OK for trunk?
commit 48d236d4c40fdb7111308fe88844068603e235eb
Author: Torvald Riegel <trie...@redhat.com>
Date:   Thu Dec 8 11:57:05 2011 +0100

    Prevent sharing of commit calls among transactions.
    
        gcc/
        * tree-ssa-tail-merge.c (gimple_equal_p): Don't treat transaction
        commits as equal.
    
        gcc/testsuite/
        * c-c++-common/tm/20111206.c: New test.

diff --git a/gcc/testsuite/c-c++-common/tm/20111206.c 
b/gcc/testsuite/c-c++-common/tm/20111206.c
new file mode 100644
index 0000000..74a5519
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/tm/20111206.c
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-fgnu-tm -O2" } */
+/* This test case triggered block sharing between the two transactions.  */
+
+void func1 (void) __attribute__ ((transaction_callable, used));
+long func2 (void) __attribute__ ((transaction_callable, used));
+unsigned long rand (void);
+
+void client_run (void)
+{
+  long types[100];
+  long i;
+
+  for (i = 0; i < 100; i++)
+    {
+      long action = rand ();
+
+      switch (action)
+       {
+       case 0:
+         {
+           __transaction_relaxed
+           {
+             long bill = func2 ();
+             if (bill >= 0)
+               {
+                 func1 ();
+               }
+           }
+           break;
+         }
+
+       case 1:
+         {
+           long n;
+           __transaction_relaxed
+           {
+             for (n = 0; n < 100; n++)
+               {
+                 long t = types[n];
+                 switch (t)
+                   {
+                   case 0:
+                     func1 ();
+                     break;
+                   }
+               }
+           }
+           break;
+         }
+       }
+    }
+}
diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c
index a501b07..7452266 100644
--- a/gcc/tree-ssa-tail-merge.c
+++ b/gcc/tree-ssa-tail-merge.c
@@ -1051,6 +1051,14 @@ gimple_equal_p (same_succ same_succ, gimple s1, gimple 
s2)
       if (!gimple_call_same_target_p (s1, s2))
         return false;
 
+      /* Eventually, we'll significantly complicate the CFG by adding
+        back edges to properly model the effects of transaction restart.
+        For the bulk of optimization this does not matter, but what we
+        cannot recover from is tail merging blocks between two separate
+        transactions.  Avoid that by making commit not match.  */
+      if (gimple_call_builtin_p (s1, BUILT_IN_TM_COMMIT))
+       return false;
+
       equal = true;
       for (i = 0; i < gimple_call_num_args (s1); ++i)
        {

Reply via email to