From c6f63822c1911e571699fbc645abbb76f711fa37 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 16 Dec 2013 11:02:54 -0500
Subject: [PATCH 22/88] Introduce gimple_transaction

gcc/
	* coretypes.h (gimple_transaction): New typedef.
	(const_gimple_transaction): New typedef.

	* gimple.h (gimple_build_transaction): Return a gimple_transaction
	rather than a plain gimple.
	(gimple_transaction_body_ptr): Require a gimple_transaction rather
	than a plain gimple.
	(gimple_transaction_body): Likewise.
	(gimple_transaction_label_ptr): Likewise.
	(gimple_transaction_set_body): Likewise.
	(gimple_transaction_set_label): Likewise.
	(gimple_transaction_set_subcode): Likewise.
	(gimple_transaction_label): Require a const_gimple_transaction
	rather than a plain const_gimple.
	(gimple_transaction_subcode): Likewise.

	* gimple-low.c (lower_stmt): Add checked cast to
	gimple_transaction within GIMPLE_TRANSACTION case of switch
	statement.

	* gimple-pretty-print.c (dump_gimple_transaction): Require a
	gimple_transaction rather than a plain gimple.
	(pp_gimple_stmt_1): Add checked cast to gimple_transaction within
	GIMPLE_TRANSACTION case of switch statement.
	* gimple-streamer-in.c (input_gimple_stmt): Likewise.
	* gimple-streamer-out.c (output_gimple_stmt): Likewise.
	* gimple-walk.c (walk_gimple_op): Likewise.
	(walk_gimple_stmt): Likewise.

	* gimple.c (gimple_build_transaction): Return a gimple_transaction
	rather than a plain gimple.
	(gimple_copy): Add checked casts to gimple_transaction within
	GIMPLE_TRANSACTION case of switch statement.

	* gimplify.c (gimplify_transaction): Split local "g" into
	"body_stmt" and "trans_stmt", strengthening the type of the latter
	from gimple to gimple_transaction.

	* omp-low.c (lower_omp_1): Add checked cast to gimple_transaction
	within GIMPLE_TRANSACTION case of switch statement.

	* trans-mem.c (diagnose_tm_1): Add checked cast within
	GIMPLE_TRANSACTION case of switch statement, introducing a new
	local "trans_stmt".  Use it in place of "stmt".
	(examine_call_tm): Convert local from gimple to gimple_transaction.
	(tm_region::get_transaction_stmt): New method.
	(tm_region::transaction_stmt): Add clarification of type to the
	comment.
	(tm_region_init_0): Require a gimple_transaction rather than a
	plain gimple.
	(tm_region_init): Convert a check against GIMPLE_TRANSACTION to a
	dyn_cast<gimple_transaction> and new local.
	(transaction_subcode_ior): Add a new local, using the new
	get_transaction_stmt method to perform a checked cast.
	(propagate_tm_flags_out): Likewise.
	(expand_transaction): Add a checked cast using the new
	get_transaction_stmt method.
	(generate_tm_state): Likewise.
	(execute_tm_mark): Likewise.
	(ipa_tm_diagnose_transaction): Likewise.

	* tree-cfg.c (verify_gimple_transaction): Require a
	gimple_transaction rather than a plain gimple.
	(make_edges): Add checked cast within GIMPLE_TRANSACTION case of
	switch statement
	(cleanup_dead_labels): Likewise.
	(verify_gimple_stmt): Likewise.
	(verify_gimple_in_seq_2): Likewise.
	(verify_gimple_in_seq_2): Likewise.
	(gimple_redirect_edge_and_branch): Add checked cast.

	* tree-inline.c (remap_gimple_stmt): Add checked cast within
	GIMPLE_TRANSACTION case of switch statement, introducing a new
	local "old_trans_stmt".  Use it in place of "stmt".  Add new
	local "new_trans_stmt", using it to initialize "copy", and for
	type-safe operations as a transaction.
	(estimate_num_insns): Add checked cast within GIMPLE_TRANSACTION
	case of switch statement.
---
 gcc/coretypes.h           |  4 +++
 gcc/gimple-low.c          |  4 ++-
 gcc/gimple-pretty-print.c |  6 +++--
 gcc/gimple-streamer-in.c  |  3 ++-
 gcc/gimple-streamer-out.c |  7 +++--
 gcc/gimple-walk.c         |  8 +++---
 gcc/gimple.c              | 11 +++++---
 gcc/gimple.h              | 46 ++++++++++++++-------------------
 gcc/gimplify.c            | 13 +++++-----
 gcc/omp-low.c             |  4 ++-
 gcc/trans-mem.c           | 66 +++++++++++++++++++++++++++++++++--------------
 gcc/tree-cfg.c            | 19 ++++++++------
 gcc/tree-inline.c         | 19 +++++++++++---
 13 files changed, 131 insertions(+), 79 deletions(-)

