re PR ipa/67811 ([TM] ICE with try-block in transaction)
authorRichard Henderson <rth@redhat.com>
Tue, 22 Dec 2015 19:42:24 +0000 (11:42 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 22 Dec 2015 19:42:24 +0000 (11:42 -0800)
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

16 files changed:
gcc/ChangeLog
gcc/gimple-pretty-print.c
gcc/gimple-streamer-in.c
gcc/gimple-streamer-out.c
gcc/gimple-walk.c
gcc/gimple.c
gcc/gimple.h
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tm/noexcept-1.C
gcc/testsuite/g++.dg/tm/noexcept-4.C
gcc/testsuite/g++.dg/tm/noexcept-5.C
gcc/testsuite/g++.dg/tm/pr67811.C [new file with mode: 0644]
gcc/trans-mem.c
gcc/tree-cfg.c
gcc/tree-inline.c

index 11f53c769014670961856966ad999b9c3584c1af..a9e73f45e6af290756e597cdcdcd93964476263f 100644 (file)
@@ -1,3 +1,38 @@
+2015-12-22  Richard Henderson  <rth@redhat.com>
+
+       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  <bergner@vnet.ibm.com>
 
        PR target/68772
index 01e9b6b004c8f7f65274189821db2f75c7dd9432..41e4c5e8dabf425f043153749bc00cdc09bad50b 100644 (file)
@@ -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);
-       }
     }
 }
 
index 44bcc11f4e2fc73c05af4f3555e166018227bef9..6310717c7c64d5a893c8413d81a46e374ed497ad 100644 (file)
@@ -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 <gtransaction *> (stmt),
-                                   stream_read_tree (ib, data_in));
+      gimple_transaction_set_label_norm (as_a <gtransaction *> (stmt),
+                                        stream_read_tree (ib, data_in));
+      gimple_transaction_set_label_uninst (as_a <gtransaction *> (stmt),
+                                          stream_read_tree (ib, data_in));
+      gimple_transaction_set_label_over (as_a <gtransaction *> (stmt),
+                                        stream_read_tree (ib, data_in));
       break;
 
     default:
index 1431f5ce3c90d7808a85dccfcde5c8b4997ceb81..cbcb4db4a6247607f559450ef08f42b43c37dd3c 100644 (file)
@@ -180,9 +180,11 @@ output_gimple_stmt (struct output_block *ob, gimple *stmt)
 
     case GIMPLE_TRANSACTION:
       {
-       gtransaction *trans_stmt = as_a <gtransaction *> (stmt);
-       gcc_assert (gimple_transaction_body (trans_stmt) == NULL);
-       stream_write_tree (ob, gimple_transaction_label (trans_stmt), true);
+       gtransaction *txn = as_a <gtransaction *> (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;
 
index 850cf57fa6508dee5e96c139dd1d226353d28b59..b8bae505b66a1a229d76f442e8a3dcf3d12b7885 100644 (file)
@@ -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 <gtransaction *> (stmt)),
-                      callback_op, wi, pset);
-      if (ret)
-       return ret;
+      {
+       gtransaction *txn = as_a <gtransaction *> (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:
index bf552a7ae9cd44e0daf828b97c3100e0cb13edbd..49663dfe7b12180581be620a329d2877657a0379 100644 (file)
@@ -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 <gtransaction *> (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;
 }
 
index dc61043fafca15297ad758018a1b24a5162c5977..adfe071a0eb065a4a9199e966e154f3f97b7fcbf 100644 (file)
@@ -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 *
index 438efba57e12a71fedfbc9b0e47c00779f46b86e..62b0e64350631d113eb41285cfb3b04a2efa1539 100644 (file)
@@ -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))
index 19fccfd53160b3af3a52ac5cce5d385a285a27e7..3c2e2aca9e5f4541ad3c40b5422f12d4d484f395 100644 (file)
@@ -1,3 +1,10 @@
+2015-12-22  Richard Henderson  <rth@redhat.com>
+
+       * 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  <bergner@vnet.ibm.com>
 
        PR target/68772
index bae1bea392ca2e0739cc6fd1f384ed46c4576acf..dcbd3d8ee9c6736ec67244e4f4d1677d88772776 100644 (file)
@@ -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" } } */
index af7cd8d9b76470449b814bc3875a2a82ae939c55..82db6ab477f5fea41086f8cd51098d9e18f72212 100644 (file)
@@ -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" } } */
index 03aba5ac9182d5878e7606b403921297dfeba3f2..7744bfb2558508c85f58d1b84618708b0a1646e4 100644 (file)
@@ -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 (file)
index 0000000..90ab64c
--- /dev/null
@@ -0,0 +1,11 @@
+// { dg-do compile }
+// { dg-options "-fgnu-tm" }
+
+void f()
+{
+  __transaction_relaxed {
+    try { throw 42; }
+    catch (...) { }
+  }
+}
+
index 4583bd50fdda840333b25dfff8a43968905451d6..fa092f1f0d977762f02c45293fee3a1e89555453 100644 (file)
@@ -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 <gtransaction *> (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<basic_block> 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<basic_block> 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,
index 5aad9ee3149695bc7aa0c501ff95573580a0e1f8..436ea146c1bc22e2eb30fe6eeea962c0529552bc 100644 (file)
@@ -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 <gtransaction *> (last));
-       if (abort_label)
-         make_edge (bb, label_to_block (abort_label), EDGE_TM_ABORT);
-       fallthru = true;
+        gtransaction *txn = as_a <gtransaction *> (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 <gtransaction *> (stmt);
-           tree label = gimple_transaction_label (trans_stmt);
+           gtransaction *txn = as_a <gtransaction *> (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 <gtransaction *> (stmt),
-                                     gimple_block_label (dest));
+      if (e->flags & EDGE_TM_ABORT)
+       gimple_transaction_set_label_over (as_a <gtransaction *> (stmt),
+                                          gimple_block_label (dest));
+      else if (e->flags & EDGE_TM_UNINSTRUMENTED)
+       gimple_transaction_set_label_uninst (as_a <gtransaction *> (stmt),
+                                            gimple_block_label (dest));
+      else
+       gimple_transaction_set_label_norm (as_a <gtransaction *> (stmt),
+                                          gimple_block_label (dest));
       break;
 
     default:
index 36c9622544927c3e7c566977d6ba5520c5cb7a45..88a6753cc633100a2089cae177a92aac8fa1af6c 100644 (file)
@@ -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;