diff options
Diffstat (limited to 'gcc/trans-mem.c')
-rw-r--r-- | gcc/trans-mem.c | 132 |
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); |