From: Richard Henderson Date: Tue, 22 Dec 2015 19:42:24 +0000 (-0800) Subject: re PR ipa/67811 ([TM] ICE with try-block in transaction) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7c11b0fef088480510a74f0f43015776c40be047;p=gcc.git re PR ipa/67811 ([TM] ICE with try-block in transaction) PR ipa/67811 * gimple.h (struct gtransaction): Add label_norm, label_uninst; replace label with label_over. (gimple_build_transaction): Remove label parameter. (gimple_transaction_label_norm): New. (gimple_transaction_label_uninst): New. (gimple_transaction_label_over): Rename from gimple_transaction_label. (gimple_transaction_label_norm_ptr): New. (gimple_transaction_label_uninst_ptr): New. (gimple_transaction_label_over_ptr): Rename from gimple_transaction_label_ptr. (gimple_transaction_set_label_norm): New. (gimple_transaction_set_label_uninst): New. (gimple_transaction_set_label_over): Rename from gimple_transaction_set_label. * gimple-pretty-print.c (dump_gimple_transaction): Update. * gimple-streamer-in.c (input_gimple_stmt) [GIMPLE_TRANSACTION]: Same. * gimple-streamer-out.c (output_gimple_stmt) [GIMPLE_TRANSACTION]: Same. * gimple-walk.c (walk_gimple_op) [GIMPLE_TRANSACTION]: Same. * tree-cfg.c (make_edges_bb) [GIMPLE_TRANSACTION]: Same. (cleanup_dead_labels) [GIMPLE_TRANSACTION]: Same. (verify_gimple_transaction): Same. (gimple_redirect_edge_and_branch) [GIMPLE_TRANSACTION]: Same. * tree-inline.c (remap_gimple_stmt) [GIMPLE_TRANSACTION]: Same. * gimple.c (gimple_build_transaction): Remove label parameter; initialize all three label memebers. * gimplify.c (gimplify_transaction): Update call to gimple_build_transaction. * trans-mem.c (make_tm_uninst): New. (lower_transaction): Create uninstrumented code path here... (ipa_tm_scan_calls_transaction): ... not here. (ipa_uninstrument_transaction): Remove. testsuite/ * g++.dg/tm/noexcept-1.C: Update expected must_not_throw count. * g++.dg/tm/noexcept-4.C: Likewise. * g++.dg/tm/noexcept-5.C: Likewise. * g++.dg/tm/pr67811.C: New. From-SVN: r231907 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 11f53c76901..a9e73f45e6a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,38 @@ +2015-12-22 Richard Henderson + + PR ipa/67811 + * gimple.h (struct gtransaction): Add label_norm, label_uninst; + replace label with label_over. + (gimple_build_transaction): Remove label parameter. + (gimple_transaction_label_norm): New. + (gimple_transaction_label_uninst): New. + (gimple_transaction_label_over): Rename from gimple_transaction_label. + (gimple_transaction_label_norm_ptr): New. + (gimple_transaction_label_uninst_ptr): New. + (gimple_transaction_label_over_ptr): Rename from + gimple_transaction_label_ptr. + (gimple_transaction_set_label_norm): New. + (gimple_transaction_set_label_uninst): New. + (gimple_transaction_set_label_over): Rename from + gimple_transaction_set_label. + * gimple-pretty-print.c (dump_gimple_transaction): Update. + * gimple-streamer-in.c (input_gimple_stmt) [GIMPLE_TRANSACTION]: Same. + * gimple-streamer-out.c (output_gimple_stmt) [GIMPLE_TRANSACTION]: Same. + * gimple-walk.c (walk_gimple_op) [GIMPLE_TRANSACTION]: Same. + * tree-cfg.c (make_edges_bb) [GIMPLE_TRANSACTION]: Same. + (cleanup_dead_labels) [GIMPLE_TRANSACTION]: Same. + (verify_gimple_transaction): Same. + (gimple_redirect_edge_and_branch) [GIMPLE_TRANSACTION]: Same. + * tree-inline.c (remap_gimple_stmt) [GIMPLE_TRANSACTION]: Same. + * gimple.c (gimple_build_transaction): Remove label parameter; + initialize all three label memebers. + * gimplify.c (gimplify_transaction): Update call + to gimple_build_transaction. + * trans-mem.c (make_tm_uninst): New. + (lower_transaction): Create uninstrumented code path here... + (ipa_tm_scan_calls_transaction): ... not here. + (ipa_uninstrument_transaction): Remove. + 2015-12-22 Peter Bergner PR target/68772 diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 01e9b6b004c..41e4c5e8dab 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1607,8 +1607,11 @@ dump_gimple_transaction (pretty_printer *buffer, gtransaction *gs, if (flags & TDF_RAW) { dump_gimple_fmt (buffer, spc, flags, - "%G [SUBCODE=%x,LABEL=%T] <%+BODY <%S> >", - gs, subcode, gimple_transaction_label (gs), + "%G [SUBCODE=%x,NORM=%T,UNINST=%T,OVER=%T] " + "<%+BODY <%S> >", + gs, subcode, gimple_transaction_label_norm (gs), + gimple_transaction_label_uninst (gs), + gimple_transaction_label_over (gs), gimple_transaction_body (gs)); } else @@ -1621,13 +1624,35 @@ dump_gimple_transaction (pretty_printer *buffer, gtransaction *gs, pp_string (buffer, "__transaction_atomic"); subcode &= ~GTMA_DECLARATION_MASK; - if (subcode || gimple_transaction_label (gs)) + if (gimple_transaction_body (gs)) + { + newline_and_indent (buffer, spc + 2); + pp_left_brace (buffer); + pp_newline (buffer); + dump_gimple_seq (buffer, gimple_transaction_body (gs), + spc + 4, flags); + newline_and_indent (buffer, spc + 2); + pp_right_brace (buffer); + } + else { pp_string (buffer, " //"); - if (gimple_transaction_label (gs)) + if (gimple_transaction_label_norm (gs)) + { + pp_string (buffer, " NORM="); + dump_generic_node (buffer, gimple_transaction_label_norm (gs), + spc, flags, false); + } + if (gimple_transaction_label_uninst (gs)) { - pp_string (buffer, " LABEL="); - dump_generic_node (buffer, gimple_transaction_label (gs), + pp_string (buffer, " UNINST="); + dump_generic_node (buffer, gimple_transaction_label_uninst (gs), + spc, flags, false); + } + if (gimple_transaction_label_over (gs)) + { + pp_string (buffer, " OVER="); + dump_generic_node (buffer, gimple_transaction_label_over (gs), spc, flags, false); } if (subcode) @@ -1668,17 +1693,6 @@ dump_gimple_transaction (pretty_printer *buffer, gtransaction *gs, pp_right_bracket (buffer); } } - - if (!gimple_seq_empty_p (gimple_transaction_body (gs))) - { - newline_and_indent (buffer, spc + 2); - pp_left_brace (buffer); - pp_newline (buffer); - dump_gimple_seq (buffer, gimple_transaction_body (gs), - spc + 4, flags); - newline_and_indent (buffer, spc + 2); - pp_right_brace (buffer); - } } } diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c index 44bcc11f4e2..6310717c7c6 100644 --- a/gcc/gimple-streamer-in.c +++ b/gcc/gimple-streamer-in.c @@ -198,8 +198,12 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, break; case GIMPLE_TRANSACTION: - gimple_transaction_set_label (as_a (stmt), - stream_read_tree (ib, data_in)); + gimple_transaction_set_label_norm (as_a (stmt), + stream_read_tree (ib, data_in)); + gimple_transaction_set_label_uninst (as_a (stmt), + stream_read_tree (ib, data_in)); + gimple_transaction_set_label_over (as_a (stmt), + stream_read_tree (ib, data_in)); break; default: diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c index 1431f5ce3c9..cbcb4db4a62 100644 --- a/gcc/gimple-streamer-out.c +++ b/gcc/gimple-streamer-out.c @@ -180,9 +180,11 @@ output_gimple_stmt (struct output_block *ob, gimple *stmt) case GIMPLE_TRANSACTION: { - gtransaction *trans_stmt = as_a (stmt); - gcc_assert (gimple_transaction_body (trans_stmt) == NULL); - stream_write_tree (ob, gimple_transaction_label (trans_stmt), true); + gtransaction *txn = as_a (stmt); + gcc_assert (gimple_transaction_body (txn) == NULL); + stream_write_tree (ob, gimple_transaction_label_norm (txn), true); + stream_write_tree (ob, gimple_transaction_label_uninst (txn), true); + stream_write_tree (ob, gimple_transaction_label_over (txn), true); } break; diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c index 850cf57fa65..b8bae505b66 100644 --- a/gcc/gimple-walk.c +++ b/gcc/gimple-walk.c @@ -474,11 +474,22 @@ walk_gimple_op (gimple *stmt, walk_tree_fn callback_op, break; case GIMPLE_TRANSACTION: - ret = walk_tree (gimple_transaction_label_ptr ( - as_a (stmt)), - callback_op, wi, pset); - if (ret) - return ret; + { + gtransaction *txn = as_a (stmt); + + ret = walk_tree (gimple_transaction_label_norm_ptr (txn), + callback_op, wi, pset); + if (ret) + return ret; + ret = walk_tree (gimple_transaction_label_uninst_ptr (txn), + callback_op, wi, pset); + if (ret) + return ret; + ret = walk_tree (gimple_transaction_label_over_ptr (txn), + callback_op, wi, pset); + if (ret) + return ret; + } break; case GIMPLE_OMP_RETURN: diff --git a/gcc/gimple.c b/gcc/gimple.c index bf552a7ae9c..49663dfe7b1 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1131,12 +1131,14 @@ gimple_build_omp_atomic_store (tree val) /* Build a GIMPLE_TRANSACTION statement. */ gtransaction * -gimple_build_transaction (gimple_seq body, tree label) +gimple_build_transaction (gimple_seq body) { gtransaction *p = as_a (gimple_alloc (GIMPLE_TRANSACTION, 0)); gimple_transaction_set_body (p, body); - gimple_transaction_set_label (p, label); + gimple_transaction_set_label_norm (p, 0); + gimple_transaction_set_label_uninst (p, 0); + gimple_transaction_set_label_over (p, 0); return p; } diff --git a/gcc/gimple.h b/gcc/gimple.h index dc61043fafc..adfe071a0eb 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -836,8 +836,10 @@ struct GTY((tag("GSS_TRANSACTION"))) /* [ WORD 10 ] */ gimple_seq body; - /* [ WORD 11 ] */ - tree label; + /* [ WORD 11-13 ] */ + tree label_norm; + tree label_uninst; + tree label_over; }; #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) SYM, @@ -1463,7 +1465,7 @@ gomp_target *gimple_build_omp_target (gimple_seq, int, tree); gomp_teams *gimple_build_omp_teams (gimple_seq, tree); gomp_atomic_load *gimple_build_omp_atomic_load (tree, tree); gomp_atomic_store *gimple_build_omp_atomic_store (tree); -gtransaction *gimple_build_transaction (gimple_seq, tree); +gtransaction *gimple_build_transaction (gimple_seq); extern void gimple_seq_add_stmt (gimple_seq *, gimple *); extern void gimple_seq_add_stmt_without_update (gimple_seq *, gimple *); void gimple_seq_add_seq (gimple_seq *, gimple_seq); @@ -5847,21 +5849,45 @@ gimple_transaction_body_ptr (gtransaction *transaction_stmt) static inline gimple_seq gimple_transaction_body (gtransaction *transaction_stmt) { - return *gimple_transaction_body_ptr (transaction_stmt); + return transaction_stmt->body; } /* Return the label associated with a GIMPLE_TRANSACTION. */ static inline tree -gimple_transaction_label (const gtransaction *transaction_stmt) +gimple_transaction_label_norm (const gtransaction *transaction_stmt) { - return transaction_stmt->label; + return transaction_stmt->label_norm; } static inline tree * -gimple_transaction_label_ptr (gtransaction *transaction_stmt) +gimple_transaction_label_norm_ptr (gtransaction *transaction_stmt) { - return &transaction_stmt->label; + return &transaction_stmt->label_norm; +} + +static inline tree +gimple_transaction_label_uninst (const gtransaction *transaction_stmt) +{ + return transaction_stmt->label_uninst; +} + +static inline tree * +gimple_transaction_label_uninst_ptr (gtransaction *transaction_stmt) +{ + return &transaction_stmt->label_uninst; +} + +static inline tree +gimple_transaction_label_over (const gtransaction *transaction_stmt) +{ + return transaction_stmt->label_over; +} + +static inline tree * +gimple_transaction_label_over_ptr (gtransaction *transaction_stmt) +{ + return &transaction_stmt->label_over; } /* Return the subcode associated with a GIMPLE_TRANSACTION. */ @@ -5885,9 +5911,21 @@ gimple_transaction_set_body (gtransaction *transaction_stmt, /* Set the label associated with a GIMPLE_TRANSACTION. */ static inline void -gimple_transaction_set_label (gtransaction *transaction_stmt, tree label) +gimple_transaction_set_label_norm (gtransaction *transaction_stmt, tree label) +{ + transaction_stmt->label_norm = label; +} + +static inline void +gimple_transaction_set_label_uninst (gtransaction *transaction_stmt, tree label) +{ + transaction_stmt->label_uninst = label; +} + +static inline void +gimple_transaction_set_label_over (gtransaction *transaction_stmt, tree label) { - transaction_stmt->label = label; + transaction_stmt->label_over = label; } /* Set the subcode associated with a GIMPLE_TRANSACTION. */ @@ -5899,7 +5937,6 @@ gimple_transaction_set_subcode (gtransaction *transaction_stmt, transaction_stmt->subcode = subcode; } - /* Return a pointer to the return value for GIMPLE_RETURN GS. */ static inline tree * diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 438efba57e1..62b0e643506 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -9739,7 +9739,7 @@ gimplify_transaction (tree *expr_p, gimple_seq *pre_p) body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body); pop_gimplify_context (body_stmt); - trans_stmt = gimple_build_transaction (body, NULL); + trans_stmt = gimple_build_transaction (body); if (TRANSACTION_EXPR_OUTER (expr)) subcode = GTMA_IS_OUTER; else if (TRANSACTION_EXPR_RELAXED (expr)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 19fccfd5316..3c2e2aca9e5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-12-22 Richard Henderson + + * g++.dg/tm/noexcept-1.C: Update expected must_not_throw count. + * g++.dg/tm/noexcept-4.C: Likewise. + * g++.dg/tm/noexcept-5.C: Likewise. + * g++.dg/tm/pr67811.C: New. + 2015-12-22 Peter Bergner PR target/68772 diff --git a/gcc/testsuite/g++.dg/tm/noexcept-1.C b/gcc/testsuite/g++.dg/tm/noexcept-1.C index bae1bea392c..dcbd3d8ee9c 100644 --- a/gcc/testsuite/g++.dg/tm/noexcept-1.C +++ b/gcc/testsuite/g++.dg/tm/noexcept-1.C @@ -32,5 +32,5 @@ int f3() return global; } -/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 6 "tmlower" } } */ +/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 12 "tmlower" } } */ /* { dg-final { scan-tree-dump-times "ITM_RU" 6 "tmmark" } } */ diff --git a/gcc/testsuite/g++.dg/tm/noexcept-4.C b/gcc/testsuite/g++.dg/tm/noexcept-4.C index af7cd8d9b76..82db6ab477f 100644 --- a/gcc/testsuite/g++.dg/tm/noexcept-4.C +++ b/gcc/testsuite/g++.dg/tm/noexcept-4.C @@ -29,5 +29,5 @@ int f3() + __transaction_atomic noexcept (global + 6); } -/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 6 "tmlower" } } */ +/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 12 "tmlower" } } */ /* { dg-final { scan-tree-dump-times "ITM_RU" 6 "tmmark" } } */ diff --git a/gcc/testsuite/g++.dg/tm/noexcept-5.C b/gcc/testsuite/g++.dg/tm/noexcept-5.C index 03aba5ac918..7744bfb2558 100644 --- a/gcc/testsuite/g++.dg/tm/noexcept-5.C +++ b/gcc/testsuite/g++.dg/tm/noexcept-5.C @@ -15,5 +15,5 @@ void f2(int x) } } } -/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 1 "tmlower" } } */ +/* { dg-final { scan-tree-dump-times "eh_must_not_throw" 2 "tmlower" } } */ /* { dg-final { scan-tree-dump-times "ITM_RU" 1 "tmmark" } } */ diff --git a/gcc/testsuite/g++.dg/tm/pr67811.C b/gcc/testsuite/g++.dg/tm/pr67811.C new file mode 100644 index 00000000000..90ab64c72e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/tm/pr67811.C @@ -0,0 +1,11 @@ +// { dg-do compile } +// { dg-options "-fgnu-tm" } + +void f() +{ + __transaction_relaxed { + try { throw 42; } + catch (...) { } + } +} + diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index 4583bd50fdd..fa092f1f0d9 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -1608,6 +1608,27 @@ examine_call_tm (unsigned *state, gimple_stmt_iterator *gsi) *state |= GTMA_HAVE_LOAD | GTMA_HAVE_STORE; } +/* Iterate through the statements in the sequence, moving labels + (and thus edges) of transactions from "label_norm" to "label_uninst". */ + +static tree +make_tm_uninst (gimple_stmt_iterator *gsi, bool *handled_ops_p, + struct walk_stmt_info *) +{ + gimple *stmt = gsi_stmt (*gsi); + + if (gtransaction *txn = dyn_cast (stmt)) + { + *handled_ops_p = true; + txn->label_uninst = txn->label_norm; + txn->label_norm = NULL; + } + else + *handled_ops_p = !gimple_has_substatements (stmt); + + return NULL_TREE; +} + /* Lower a GIMPLE_TRANSACTION statement. */ static void @@ -1670,20 +1691,49 @@ lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi) g = gimple_build_try (gimple_transaction_body (stmt), gimple_seq_alloc_with_stmt (g), GIMPLE_TRY_FINALLY); - gsi_insert_after (gsi, g, GSI_CONTINUE_LINKING); - gimple_transaction_set_body (stmt, NULL); + /* For a (potentially) outer transaction, create two paths. */ + gimple_seq uninst = NULL; + if (outer_state == NULL) + { + uninst = copy_gimple_seq_and_replace_locals (g); + /* In the uninstrumented copy, reset inner transactions to have only + an uninstrumented code path. */ + memset (&this_wi, 0, sizeof (this_wi)); + walk_gimple_seq (uninst, make_tm_uninst, NULL, &this_wi); + } + + tree label1 = create_artificial_label (UNKNOWN_LOCATION); + gsi_insert_after (gsi, gimple_build_label (label1), GSI_CONTINUE_LINKING); + gsi_insert_after (gsi, g, GSI_CONTINUE_LINKING); + gimple_transaction_set_label_norm (stmt, label1); /* If the transaction calls abort or if this is an outer transaction, add an "over" label afterwards. */ - if ((this_state & (GTMA_HAVE_ABORT)) + tree label3 = NULL; + if ((this_state & GTMA_HAVE_ABORT) + || outer_state == NULL || (gimple_transaction_subcode (stmt) & GTMA_IS_OUTER)) { - tree label = create_artificial_label (UNKNOWN_LOCATION); - gimple_transaction_set_label (stmt, label); - gsi_insert_after (gsi, gimple_build_label (label), GSI_CONTINUE_LINKING); + label3 = create_artificial_label (UNKNOWN_LOCATION); + gimple_transaction_set_label_over (stmt, label3); } + if (uninst != NULL) + { + gsi_insert_after (gsi, gimple_build_goto (label3), GSI_CONTINUE_LINKING); + + tree label2 = create_artificial_label (UNKNOWN_LOCATION); + gsi_insert_after (gsi, gimple_build_label (label2), GSI_CONTINUE_LINKING); + gsi_insert_seq_after (gsi, uninst, GSI_CONTINUE_LINKING); + gimple_transaction_set_label_uninst (stmt, label2); + } + + if (label3 != NULL) + gsi_insert_after (gsi, gimple_build_label (label3), GSI_CONTINUE_LINKING); + + gimple_transaction_set_body (stmt, NULL); + /* Record the set of operations found for use later. */ this_state |= gimple_transaction_subcode (stmt) & GTMA_DECLARATION_MASK; gimple_transaction_set_subcode (stmt, this_state); @@ -4113,35 +4163,6 @@ maybe_push_queue (struct cgraph_node *node, } } -/* Duplicate the basic blocks in QUEUE for use in the uninstrumented - code path. QUEUE are the basic blocks inside the transaction - represented in REGION. - - Later in split_code_paths() we will add the conditional to choose - between the two alternatives. */ - -static void -ipa_uninstrument_transaction (struct tm_region *region, - vec queue) -{ - gimple *transaction = region->transaction_stmt; - basic_block transaction_bb = gimple_bb (transaction); - int n = queue.length (); - basic_block *new_bbs = XNEWVEC (basic_block, n); - - copy_bbs (queue.address (), n, new_bbs, NULL, 0, NULL, NULL, transaction_bb, - true); - edge e = make_edge (transaction_bb, new_bbs[0], EDGE_TM_UNINSTRUMENTED); - add_phi_args_after_copy (new_bbs, n, e); - - // Now we will have a GIMPLE_ATOMIC with 3 possible edges out of it. - // a) EDGE_FALLTHRU into the transaction - // b) EDGE_TM_ABORT out of the transaction - // c) EDGE_TM_UNINSTRUMENTED into the uninstrumented blocks. - - free (new_bbs); -} - /* A subroutine of ipa_tm_scan_calls_transaction and ipa_tm_scan_calls_clone. Queue all callees within block BB. */ @@ -4189,43 +4210,23 @@ static void ipa_tm_scan_calls_transaction (struct tm_ipa_cg_data *d, cgraph_node_queue *callees_p) { - struct tm_region *r; - d->transaction_blocks_normal = BITMAP_ALLOC (&tm_obstack); d->all_tm_regions = all_tm_regions; - for (r = all_tm_regions; r; r = r->next) + for (tm_region *r = all_tm_regions; r; r = r->next) { vec bbs; basic_block bb; unsigned i; bbs = get_tm_region_blocks (r->entry_block, r->exit_blocks, NULL, - d->transaction_blocks_normal, false); - - // Generate the uninstrumented code path for this transaction. - ipa_uninstrument_transaction (r, bbs); + d->transaction_blocks_normal, false, false); FOR_EACH_VEC_ELT (bbs, i, bb) ipa_tm_scan_calls_block (callees_p, bb, false); bbs.release (); } - - // ??? copy_bbs should maintain cgraph edges for the blocks as it is - // copying them, rather than forcing us to do this externally. - cgraph_edge::rebuild_edges (); - - // ??? In ipa_uninstrument_transaction we don't try to update dominators - // because copy_bbs doesn't return a VEC like iterate_fix_dominators expects. - // Instead, just release dominators here so update_ssa recomputes them. - free_dominance_info (CDI_DOMINATORS); - - // When building the uninstrumented code path, copy_bbs will have invoked - // create_new_def_for starting an "ssa update context". There is only one - // instance of this context, so resolve ssa updates before moving on to - // the next function. - update_ssa (TODO_update_ssa); } /* Scan all calls in NODE as if this is the transactional clone, diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 5aad9ee3149..436ea146c1b 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -828,11 +828,21 @@ make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index) case GIMPLE_TRANSACTION: { - tree abort_label - = gimple_transaction_label (as_a (last)); - if (abort_label) - make_edge (bb, label_to_block (abort_label), EDGE_TM_ABORT); - fallthru = true; + gtransaction *txn = as_a (last); + tree label1 = gimple_transaction_label_norm (txn); + tree label2 = gimple_transaction_label_uninst (txn); + + if (label1) + make_edge (bb, label_to_block (label1), EDGE_FALLTHRU); + if (label2) + make_edge (bb, label_to_block (label2), + EDGE_TM_UNINSTRUMENTED | (label1 ? 0 : EDGE_FALLTHRU)); + + tree label3 = gimple_transaction_label_over (txn); + if (gimple_transaction_subcode (txn) & GTMA_HAVE_ABORT) + make_edge (bb, label_to_block (label3), EDGE_TM_ABORT); + + fallthru = false; } break; @@ -1517,13 +1527,30 @@ cleanup_dead_labels (void) case GIMPLE_TRANSACTION: { - gtransaction *trans_stmt = as_a (stmt); - tree label = gimple_transaction_label (trans_stmt); + gtransaction *txn = as_a (stmt); + + label = gimple_transaction_label_norm (txn); + if (label) + { + new_label = main_block_label (label); + if (new_label != label) + gimple_transaction_set_label_norm (txn, new_label); + } + + label = gimple_transaction_label_uninst (txn); + if (label) + { + new_label = main_block_label (label); + if (new_label != label) + gimple_transaction_set_label_uninst (txn, new_label); + } + + label = gimple_transaction_label_over (txn); if (label) { - tree new_label = main_block_label (label); + new_label = main_block_label (label); if (new_label != label) - gimple_transaction_set_label (trans_stmt, new_label); + gimple_transaction_set_label_over (txn, new_label); } } break; @@ -4732,9 +4759,18 @@ verify_gimple_in_seq_2 (gimple_seq stmts) static bool verify_gimple_transaction (gtransaction *stmt) { - tree lab = gimple_transaction_label (stmt); + tree lab; + + lab = gimple_transaction_label_norm (stmt); if (lab != NULL && TREE_CODE (lab) != LABEL_DECL) return true; + lab = gimple_transaction_label_uninst (stmt); + if (lab != NULL && TREE_CODE (lab) != LABEL_DECL) + return true; + lab = gimple_transaction_label_over (stmt); + if (lab != NULL && TREE_CODE (lab) != LABEL_DECL) + return true; + return verify_gimple_in_seq_2 (gimple_transaction_body (stmt)); } @@ -5642,11 +5678,15 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest) break; case GIMPLE_TRANSACTION: - /* The ABORT edge has a stored label associated with it, otherwise - the edges are simply redirectable. */ - if (e->flags == 0) - gimple_transaction_set_label (as_a (stmt), - gimple_block_label (dest)); + if (e->flags & EDGE_TM_ABORT) + gimple_transaction_set_label_over (as_a (stmt), + gimple_block_label (dest)); + else if (e->flags & EDGE_TM_UNINSTRUMENTED) + gimple_transaction_set_label_uninst (as_a (stmt), + gimple_block_label (dest)); + else + gimple_transaction_set_label_norm (as_a (stmt), + gimple_block_label (dest)); break; default: diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 36c96225449..88a6753cc63 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1518,13 +1518,15 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id) gtransaction *new_trans_stmt; s1 = remap_gimple_seq (gimple_transaction_body (old_trans_stmt), id); - copy = new_trans_stmt - = gimple_build_transaction ( - s1, - gimple_transaction_label (old_trans_stmt)); - gimple_transaction_set_subcode ( - new_trans_stmt, + copy = new_trans_stmt = gimple_build_transaction (s1); + gimple_transaction_set_subcode (new_trans_stmt, gimple_transaction_subcode (old_trans_stmt)); + gimple_transaction_set_label_norm (new_trans_stmt, + gimple_transaction_label_norm (old_trans_stmt)); + gimple_transaction_set_label_uninst (new_trans_stmt, + gimple_transaction_label_uninst (old_trans_stmt)); + gimple_transaction_set_label_over (new_trans_stmt, + gimple_transaction_label_over (old_trans_stmt)); } break;