diff --git a/gcc/coretypes.h b/gcc/coretypes.h
index 98636bb..a38d7bd 100644
--- a/gcc/coretypes.h
+++ b/gcc/coretypes.h
@@ -122,6 +122,10 @@ struct gimple_statement_call;
 typedef struct gimple_statement_call *gimple_call;
 typedef const struct gimple_statement_call *const_gimple_call;
 
+struct gimple_statement_transaction;
+typedef struct gimple_statement_transaction *gimple_transaction;
+typedef const struct gimple_statement_transaction *const_gimple_transaction;
+
 struct gimple_statement_return;
 typedef struct gimple_statement_return *gimple_return;
 typedef const struct gimple_statement_return *const_gimple_return;
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 04f87e2..4a4ad8a 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -361,7 +361,9 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
       return;
 
     case GIMPLE_TRANSACTION:
-      lower_sequence (gimple_transaction_body_ptr (stmt), data);
+      lower_sequence (gimple_transaction_body_ptr (
+			as_a <gimple_transaction> (stmt)),
+		      data);
       break;
 
     default:
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 2311f31..0c5287f 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1519,7 +1519,8 @@ dump_gimple_omp_return (pretty_printer *buffer, gimple gs, int spc, int flags)
 /* Dump a GIMPLE_TRANSACTION tuple on the pretty_printer BUFFER.  */
 
 static void
-dump_gimple_transaction (pretty_printer *buffer, gimple gs, int spc, int flags)
+dump_gimple_transaction (pretty_printer *buffer, gimple_transaction gs,
+			 int spc, int flags)
 {
   unsigned subcode = gimple_transaction_subcode (gs);
 
@@ -2257,7 +2258,8 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags)
       break;
 
     case GIMPLE_TRANSACTION:
-      dump_gimple_transaction (buffer, gs, spc, flags);
+      dump_gimple_transaction (buffer, as_a <gimple_transaction> (gs), spc,
+			       flags);
       break;
 
     default:
diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c
index c297ec3..a4130a5 100644
--- a/gcc/gimple-streamer-in.c
+++ b/gcc/gimple-streamer-in.c
@@ -200,7 +200,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
       break;
 
     case GIMPLE_TRANSACTION:
-      gimple_transaction_set_label (stmt, stream_read_tree (ib, data_in));
+      gimple_transaction_set_label (as_a <gimple_transaction> (stmt),
+				    stream_read_tree (ib, data_in));
       break;
 
     default:
diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c
index 77fc3fa..cc87e88 100644
--- a/gcc/gimple-streamer-out.c
+++ b/gcc/gimple-streamer-out.c
@@ -177,8 +177,11 @@ output_gimple_stmt (struct output_block *ob, gimple stmt)
       break;
 
     case GIMPLE_TRANSACTION:
-      gcc_assert (gimple_transaction_body (stmt) == NULL);
-      stream_write_tree (ob, gimple_transaction_label (stmt), true);
+      {
+	gimple_transaction trans_stmt = as_a <gimple_transaction> (stmt);
+	gcc_assert (gimple_transaction_body (trans_stmt) == NULL);
+	stream_write_tree (ob, gimple_transaction_label (trans_stmt), true);
+      }
       break;
 
     default:
diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
index 40d2145..e41a9a5 100644
--- a/gcc/gimple-walk.c
+++ b/gcc/gimple-walk.c
@@ -438,8 +438,9 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
       break;
 
     case GIMPLE_TRANSACTION:
-      ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op,
-		       wi, pset);
+      ret = walk_tree (gimple_transaction_label_ptr (
+			 as_a <gimple_transaction> (stmt)),
+		       callback_op, wi, pset);
       if (ret)
 	return ret;
       break;
@@ -618,7 +619,8 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
       break;
 
     case GIMPLE_TRANSACTION:
-      ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
+      ret = walk_gimple_seq_mod (gimple_transaction_body_ptr (
+				   as_a <gimple_transaction> (stmt)),
 			     callback_stmt, callback_op, wi);
       if (ret)
 	return wi->callback_result;
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 2d86191..68ede1f 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1101,10 +1101,11 @@ gimple_build_omp_atomic_store (tree val)
 
 /* Build a GIMPLE_TRANSACTION statement.  */
 
