From patchwork Sat Dec 10 20:20:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Prevent sharing of commit calls among transactions. Date: Sat, 10 Dec 2011 10:20:37 -0000 From: Torvald Riegel X-Patchwork-Id: 130562 Message-Id: <1323548437.4159.6975.camel@triegel.csb> To: GCC Patches Cc: Richard Henderson , Aldy Hernandez 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 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) {