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
This commit is contained in:
Aldy Hernandez 2012-10-17 21:18:16 +00:00 committed by Aldy Hernandez
parent a7b159a4dc
commit a3770d3b7d
3 changed files with 79 additions and 36 deletions

View File

@ -1,3 +1,9 @@
2012-10-17 Aldy Hernandez <aldyh@redhat.com>
PR middle-end/54893
* trans-mem.c (diagnose_tm_1_op): Allow volatiles inside relaxed
transactions.
2012-10-17 Aldy Hernandez <aldyh@redhat.com>
PR rtl-optimization/54900

View File

@ -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" } } */

View File

@ -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