-gimple
+gimple_transaction
 gimple_build_transaction (gimple_seq body, tree label)
 {
-  gimple p = gimple_alloc (GIMPLE_TRANSACTION, 0);
+  gimple_transaction p =
+    as_a <gimple_transaction> (gimple_alloc (GIMPLE_TRANSACTION, 0));
   gimple_transaction_set_body (p, body);
   gimple_transaction_set_label (p, label);
   return p;
@@ -1765,8 +1766,10 @@ gimple_copy (gimple stmt)
 	  break;
 
 	case GIMPLE_TRANSACTION:
-	  new_seq = gimple_seq_copy (gimple_transaction_body (stmt));
-	  gimple_transaction_set_body (copy, new_seq);
+	  new_seq = gimple_seq_copy (gimple_transaction_body (
+				       as_a <gimple_transaction> (stmt)));
+	  gimple_transaction_set_body (as_a <gimple_transaction> (copy),
+				       new_seq);
 	  break;
 
 	case GIMPLE_WITH_CLEANUP_EXPR:
diff --git a/gcc/gimple.h b/gcc/gimple.h
index d2dc7ce..4ddcb24 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1359,7 +1359,7 @@ gimple gimple_build_omp_target (gimple_seq, int, tree);
 gimple gimple_build_omp_teams (gimple_seq, tree);
 gimple gimple_build_omp_atomic_load (tree, tree);
 gimple gimple_build_omp_atomic_store (tree);
-gimple gimple_build_transaction (gimple_seq, tree);
+gimple_transaction gimple_build_transaction (gimple_seq, tree);
 gimple gimple_build_predict (enum br_predictor, enum prediction);
 extern void gimple_seq_add_stmt (gimple_seq *, gimple);
 extern void gimple_seq_add_stmt_without_update (gimple_seq *, gimple);
@@ -5545,78 +5545,70 @@ gimple_omp_continue_set_control_use (gimple g, tree use)
   omp_continue_stmt->control_use = use;
 }
 
-/* Return a pointer to the body for the GIMPLE_TRANSACTION statement GS.  */
+/* Return a pointer to the body for the GIMPLE_TRANSACTION statement
+   TRANSACTION_STMT.  */
 
 static inline gimple_seq *
-gimple_transaction_body_ptr (gimple gs)
+gimple_transaction_body_ptr (gimple_transaction transaction_stmt)
 {
-  gimple_statement_transaction *transaction_stmt =
-    as_a <gimple_statement_transaction *> (gs);
   return &transaction_stmt->body;
 }
 
-/* Return the body for the GIMPLE_TRANSACTION statement GS.  */
+/* Return the body for the GIMPLE_TRANSACTION statement TRANSACTION_STMT.  */
 
 static inline gimple_seq
-gimple_transaction_body (gimple gs)
+gimple_transaction_body (gimple_transaction transaction_stmt)
 {
-  return *gimple_transaction_body_ptr (gs);
+  return *gimple_transaction_body_ptr (transaction_stmt);
 }
 
 /* Return the label associated with a GIMPLE_TRANSACTION.  */
 
 static inline tree
-gimple_transaction_label (const_gimple gs)
+gimple_transaction_label (const_gimple_transaction transaction_stmt)
 {
-  const gimple_statement_transaction *transaction_stmt =
-    as_a <const gimple_statement_transaction *> (gs);
   return transaction_stmt->label;
 }
 
 static inline tree *
-gimple_transaction_label_ptr (gimple gs)
+gimple_transaction_label_ptr (gimple_transaction transaction_stmt)
 {
-  gimple_statement_transaction *transaction_stmt =
-    as_a <gimple_statement_transaction *> (gs);
   return &transaction_stmt->label;
 }
 
 /* Return the subcode associated with a GIMPLE_TRANSACTION.  */
 
 static inline unsigned int
-gimple_transaction_subcode (const_gimple gs)
+gimple_transaction_subcode (const_gimple_transaction transaction_stmt)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  return gs->subcode;
+  return transaction_stmt->subcode;
 }
 
-/* Set BODY to be the body for the GIMPLE_TRANSACTION statement GS.  */
+/* Set BODY to be the body for the GIMPLE_TRANSACTION statement
+   TRANSACTION_STMT.  */
 
 static inline void
-gimple_transaction_set_body (gimple gs, gimple_seq body)
+gimple_transaction_set_body (gimple_transaction transaction_stmt,
+			     gimple_seq body)
 {
-  gimple_statement_transaction *transaction_stmt =
-    as_a <gimple_statement_transaction *> (gs);
   transaction_stmt->body = body;
 }
 
 /* Set the label associated with a GIMPLE_TRANSACTION.  */
 
 static inline void
