summaryrefslogtreecommitdiff
path: root/gcc/trans-mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/trans-mem.c')
-rw-r--r--gcc/trans-mem.c132
1 files changed, 83 insertions, 49 deletions
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 9899e7b54a8..d3a6f10fbcc 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -767,9 +767,10 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_TRANSACTION:
{
+ gtransaction *trans_stmt = as_a <gtransaction *> (stmt);
unsigned char inner_flags = DIAG_TM_SAFE;
- if (gimple_transaction_subcode (stmt) & GTMA_IS_RELAXED)
+ if (gimple_transaction_subcode (trans_stmt) & GTMA_IS_RELAXED)
{
if (d->block_flags & DIAG_TM_SAFE)
error_at (gimple_location (stmt),
@@ -779,7 +780,7 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
"relaxed transaction in %<transaction_safe%> function");
inner_flags = DIAG_TM_RELAXED;
}
- else if (gimple_transaction_subcode (stmt) & GTMA_IS_OUTER)
+ else if (gimple_transaction_subcode (trans_stmt) & GTMA_IS_OUTER)
{
if (d->block_flags)
error_at (gimple_location (stmt),
@@ -795,7 +796,7 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
}
*handled_ops_p = true;
- if (gimple_transaction_body (stmt))
+ if (gimple_transaction_body (trans_stmt))
{
struct walk_stmt_info wi_inner;
struct diagnose_tm d_inner;
@@ -808,7 +809,7 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
memset (&wi_inner, 0, sizeof (wi_inner));
wi_inner.info = &d_inner;
- walk_gimple_seq (gimple_transaction_body (stmt),
+ walk_gimple_seq (gimple_transaction_body (trans_stmt),
diagnose_tm_1, diagnose_tm_1_op, &wi_inner);
}
}
@@ -930,7 +931,7 @@ typedef struct tm_log_entry
/* Entry block for the transaction this address occurs in. */
basic_block entry_block;
/* Dominating statements the store occurs in. */
- gimple_vec stmts;
+ vec<gimple> stmts;
/* Initially, while we are building the log, we place a nonzero
value here to mean that this address *will* be saved with a
save/restore sequence. Later, when generating the save sequence
@@ -1610,7 +1611,8 @@ examine_call_tm (unsigned *state, gimple_stmt_iterator *gsi)
static void
lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
{
- gimple g, stmt = gsi_stmt (*gsi);
+ gimple g;
+ gtransaction *stmt = as_a <gtransaction *> (gsi_stmt (*gsi));
unsigned int *outer_state = (unsigned int *) wi->info;
unsigned int this_state = 0;
struct walk_stmt_info this_wi;
@@ -1806,6 +1808,22 @@ make_pass_lower_tm (gcc::context *ctxt)
struct tm_region
{
+public:
+
+ /* The field "transaction_stmt" is initially a gtransaction *,
+ but eventually gets lowered to a gcall *(to BUILT_IN_TM_START).
+
+ Helper method to get it as a gtransaction *, with code-checking
+ in a checked-build. */
+
+ gtransaction *
+ get_transaction_stmt () const
+ {
+ return as_a <gtransaction *> (transaction_stmt);
+ }
+
+public:
+
/* Link to the next unnested transaction. */
struct tm_region *next;
@@ -1817,7 +1835,8 @@ struct tm_region
/* The GIMPLE_TRANSACTION statement beginning this transaction.
After TM_MARK, this gets replaced by a call to
- BUILT_IN_TM_START. */
+ BUILT_IN_TM_START.
+ Hence this will be either a gtransaction *or a gcall *. */
gimple transaction_stmt;
/* After TM_MARK expands the GIMPLE_TRANSACTION into a call to
@@ -1860,7 +1879,8 @@ static bitmap_obstack tm_obstack;
GIMPLE_TRANSACTION statement in a tree of tm_region elements. */
static struct tm_region *
-tm_region_init_0 (struct tm_region *outer, basic_block bb, gimple stmt)
+tm_region_init_0 (struct tm_region *outer, basic_block bb,
+ gtransaction *stmt)
{
struct tm_region *region;
@@ -1975,8 +1995,9 @@ tm_region_init (struct tm_region *region)
/* Check for the last statement in the block beginning a new region. */
g = last_stmt (bb);
old_region = region;
- if (g && gimple_code (g) == GIMPLE_TRANSACTION)
- region = tm_region_init_0 (region, bb, g);
+ if (g)
+ if (gtransaction *trans_stmt = dyn_cast <gtransaction *> (g))
+ region = tm_region_init_0 (region, bb, trans_stmt);
/* Process subsequent blocks. */
FOR_EACH_EDGE (e, ei, bb->succs)
@@ -2085,8 +2106,9 @@ transaction_subcode_ior (struct tm_region *region, unsigned flags)
{
if (region && region->transaction_stmt)
{
- flags |= gimple_transaction_subcode (region->transaction_stmt);
- gimple_transaction_set_subcode (region->transaction_stmt, flags);
+ gtransaction *transaction_stmt = region->get_transaction_stmt ();
+ flags |= gimple_transaction_subcode (transaction_stmt);
+ gimple_transaction_set_subcode (transaction_stmt, flags);
}
}
@@ -2096,12 +2118,12 @@ transaction_subcode_ior (struct tm_region *region, unsigned flags)
LOC is the location to use for the new statement(s). */
-static gimple
+static gcall *
build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
{
enum built_in_function code = END_BUILTINS;
tree t, type = TREE_TYPE (rhs), decl;
- gimple gcall;
+ gcall *gcall;
if (type == float_type_node)
code = BUILT_IN_TM_LOAD_FLOAT;
@@ -2168,12 +2190,12 @@ build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
/* Similarly for storing TYPE in a transactional context. */
-static gimple
+static gcall *
build_tm_store (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
{
enum built_in_function code = END_BUILTINS;
tree t, fn, type = TREE_TYPE (rhs), simple_type;
- gimple gcall;
+ gcall *gcall;
if (type == float_type_node)
code = BUILT_IN_TM_STORE_FLOAT;
@@ -2340,7 +2362,7 @@ static bool
expand_call_tm (struct tm_region *region,
gimple_stmt_iterator *gsi)
{
- gimple stmt = gsi_stmt (*gsi);
+ gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
tree lhs = gimple_call_lhs (stmt);
tree fn_decl;
struct cgraph_node *node;
@@ -2427,6 +2449,7 @@ expand_call_tm (struct tm_region *region,
tree tmp = create_tmp_reg (TREE_TYPE (lhs), NULL);
location_t loc = gimple_location (stmt);
edge fallthru_edge = NULL;
+ gassign *assign_stmt;
/* Remember if the call was going to throw. */
if (stmt_can_throw_internal (stmt))
@@ -2445,15 +2468,15 @@ expand_call_tm (struct tm_region *region,
gimple_call_set_lhs (stmt, tmp);
update_stmt (stmt);
- stmt = gimple_build_assign (lhs, tmp);
- gimple_set_location (stmt, loc);
+ assign_stmt = gimple_build_assign (lhs, tmp);
+ gimple_set_location (assign_stmt, loc);
/* We cannot throw in the middle of a BB. If the call was going
to throw, place the instrumentation on the fallthru edge, so
the call remains the last statement in the block. */
if (fallthru_edge)
{
- gimple_seq fallthru_seq = gimple_seq_alloc_with_stmt (stmt);
+ gimple_seq fallthru_seq = gimple_seq_alloc_with_stmt (assign_stmt);
gimple_stmt_iterator fallthru_gsi = gsi_start (fallthru_seq);
expand_assign_tm (region, &fallthru_gsi);
gsi_insert_seq_on_edge (fallthru_edge, fallthru_seq);
@@ -2461,7 +2484,7 @@ expand_call_tm (struct tm_region *region,
}
else
{
- gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
+ gsi_insert_after (gsi, assign_stmt, GSI_CONTINUE_LINKING);
expand_assign_tm (region, gsi);
}
@@ -2710,7 +2733,7 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
/* ??? There are plenty of bits here we're not computing. */
{
- int subcode = gimple_transaction_subcode (region->transaction_stmt);
+ int subcode = gimple_transaction_subcode (region->get_transaction_stmt ());
int flags = 0;
if (subcode & GTMA_DOES_GO_IRREVOCABLE)
flags |= PR_DOESGOIRREVOCABLE;
@@ -2729,7 +2752,7 @@ expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
if (subcode & GTMA_IS_OUTER)
region->original_transaction_was_outer = true;
tree t = build_int_cst (tm_state_type, flags);
- gimple call = gimple_build_call (tm_start, 1, t);
+ gcall *call = gimple_build_call (tm_start, 1, t);
gimple_call_set_lhs (call, tm_state);
gimple_set_location (call, gimple_location (region->transaction_stmt));
@@ -2915,8 +2938,8 @@ generate_tm_state (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
// again as we process blocks.
if (region->exit_blocks)
{
- unsigned int subcode
- = gimple_transaction_subcode (region->transaction_stmt);
+ gtransaction *transaction_stmt = region->get_transaction_stmt ();
+ unsigned int subcode = gimple_transaction_subcode (transaction_stmt);
if (subcode & GTMA_DOES_GO_IRREVOCABLE)
subcode &= (GTMA_DECLARATION_MASK | GTMA_DOES_GO_IRREVOCABLE
@@ -2924,7 +2947,7 @@ generate_tm_state (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
| GTMA_HAS_NO_INSTRUMENTATION);
else
subcode &= GTMA_DECLARATION_MASK;
- gimple_transaction_set_subcode (region->transaction_stmt, subcode);
+ gimple_transaction_set_subcode (transaction_stmt, subcode);
}
return NULL;
@@ -2940,11 +2963,13 @@ propagate_tm_flags_out (struct tm_region *region)
if (region->outer && region->outer->transaction_stmt)
{
- unsigned s = gimple_transaction_subcode (region->transaction_stmt);
+ unsigned s
+ = gimple_transaction_subcode (region->get_transaction_stmt ());
s &= (GTMA_HAVE_ABORT | GTMA_HAVE_LOAD | GTMA_HAVE_STORE
| GTMA_MAY_ENTER_IRREVOCABLE);
- s |= gimple_transaction_subcode (region->outer->transaction_stmt);
- gimple_transaction_set_subcode (region->outer->transaction_stmt, s);
+ s |= gimple_transaction_subcode (region->outer->get_transaction_stmt ());
+ gimple_transaction_set_subcode (region->outer->get_transaction_stmt (),
+ s);
}
propagate_tm_flags_out (region->next);
@@ -2979,7 +3004,8 @@ execute_tm_mark (void)
{
if (r->transaction_stmt)
{
- unsigned sub = gimple_transaction_subcode (r->transaction_stmt);
+ unsigned sub
+ = gimple_transaction_subcode (r->get_transaction_stmt ());
/* If we're sure to go irrevocable, there won't be
anything to expand, since the run-time will go
@@ -3097,23 +3123,26 @@ expand_block_edges (struct tm_region *const region, basic_block bb)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi = next_gsi)
{
gimple stmt = gsi_stmt (gsi);
+ gcall *call_stmt;
next_gsi = gsi;
gsi_next (&next_gsi);
// ??? Shouldn't we split for any non-pure, non-irrevocable function?
- if (gimple_code (stmt) != GIMPLE_CALL
- || (gimple_call_flags (stmt) & ECF_TM_BUILTIN) == 0)
+ call_stmt = dyn_cast <gcall *> (stmt);
+ if ((!call_stmt)
+ || (gimple_call_flags (call_stmt) & ECF_TM_BUILTIN) == 0)
continue;
- if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)) == BUILT_IN_TM_ABORT)
+ if (DECL_FUNCTION_CODE (gimple_call_fndecl (call_stmt))
+ == BUILT_IN_TM_ABORT)
{
// If we have a ``_transaction_cancel [[outer]]'', there is only
// one abnormal edge: to the transaction marked OUTER.
// All compiler-generated instances of BUILT_IN_TM_ABORT have a
// constant argument, which we can examine here. Users invoking
// TM_ABORT directly get what they deserve.
- tree arg = gimple_call_arg (stmt, 0);
+ tree arg = gimple_call_arg (call_stmt, 0);
if (TREE_CODE (arg) == INTEGER_CST
&& (TREE_INT_CST_LOW (arg) & AR_OUTERABORT) != 0
&& !decl_is_tm_clone (current_function_decl))
@@ -3122,7 +3151,7 @@ expand_block_edges (struct tm_region *const region, basic_block bb)
for (struct tm_region *o = region; o; o = o->outer)
if (o->original_transaction_was_outer)
{
- split_bb_make_tm_edge (stmt, o->restart_block,
+ split_bb_make_tm_edge (call_stmt, o->restart_block,
gsi, &next_gsi);
break;
}
@@ -3135,7 +3164,8 @@ expand_block_edges (struct tm_region *const region, basic_block bb)
// Non-outer, TM aborts have an abnormal edge to the inner-most
// transaction, the one being aborted;
- split_bb_make_tm_edge (stmt, region->restart_block, gsi, &next_gsi);
+ split_bb_make_tm_edge (call_stmt, region->restart_block, gsi,
+ &next_gsi);
}
// All TM builtins have an abnormal edge to the outer-most transaction.
@@ -3153,14 +3183,14 @@ expand_block_edges (struct tm_region *const region, basic_block bb)
for (struct tm_region *o = region; o; o = o->outer)
if (!o->outer)
{
- split_bb_make_tm_edge (stmt, o->restart_block, gsi, &next_gsi);
+ split_bb_make_tm_edge (call_stmt, o->restart_block, gsi, &next_gsi);
break;
}
// Delete any tail-call annotation that may have been added.
// The tail-call pass may have mis-identified the commit as being
// a candidate because we had not yet added this restart edge.
- gimple_call_set_tail (stmt, false);
+ gimple_call_set_tail (call_stmt, false);
}
}
@@ -3764,7 +3794,7 @@ dump_tm_memopt_transform (gimple stmt)
static void
tm_memopt_transform_stmt (unsigned int offset,
- gimple stmt,
+ gcall *stmt,
gimple_stmt_iterator *gsi)
{
tree fn = gimple_call_fn (stmt);
@@ -3800,28 +3830,30 @@ tm_memopt_transform_blocks (vec<basic_block> blocks)
if (is_tm_simple_load (stmt))
{
+ gcall *call_stmt = as_a <gcall *> (stmt);
loc = tm_memopt_value_number (stmt, NO_INSERT);
if (store_avail && bitmap_bit_p (store_avail, loc))
- tm_memopt_transform_stmt (TRANSFORM_RAW, stmt, &gsi);
+ tm_memopt_transform_stmt (TRANSFORM_RAW, call_stmt, &gsi);
else if (store_antic && bitmap_bit_p (store_antic, loc))
{
- tm_memopt_transform_stmt (TRANSFORM_RFW, stmt, &gsi);
+ tm_memopt_transform_stmt (TRANSFORM_RFW, call_stmt, &gsi);
bitmap_set_bit (store_avail, loc);
}
else if (read_avail && bitmap_bit_p (read_avail, loc))
- tm_memopt_transform_stmt (TRANSFORM_RAR, stmt, &gsi);
+ tm_memopt_transform_stmt (TRANSFORM_RAR, call_stmt, &gsi);
else
bitmap_set_bit (read_avail, loc);
}
else if (is_tm_simple_store (stmt))
{
+ gcall *call_stmt = as_a <gcall *> (stmt);
loc = tm_memopt_value_number (stmt, NO_INSERT);
if (store_avail && bitmap_bit_p (store_avail, loc))
- tm_memopt_transform_stmt (TRANSFORM_WAW, stmt, &gsi);
+ tm_memopt_transform_stmt (TRANSFORM_WAW, call_stmt, &gsi);
else
{
if (read_avail && bitmap_bit_p (read_avail, loc))
- tm_memopt_transform_stmt (TRANSFORM_WAR, stmt, &gsi);
+ tm_memopt_transform_stmt (TRANSFORM_WAR, call_stmt, &gsi);
bitmap_set_bit (store_avail, loc);
}
}
@@ -4676,7 +4708,8 @@ ipa_tm_diagnose_transaction (struct cgraph_node *node,
struct tm_region *r;
for (r = all_tm_regions; r ; r = r->next)
- if (gimple_transaction_subcode (r->transaction_stmt) & GTMA_IS_RELAXED)
+ if (gimple_transaction_subcode (r->get_transaction_stmt ())
+ & GTMA_IS_RELAXED)
{
/* Atomic transactions can be nested inside relaxed. */
if (r->inner)
@@ -4950,7 +4983,7 @@ ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region,
basic_block bb)
{
gimple_stmt_iterator gsi;
- gimple g;
+ gcall *g;
transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE);
@@ -4973,10 +5006,11 @@ ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region,
static bool
ipa_tm_insert_gettmclone_call (struct cgraph_node *node,
struct tm_region *region,
- gimple_stmt_iterator *gsi, gimple stmt)
+ gimple_stmt_iterator *gsi, gcall *stmt)
{
tree gettm_fn, ret, old_fn, callfn;
- gimple g, g2;
+ gcall *g;
+ gassign *g2;
bool safe;
old_fn = gimple_call_fn (stmt);
@@ -5072,7 +5106,7 @@ ipa_tm_transform_calls_redirect (struct cgraph_node *node,
gimple_stmt_iterator *gsi,
bool *need_ssa_rename_p)
{
- gimple stmt = gsi_stmt (*gsi);
+ gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
struct cgraph_node *new_node;
struct cgraph_edge *e = node->get_edge (stmt);
tree fndecl = gimple_call_fndecl (stmt);