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:
parent
a7b159a4dc
commit
a3770d3b7d
@ -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>
|
2012-10-17 Aldy Hernandez <aldyh@redhat.com>
|
||||||
|
|
||||||
PR rtl-optimization/54900
|
PR rtl-optimization/54900
|
||||||
|
16
gcc/testsuite/c-c++-common/tm/pr54893.c
Normal file
16
gcc/testsuite/c-c++-common/tm/pr54893.c
Normal 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" } } */
|
@ -548,6 +548,15 @@ struct diagnose_tm
|
|||||||
gimple stmt;
|
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. */
|
/* Tree callback function for diagnose_tm pass. */
|
||||||
|
|
||||||
static tree
|
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 walk_stmt_info *wi = (struct walk_stmt_info *) data;
|
||||||
struct diagnose_tm *d = (struct diagnose_tm *) wi->info;
|
struct diagnose_tm *d = (struct diagnose_tm *) wi->info;
|
||||||
enum tree_code code = TREE_CODE (*tp);
|
|
||||||
|
|
||||||
if ((code == VAR_DECL
|
if (volatile_var_p (*tp)
|
||||||
|| code == RESULT_DECL
|
&& d->block_flags & DIAG_TM_SAFE
|
||||||
|| code == PARM_DECL)
|
|
||||||
&& d->block_flags & (DIAG_TM_SAFE | DIAG_TM_RELAXED)
|
|
||||||
&& TREE_THIS_VOLATILE (TREE_TYPE (*tp))
|
|
||||||
&& !d->saw_volatile)
|
&& !d->saw_volatile)
|
||||||
{
|
{
|
||||||
d->saw_volatile = 1;
|
d->saw_volatile = 1;
|
||||||
@ -3782,41 +3787,57 @@ ipa_tm_scan_irr_block (basic_block bb)
|
|||||||
gimple stmt = gsi_stmt (gsi);
|
gimple stmt = gsi_stmt (gsi);
|
||||||
switch (gimple_code (stmt))
|
switch (gimple_code (stmt))
|
||||||
{
|
{
|
||||||
case GIMPLE_CALL:
|
case GIMPLE_ASSIGN:
|
||||||
if (is_tm_pure_call (stmt))
|
if (gimple_assign_single_p (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;
|
tree lhs = gimple_assign_lhs (stmt);
|
||||||
struct cgraph_node *node;
|
tree rhs = gimple_assign_rhs1 (stmt);
|
||||||
|
if (volatile_var_p (lhs) || volatile_var_p (rhs))
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case GIMPLE_ASM:
|
||||||
/* ??? The Approved Method of indicating that an inline
|
/* ??? The Approved Method of indicating that an inline
|
||||||
assembly statement is not relevant to the transaction
|
assembly statement is not relevant to the transaction
|
||||||
|
Loading…
Reference in New Issue
Block a user