-gimple_transaction_set_label (gimple gs, tree label)
+gimple_transaction_set_label (gimple_transaction transaction_stmt, tree label)
 {
-  gimple_statement_transaction *transaction_stmt =
-    as_a <gimple_statement_transaction *> (gs);
   transaction_stmt->label = label;
 }
 
 /* Set the subcode associated with a GIMPLE_TRANSACTION.  */
 
 static inline void
-gimple_transaction_set_subcode (gimple gs, unsigned int subcode)
+gimple_transaction_set_subcode (gimple_transaction transaction_stmt,
+				unsigned int subcode)
 {
-  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
-  gs->subcode = subcode;
+  transaction_stmt->subcode = subcode;
 }
 
 
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index f1aee13..2230a96 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -7359,7 +7359,8 @@ static enum gimplify_status
 gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
 {
   tree expr = *expr_p, temp, tbody = TRANSACTION_EXPR_BODY (expr);
-  gimple g;
+  gimple body_stmt;
+  gimple_transaction trans_stmt;
   gimple_seq body = NULL;
   int subcode = 0;
 
@@ -7376,17 +7377,17 @@ gimplify_transaction (tree *expr_p, gimple_seq *pre_p)
   push_gimplify_context ();
   temp = voidify_wrapper_expr (*expr_p, NULL);
 
-  g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
-  pop_gimplify_context (g);
+  body_stmt = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
+  pop_gimplify_context (body_stmt);
 
-  g = gimple_build_transaction (body, NULL);
+  trans_stmt = gimple_build_transaction (body, NULL);
   if (TRANSACTION_EXPR_OUTER (expr))
     subcode = GTMA_IS_OUTER;
   else if (TRANSACTION_EXPR_RELAXED (expr))
     subcode = GTMA_IS_RELAXED;
-  gimple_transaction_set_subcode (g, subcode);
+  gimple_transaction_set_subcode (trans_stmt, subcode);
 
-  gimplify_seq_add_stmt (pre_p, g);
+  gimplify_seq_add_stmt (pre_p, trans_stmt);
 
   if (temp)
     {
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 58a958e..b8a131b 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -10468,7 +10468,9 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
       lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
       break;
     case GIMPLE_TRANSACTION:
-      lower_omp (gimple_transaction_body_ptr (stmt), ctx);
+      lower_omp (gimple_transaction_body_ptr (
+                   as_a <gimple_transaction> (stmt)),
+		 ctx);
       break;
     case GIMPLE_BIND:
       lower_omp (gimple_bind_body_ptr (as_a <gimple_bind> (stmt)), ctx);
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index fe8be6c..82f93b9 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -755,9 +755,10 @@ diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
 
     case GIMPLE_TRANSACTION:
       {
+	gimple_transaction trans_stmt = as_a <gimple_transaction> (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),
@@ -767,7 +768,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),
@@ -783,7 +784,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;
@@ -796,7 +797,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);
 	  }
       }
@@ -1598,7 +1599,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;
+  gimple_transaction stmt = as_a <gimple_transaction> (gsi_stmt (*gsi));
   unsigned int *outer_state = (unsigned int *) wi->info;
   unsigned int this_state = 0;
   struct walk_stmt_info this_wi;
@@ -1794,6 +1796,22 @@ make_pass_lower_tm (gcc::context *ctxt)
 
 struct tm_region
 {
+public:
+
+  /* The field "transaction_stmt" is initially a gimple_transaction,
+     but eventually gets lowered to a gimple_call (to BUILT_IN_TM_START).
+
+     Helper method to get it as a gimple_transaction, with code-checking
+     in a checked-build.  */
+
+  gimple_transaction
+  get_transaction_stmt () const
+  {
+    return as_a <gimple_transaction> (transaction_stmt);
+  }
+
+public:
+
   /* Link to the next unnested transaction.  */
   struct tm_region *next;
 
@@ -1805,7 +1823,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 gimple_transaction or a gimple_call.  */
   gimple transaction_stmt;
 
   /* After TM_MARK expands the GIMPLE_TRANSACTION into a call to
@@ -1848,7 +1867,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,
+		  gimple_transaction stmt)
 {
   struct tm_region *region;
 
@@ -1963,8 +1983,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 (gimple_transaction trans_stmt = dyn_cast <gimple_transaction> (g))
+	  region = tm_region_init_0 (region, bb, trans_stmt);
 
       /* Process subsequent blocks.  */
       FOR_EACH_EDGE (e, ei, bb->succs)
@@ -2073,8 +2094,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);
+      gimple_transaction transaction_stmt = region->get_transaction_stmt ();
+      flags |= gimple_transaction_subcode (transaction_stmt);
+      gimple_transaction_set_subcode (transaction_stmt, flags);
     }
 }
 
