From a3770d3b7d86f1be758db337631be9b52530c173 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Wed, 17 Oct 2012 21:18:16 +0000 Subject: [PATCH] re PR middle-end/54893 (unable to access volatile variable within relaxed transaction) PR middle-end/54893 * trans-mem.c (diagnose_tm_1_op): Allow volatiles inside relaxed transactions. From-SVN: r192549 --- gcc/ChangeLog | 6 ++ gcc/testsuite/c-c++-common/tm/pr54893.c | 16 +++++ gcc/trans-mem.c | 93 +++++++++++++++---------- 3 files changed, 79 insertions(+), 36 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/tm/pr54893.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9c6a1d96edc..b9d99e51dd7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-10-17 Aldy Hernandez + + PR middle-end/54893 + * trans-mem.c (diagnose_tm_1_op): Allow volatiles inside relaxed + transactions. + 2012-10-17 Aldy Hernandez PR rtl-optimization/54900 diff --git a/gcc/testsuite/c-c++-common/tm/pr54893.c b/gcc/testsuite/c-c++-common/tm/pr54893.c new file mode 100644 index 00000000000..8967f384afd --- /dev/null +++ b/gcc/testsuite/c-c++-common/tm/pr54893.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fgnu-tm -fdump-ipa-tmipa" } */ + +/* Test that volatiles are allowed inside relaxed transactions. */ + +volatile int test_var = 0; + +int main() +{ + __transaction_relaxed { + test_var++; + } +} + +/* { dg-final { scan-ipa-dump "GTMA_DOES_GO_IRREVOCABLE" "tmipa" } } */ +/* { dg-final { cleanup-ipa-dump "tmipa" } } */ diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index ef384acd7dc..211c45e48fb 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -548,6 +548,15 @@ struct diagnose_tm gimple stmt; }; +/* Return true if T is a volatile variable of some kind. */ + +static bool +volatile_var_p (tree t) +{ + return (SSA_VAR_P (t) + && TREE_THIS_VOLATILE (TREE_TYPE (t))); +} + /* Tree callback function for diagnose_tm pass. */ static tree @@ -556,13 +565,9 @@ diagnose_tm_1_op (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, { struct walk_stmt_info *wi = (struct walk_stmt_info *) data; struct diagnose_tm *d = (struct diagnose_tm *) wi->info; - enum tree_code code = TREE_CODE (*tp); - if ((code == VAR_DECL - || code == RESULT_DECL - || code == PARM_DECL) - && d->block_flags & (DIAG_TM_SAFE | DIAG_TM_RELAXED) - && TREE_THIS_VOLATILE (TREE_TYPE (*tp)) + if (volatile_var_p (*tp) + && d->block_flags & DIAG_TM_SAFE && !d->saw_volatile) { d->saw_volatile = 1; @@ -3782,41 +3787,57 @@ ipa_tm_scan_irr_block (basic_block bb) gimple stmt = gsi_stmt (gsi); switch (gimple_code (stmt)) { - case GIMPLE_CALL: - if (is_tm_pure_call (stmt)) - break; - - fn = gimple_call_fn (stmt); - - /* Functions with the attribute are by definition irrevocable. */ - if (is_tm_irrevocable (fn)) - return true; - - /* For direct function calls, go ahead and check for replacement - functions, or transitive irrevocable functions. For indirect - functions, we'll ask the runtime. */ - if (TREE_CODE (fn) == ADDR_EXPR) + case GIMPLE_ASSIGN: + if (gimple_assign_single_p (stmt)) { - struct tm_ipa_cg_data *d; - struct cgraph_node *node; - - fn = TREE_OPERAND (fn, 0); - if (is_tm_ending_fndecl (fn)) - break; - if (find_tm_replacement_function (fn)) - break; - - node = cgraph_get_node(fn); - d = get_cg_data (&node, true); - - /* Return true if irrevocable, but above all, believe - the user. */ - if (d->is_irrevocable - && !is_tm_safe_or_pure (fn)) + tree lhs = gimple_assign_lhs (stmt); + tree rhs = gimple_assign_rhs1 (stmt); + if (volatile_var_p (lhs) || volatile_var_p (rhs)) return true; } break; + case GIMPLE_CALL: + { + tree lhs = gimple_call_lhs (stmt); + if (lhs && volatile_var_p (lhs)) + return true; + + if (is_tm_pure_call (stmt)) + break; + + fn = gimple_call_fn (stmt); + + /* Functions with the attribute are by definition irrevocable. */ + if (is_tm_irrevocable (fn)) + return true; + + /* For direct function calls, go ahead and check for replacement + functions, or transitive irrevocable functions. For indirect + functions, we'll ask the runtime. */ + if (TREE_CODE (fn) == ADDR_EXPR) + { + struct tm_ipa_cg_data *d; + struct cgraph_node *node; + + fn = TREE_OPERAND (fn, 0); + if (is_tm_ending_fndecl (fn)) + break; + if (find_tm_replacement_function (fn)) + break; + + node = cgraph_get_node(fn); + d = get_cg_data (&node, true); + + /* Return true if irrevocable, but above all, believe + the user. */ + if (d->is_irrevocable + && !is_tm_safe_or_pure (fn)) + return true; + } + break; + } + case GIMPLE_ASM: /* ??? The Approved Method of indicating that an inline assembly statement is not relevant to the transaction