@@ -2698,7 +2720,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;
@@ -2903,8 +2925,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);
+      gimple_transaction 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
@@ -2912,7 +2934,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;
@@ -2928,11 +2950,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);
@@ -2967,7 +2991,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
@@ -4664,7 +4689,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)
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index b553260..afd7f3d 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -163,7 +163,7 @@ static inline bool stmt_starts_bb_p (gimple, gimple);
 static int gimple_verify_flow_info (void);
 static void gimple_make_forwarder_block (edge);
 static gimple first_non_label_stmt (basic_block);
-static bool verify_gimple_transaction (gimple);
+static bool verify_gimple_transaction (gimple_transaction);
 static bool call_can_make_abnormal_goto (gimple);
 
 /* Flowgraph optimization and cleanup.  */
@@ -859,7 +859,8 @@ make_edges (void)
 
 	    case GIMPLE_TRANSACTION:
 	      {
-		tree abort_label = gimple_transaction_label (last);
+		tree abort_label =
+		  gimple_transaction_label (as_a <gimple_transaction> (last));
 		if (abort_label)
 		  make_edge (bb, label_to_block (abort_label), EDGE_TM_ABORT);
 		fallthru = true;
@@ -1473,12 +1474,13 @@ cleanup_dead_labels (void)
 
 	case GIMPLE_TRANSACTION:
 	  {
-	    tree label = gimple_transaction_label (stmt);
+	    gimple_transaction trans_stmt = as_a <gimple_transaction> (stmt);
+	    tree label = gimple_transaction_label (trans_stmt);
 	    if (label)
 	      {
 		tree new_label = main_block_label (label);
 		if (new_label != label)
-		  gimple_transaction_set_label (stmt, new_label);
+		  gimple_transaction_set_label (trans_stmt, new_label);
 	      }
 	  }
 	  break;
@@ -4517,7 +4519,7 @@ verify_gimple_stmt (gimple stmt)
       return false;
 
     case GIMPLE_TRANSACTION:
-      return verify_gimple_transaction (stmt);
+      return verify_gimple_transaction (as_a <gimple_transaction> (stmt));
 
     /* Tuples that do not have tree operands.  */
     case GIMPLE_NOP:
@@ -4646,7 +4648,7 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
 	  break;
 
 	case GIMPLE_TRANSACTION:
-	  err |= verify_gimple_transaction (stmt);
+	  err |= verify_gimple_transaction (as_a <gimple_transaction> (stmt));
 	  break;
 
 	default:
@@ -4666,7 +4668,7 @@ verify_gimple_in_seq_2 (gimple_seq stmts)
    is a problem, otherwise false.  */
 
 static bool
-verify_gimple_transaction (gimple stmt)
+verify_gimple_transaction (gimple_transaction stmt)
 {
   tree lab = gimple_transaction_label (stmt);
   if (lab != NULL && TREE_CODE (lab) != LABEL_DECL)
@@ -5579,7 +5581,8 @@ gimple_redirect_edge_and_branch (edge e, basic_block dest)
       /* The ABORT edge has a stored label associated with it, otherwise
 	 the edges are simply redirectable.  */
       if (e->flags == 0)
-	gimple_transaction_set_label (stmt, gimple_block_label (dest));
+	gimple_transaction_set_label (as_a <gimple_transaction> (stmt),
+				      gimple_block_label (dest));
       break;
 
     default:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 5a98623..0bfa44c 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1453,9 +1453,19 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id)
 	  break;
 
 	case GIMPLE_TRANSACTION:
-	  s1 = remap_gimple_seq (gimple_transaction_body (stmt), id);
-	  copy = gimple_build_transaction (s1, gimple_transaction_label (stmt));
-	  gimple_transaction_set_subcode (copy, gimple_transaction_subcode (stmt));
+	  {
+	    gimple_transaction old_trans_stmt =
+	      as_a <gimple_transaction> (stmt);
+	    gimple_transaction 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,
+	      gimple_transaction_subcode (old_trans_stmt));
+	  }
 	  break;
 
 	default:
@@ -4010,7 +4020,8 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
 
     case GIMPLE_TRANSACTION:
       return (weights->tm_cost
-	      + estimate_num_insns_seq (gimple_transaction_body (stmt),
+	      + estimate_num_insns_seq (gimple_transaction_body (
+					  as_a <gimple_transaction> (stmt)),
 					weights));
 
     default:
-- 
1.8.5.3

