This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] 19/n: trans-mem: compiler tree/gimple stuff


These are misc tree and gimple patches, which I consider front-ish-end changes.

Index: gcc/tree.c
===================================================================
--- gcc/tree.c (.../trunk) (revision 180744)
+++ gcc/tree.c (.../branches/transactional-memory) (revision 180773)
@@ -9594,6 +9594,9 @@ build_common_builtin_nodes (void)
integer_type_node, NULL_TREE);
local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER,
"__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW | ECF_LEAF);
+ if (flag_tm)
+ apply_tm_attr (builtin_decl_explicit (BUILT_IN_EH_POINTER),
+ get_identifier ("transaction_pure"));


tmp = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
ftype = build_function_type_list (tmp, integer_type_node, NULL_TREE);
Index: gcc/tree.h
===================================================================
--- gcc/tree.h (.../trunk) (revision 180744)
+++ gcc/tree.h (.../branches/transactional-memory) (revision 180773)
@@ -539,6 +539,9 @@ struct GTY(()) tree_common {
ENUM_IS_SCOPED in
ENUMERAL_TYPE


+       TRANSACTION_EXPR_OUTER in
+           TRANSACTION_EXPR
+
    public_flag:

        TREE_OVERFLOW in
@@ -566,6 +569,9 @@ struct GTY(()) tree_common {
        OMP_CLAUSE_PRIVATE_DEBUG in
            OMP_CLAUSE_PRIVATE

+       TRANSACTION_EXPR_RELAXED in
+           TRANSACTION_EXPR
+
    private_flag:

        TREE_PRIVATE in
@@ -1808,6 +1814,14 @@ extern void protected_set_expr_location
 #define CALL_EXPR_ARGP(NODE) \
   (&(TREE_OPERAND (CALL_EXPR_CHECK (NODE), 0)) + 3)

+/* TM directives and accessors.  */
+#define TRANSACTION_EXPR_BODY(NODE) \
+  TREE_OPERAND (TRANSACTION_EXPR_CHECK (NODE), 0)
+#define TRANSACTION_EXPR_OUTER(NODE) \
+  (TRANSACTION_EXPR_CHECK (NODE)->base.static_flag)
+#define TRANSACTION_EXPR_RELAXED(NODE) \
+  (TRANSACTION_EXPR_CHECK (NODE)->base.public_flag)
+
 /* OpenMP directive and clause accessors.  */

 #define OMP_BODY(NODE) \
@@ -3452,6 +3466,34 @@ struct GTY(())
 #define DECL_NO_INLINE_WARNING_P(NODE) \
   (FUNCTION_DECL_CHECK (NODE)->function_decl.no_inline_warning_flag)

+/* Nonzero in a FUNCTION_DECL means this function is the transactional
+   clone of a function - called only from inside transactions.  */
+#define DECL_IS_TM_CLONE(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.tm_clone_flag)
+
+/* Nonzero if a FUNCTION_CODE is a TM load/store.  */
+#define BUILTIN_TM_LOAD_STORE_P(FN) \
+  ((FN) >= BUILT_IN_TM_STORE_1 && (FN) <= BUILT_IN_TM_LOAD_RFW_LDOUBLE)
+
+/* Nonzero if a FUNCTION_CODE is a TM load.  */
+#define BUILTIN_TM_LOAD_P(FN) \
+  ((FN) >= BUILT_IN_TM_LOAD_1 && (FN) <= BUILT_IN_TM_LOAD_RFW_LDOUBLE)
+
+/* Nonzero if a FUNCTION_CODE is a TM store.  */
+#define BUILTIN_TM_STORE_P(FN) \
+  ((FN) >= BUILT_IN_TM_STORE_1 && (FN) <= BUILT_IN_TM_STORE_WAW_LDOUBLE)
+
+#define CASE_BUILT_IN_TM_LOAD(FN)	\
+  case BUILT_IN_TM_LOAD_##FN:		\
+  case BUILT_IN_TM_LOAD_RAR_##FN:	\
+  case BUILT_IN_TM_LOAD_RAW_##FN:	\
+  case BUILT_IN_TM_LOAD_RFW_##FN
+
+#define CASE_BUILT_IN_TM_STORE(FN)	\
+  case BUILT_IN_TM_STORE_##FN:		\
+  case BUILT_IN_TM_STORE_WAR_##FN:	\
+  case BUILT_IN_TM_STORE_WAW_##FN
+
 /* Nonzero in a FUNCTION_DECL that should be always inlined by the inliner
    disregarding size and cost heuristics.  This is equivalent to using
    the always_inline attribute without the required diagnostics if the
@@ -3539,8 +3581,9 @@ struct GTY(()) tree_function_decl {
   unsigned pure_flag : 1;
   unsigned looping_const_or_pure_flag : 1;
   unsigned has_debug_args_flag : 1;
+  unsigned tm_clone_flag : 1;

-  /* 2 bits left */
+  /* 1 bit left */
 };

 /* The source language of the translation-unit.  */
@@ -5174,6 +5217,8 @@ extern void expand_return (tree);

 /* In tree-eh.c */
 extern void using_eh_for_cleanups (void);
+extern int struct_ptr_eq (const void *, const void *);
+extern hashval_t struct_ptr_hash (const void *);

/* In fold-const.c */

@@ -5543,6 +5588,8 @@ extern tree build_duplicate_type (tree);
 #define ECF_NOVOPS		  (1 << 9)
 /* The function does not lead to calls within current function unit.  */
 #define ECF_LEAF		  (1 << 10)
+/* Nonzero if this call performs a transactional memory operation.  */
+#define ECF_TM_OPS		  (1 << 11)

 extern int flags_from_decl_or_type (const_tree);
 extern int call_expr_flags (const_tree);
@@ -5593,6 +5640,8 @@ extern void init_attributes (void);
    a decl attribute to the declaration rather than to its type).  */
 extern tree decl_attributes (tree *, tree, int);

+extern void apply_tm_attr (tree, tree);
+
 /* In integrate.c */
 extern void set_decl_abstract_flags (tree, int);
 extern void set_decl_origin_self (tree);
@@ -5805,6 +5854,21 @@ extern unsigned HOST_WIDE_INT compute_bu
 extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
 extern tree build_personality_function (const char *);

+/* In trans-mem.c.  */
+extern tree build_tm_abort_call (location_t, bool);
+extern bool is_tm_safe (const_tree);
+extern bool is_tm_pure (const_tree);
+extern bool is_tm_may_cancel_outer (tree);
+extern bool is_tm_ending_fndecl (tree);
+extern void record_tm_replacement (tree, tree);
+extern void tm_malloc_replacement (tree);
+
+static inline bool
+is_tm_safe_or_pure (tree x)
+{
+  return is_tm_safe (x) || is_tm_pure (x);
+}
+
 /* In tree-inline.c.  */

 void init_inline_once (void);
Index: gcc/attribs.c
===================================================================
--- gcc/attribs.c	(.../trunk)	(revision 180744)
+++ gcc/attribs.c	(.../branches/transactional-memory)	(revision 180773)
@@ -166,7 +166,8 @@ init_attributes (void)
 	  gcc_assert (strcmp (attribute_tables[i][j].name,
 			      attribute_tables[i][k].name));
     }
-  /* Check that no name occurs in more than one table.  */
+  /* Check that no name occurs in more than one table.  Names that
+     begin with '*' are exempt, and may be overridden.  */
   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     {
       size_t j, k, l;
@@ -174,8 +175,9 @@ init_attributes (void)
       for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
 	for (k = 0; attribute_tables[i][k].name != NULL; k++)
 	  for (l = 0; attribute_tables[j][l].name != NULL; l++)
-	    gcc_assert (strcmp (attribute_tables[i][k].name,
-				attribute_tables[j][l].name));
+	    gcc_assert (attribute_tables[i][k].name[0] == '*'
+			|| strcmp (attribute_tables[i][k].name,
+				   attribute_tables[j][l].name));
     }
 #endif

@@ -207,7 +209,7 @@ register_attribute (const struct attribu
   slot = htab_find_slot_with_hash (attribute_hash, &str,
 				   substring_hash (str.str, str.length),
 				   INSERT);
-  gcc_assert (!*slot);
+  gcc_assert (!*slot || attr->name[0] == '*');
   *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
 }

@@ -484,3 +486,12 @@ decl_attributes (tree *node, tree attrib

   return returned_attrs;
 }
+
+/* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
+   to the method FNDECL.  */
+
+void
+apply_tm_attr (tree fndecl, tree attr)
+{
+  decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
+}
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	(.../trunk)	(revision 180744)
+++ gcc/targhooks.c	(.../branches/transactional-memory)	(revision 180773)
@@ -1214,6 +1214,12 @@ default_have_conditional_execution (void
 #endif
 }

+tree
+default_builtin_tm_load_store (tree ARG_UNUSED (type))
+{
+  return NULL_TREE;
+}
+
 /* Compute cost of moving registers to/from memory.  */

int
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h (.../trunk) (revision 180744)
+++ gcc/targhooks.h (.../branches/transactional-memory) (revision 180773)
@@ -152,6 +152,9 @@ extern bool default_addr_space_subset_p
extern rtx default_addr_space_convert (rtx, tree, tree);
extern unsigned int default_case_values_threshold (void);
extern bool default_have_conditional_execution (void);
+
+extern tree default_builtin_tm_load_store (tree);
+
extern int default_memory_move_cost (enum machine_mode, reg_class_t, bool);
extern int default_register_move_cost (enum machine_mode, reg_class_t,
reg_class_t);
Index: gcc/gimple.def
===================================================================
--- gcc/gimple.def (.../trunk) (revision 180744)
+++ gcc/gimple.def (.../branches/transactional-memory) (revision 180773)
@@ -124,6 +124,14 @@ DEFGSCODE(GIMPLE_ASM, "gimple_asm", GSS_
CHAIN is the optional static chain link for nested functions. */
DEFGSCODE(GIMPLE_CALL, "gimple_call", GSS_CALL)


+/* GIMPLE_TRANSACTION <BODY, LABEL> represents __transaction_atomic and
+   __transaction_relaxed blocks.
+   BODY is the sequence of statements inside the transaction.
+   LABEL is a label for the statement immediately following the
+   transaction.  This is before RETURN so that it has MEM_OPS,
+   so that it can clobber global memory.  */
+DEFGSCODE(GIMPLE_TRANSACTION, "gimple_transaction", GSS_TRANSACTION)
+
 /* GIMPLE_RETURN <RETVAL> represents return statements.

RETVAL is the value to return or NULL. If a value is returned it
@@ -151,6 +159,12 @@ DEFGSCODE(GIMPLE_EH_FILTER, "gimple_eh_f
be invoked if an exception propagates to this point. */
DEFGSCODE(GIMPLE_EH_MUST_NOT_THROW, "gimple_eh_must_not_throw", GSS_EH_MNT)


+/* GIMPLE_EH_ELSE <N_BODY, E_BODY> must be the sole contents of
+   a GIMPLE_TRY_FINALLY node.  For all normal exits from the try block,
+   we N_BODY is run; for all exception exits from the try block,
+   E_BODY is run.  */
+DEFGSCODE(GIMPLE_EH_ELSE, "gimple_eh_else", GSS_EH_ELSE)
+
 /* GIMPLE_RESX resumes execution after an exception.  */
 DEFGSCODE(GIMPLE_RESX, "gimple_resx", GSS_EH_CTRL)

Index: gcc/builtin-types.def
===================================================================
--- gcc/builtin-types.def (.../trunk) (revision 180744)
+++ gcc/builtin-types.def (.../branches/transactional-memory) (revision 180773)
@@ -477,3 +477,24 @@ DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_INT_I
DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
+
+
+DEF_FUNCTION_TYPE_1 (BT_FN_I1_VPTR, BT_I1, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I2_VPTR, BT_I2, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I4_VPTR, BT_I4, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_I8_VPTR, BT_I8, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_VPTR, BT_FLOAT, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_VPTR, BT_DOUBLE, BT_VOLATILE_PTR)
+DEF_FUNCTION_TYPE_1 (BT_FN_LDOUBLE_VPTR, BT_LONGDOUBLE, BT_VOLATILE_PTR)
+
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I1, BT_VOID, BT_VOLATILE_PTR, BT_I1)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I2, BT_VOID, BT_VOLATILE_PTR, BT_I2)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I4, BT_VOID, BT_VOLATILE_PTR, BT_I4)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_I8, BT_VOID, BT_VOLATILE_PTR, BT_I8)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_FLOAT, BT_VOID, BT_VOLATILE_PTR, BT_FLOAT)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_DOUBLE, BT_VOID,
+ BT_VOLATILE_PTR, BT_DOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_LDOUBLE, BT_VOID,
+ BT_VOLATILE_PTR, BT_LONGDOUBLE)
+DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VPTR_SIZE, BT_VOID,
+ BT_VOLATILE_PTR, BT_SIZE)
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def (.../trunk) (revision 180744)
+++ gcc/builtins.def (.../branches/transactional-memory) (revision 180773)
@@ -142,6 +142,13 @@ along with GCC; see the file COPYING3.
false, true, true, ATTRS, false, \
(flag_openmp || flag_tree_parallelize_loops))


+/* Builtin used by the implementation of GNU TM. These
+ functions are mapped to the actual implementation of the STM library. */
+#undef DEF_TM_BUILTIN
+#define DEF_TM_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
+ DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
+ false, true, true, ATTRS, false, flag_tm)
+
/* Define an attribute list for math functions that are normally
"impure" because some of them may write into global memory for
`errno'. If !flag_errno_math they are instead "const". */
@@ -624,6 +631,7 @@ DEF_GCC_BUILTIN (BUILT_IN_APPLY_A
DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, "bswap32", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, "bswap64", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, "__clear_cache", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)
+/* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */
DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -662,6 +670,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_EXT_LIB_BUILTIN (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL)
+/* [trans-mem]: Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed. */
DEF_LIB_BUILTIN (BUILT_IN_FREE, "free", BT_FN_VOID_PTR, ATTR_NOTHROW_LIST)
DEF_GCC_BUILTIN (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
DEF_EXT_LIB_BUILTIN (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
@@ -698,6 +707,7 @@ DEF_GCC_BUILTIN (BUILT_IN_ISUNORD
DEF_LIB_BUILTIN (BUILT_IN_LABS, "labs", BT_FN_LONG_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LEAF_LIST)
+/* [trans-mem]: Adjust BUILT_IN_TM_MALLOC if BUILT_IN_MALLOC is changed. */
DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_LEAF_LIST)
DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
@@ -793,3 +803,6 @@ DEF_BUILTIN_STUB (BUILT_IN_EH_COPY_VALUE


 /* OpenMP builtins.  */
 #include "omp-builtins.def"
+
+/* GTM builtins. */
+#include "gtm-builtins.def"
Index: gcc/gimple-low.c
===================================================================
--- gcc/gimple-low.c	(.../trunk)	(revision 180744)
+++ gcc/gimple-low.c	(.../branches/transactional-memory)	(revision 180773)
@@ -396,6 +396,11 @@ lower_stmt (gimple_stmt_iterator *gsi, s
       lower_sequence (gimple_eh_filter_failure (stmt), data);
       break;

+    case GIMPLE_EH_ELSE:
+      lower_sequence (gimple_eh_else_n_body (stmt), data);
+      lower_sequence (gimple_eh_else_e_body (stmt), data);
+      break;
+
     case GIMPLE_NOP:
     case GIMPLE_ASM:
     case GIMPLE_ASSIGN:
@@ -446,6 +451,10 @@ lower_stmt (gimple_stmt_iterator *gsi, s
       data->cannot_fallthru = false;
       return;

+    case GIMPLE_TRANSACTION:
+      lower_sequence (gimple_transaction_body (stmt), data);
+      break;
+
     default:
       gcc_unreachable ();
     }
@@ -727,6 +736,10 @@ gimple_stmt_may_fallthru (gimple stmt)
       return (gimple_seq_may_fallthru (gimple_try_eval (stmt))
 	      && gimple_seq_may_fallthru (gimple_try_cleanup (stmt)));

+ case GIMPLE_EH_ELSE:
+ return (gimple_seq_may_fallthru (gimple_eh_else_n_body (stmt))
+ || gimple_seq_may_fallthru (gimple_eh_else_e_body (stmt)));
+
case GIMPLE_CALL:
/* Functions that do not return do not fall through. */
return (gimple_call_flags (stmt) & ECF_NORETURN) == 0;
Index: gcc/gsstruct.def
===================================================================
--- gcc/gsstruct.def (.../trunk) (revision 180744)
+++ gcc/gsstruct.def (.../branches/transactional-memory) (revision 180773)
@@ -38,6 +38,7 @@ DEFGSSTRUCT(GSS_CATCH, gimple_statement_
DEFGSSTRUCT(GSS_EH_FILTER, gimple_statement_eh_filter, false)
DEFGSSTRUCT(GSS_EH_MNT, gimple_statement_eh_mnt, false)
DEFGSSTRUCT(GSS_EH_CTRL, gimple_statement_eh_ctrl, false)
+DEFGSSTRUCT(GSS_EH_ELSE, gimple_statement_eh_else, false)
DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false)
DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false)
DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false)
@@ -49,3 +50,4 @@ DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_state
DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false)
DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false)
DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false)
+DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false)
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c (.../trunk) (revision 180744)
+++ gcc/tree-eh.c (.../branches/transactional-memory) (revision 180773)
@@ -58,7 +58,7 @@ using_eh_for_cleanups (void)
pointer. Assumes all pointers are interchangeable, which is sort
of already assumed by gcc elsewhere IIRC. */


-static int
+int
 struct_ptr_eq (const void *a, const void *b)
 {
   const void * const * x = (const void * const *) a;
@@ -66,7 +66,7 @@ struct_ptr_eq (const void *a, const void
   return *x == *y;
 }

-static hashval_t
+hashval_t
 struct_ptr_hash (const void *a)
 {
   const void * const * x = (const void * const *) a;
@@ -284,6 +284,11 @@ collect_finally_tree (gimple stmt, gimpl
       collect_finally_tree_1 (gimple_eh_filter_failure (stmt), region);
       break;

+    case GIMPLE_EH_ELSE:
+      collect_finally_tree_1 (gimple_eh_else_n_body (stmt), region);
+      collect_finally_tree_1 (gimple_eh_else_e_body (stmt), region);
+      break;
+
     default:
       /* A type, a decl, or some kind of statement that we're not
 	 interested in.  Don't walk them.  */
@@ -534,6 +539,10 @@ replace_goto_queue_1 (gimple stmt, struc
     case GIMPLE_EH_FILTER:
       replace_goto_queue_stmt_list (gimple_eh_filter_failure (stmt), tf);
       break;
+    case GIMPLE_EH_ELSE:
+      replace_goto_queue_stmt_list (gimple_eh_else_n_body (stmt), tf);
+      replace_goto_queue_stmt_list (gimple_eh_else_e_body (stmt), tf);
+      break;

     default:
       /* These won't have gotos in them.  */
@@ -921,6 +930,21 @@ lower_try_finally_fallthru_label (struct
   return label;
 }

+/* A subroutine of lower_try_finally. If FINALLY consits of a
+ GIMPLE_EH_ELSE node, return it. */
+
+static inline gimple
+get_eh_else (gimple_seq finally)
+{
+ gimple x = gimple_seq_first_stmt (finally);
+ if (gimple_code (x) == GIMPLE_EH_ELSE)
+ {
+ gcc_assert (gimple_seq_singleton_p (finally));
+ return x;
+ }
+ return NULL;
+}
+
/* A subroutine of lower_try_finally. If the eh_protect_cleanup_actions
langhook returns non-null, then the language requires that the exception
path out of a try_finally be treated specially. To wit: the code within
@@ -950,7 +974,7 @@ honor_protect_cleanup_actions (struct le
gimple_stmt_iterator gsi;
bool finally_may_fallthru;
gimple_seq finally;
- gimple x;
+ gimple x, eh_else;


   /* First check for nothing to do.  */
   if (lang_hooks.eh_protect_cleanup_actions == NULL)
@@ -960,12 +984,18 @@ honor_protect_cleanup_actions (struct le
     return;

   finally = gimple_try_cleanup (tf->top_p);
-  finally_may_fallthru = gimple_seq_may_fallthru (finally);
+  eh_else = get_eh_else (finally);

   /* Duplicate the FINALLY block.  Only need to do this for try-finally,
-     and not for cleanups.  */
-  if (this_state)
+     and not for cleanups.  If we've got an EH_ELSE, extract it now.  */
+  if (eh_else)
+    {
+      finally = gimple_eh_else_e_body (eh_else);
+      gimple_try_set_cleanup (tf->top_p, gimple_eh_else_n_body (eh_else));
+    }
+  else if (this_state)
     finally = lower_try_finally_dup_block (finally, outer_state);
+  finally_may_fallthru = gimple_seq_may_fallthru (finally);

/* If this cleanup consists of a TRY_CATCH_EXPR with TRY_CATCH_IS_CLEANUP
set, the handler of the TRY_CATCH_EXPR is another cleanup which ought
@@ -1011,7 +1041,7 @@ lower_try_finally_nofallthru (struct leh
struct leh_tf_state *tf)
{
tree lab;
- gimple x;
+ gimple x, eh_else;
gimple_seq finally;
struct goto_queue_node *q, *qe;


@@ -1034,15 +1064,35 @@ lower_try_finally_nofallthru (struct leh

replace_goto_queue (tf);

- lower_eh_constructs_1 (state, finally);
- gimple_seq_add_seq (&tf->top_p_seq, finally);
+ /* Emit the finally block into the stream. Lower EH_ELSE at this time. */
+ eh_else = get_eh_else (finally);
+ if (eh_else)
+ {
+ finally = gimple_eh_else_n_body (eh_else);
+ lower_eh_constructs_1 (state, finally);
+ gimple_seq_add_seq (&tf->top_p_seq, finally);


-  if (tf->may_throw)
+      if (tf->may_throw)
+	{
+	  finally = gimple_eh_else_e_body (eh_else);
+	  lower_eh_constructs_1 (state, finally);
+
+	  emit_post_landing_pad (&eh_seq, tf->region);
+	  gimple_seq_add_seq (&eh_seq, finally);
+	}
+    }
+  else
     {
-      emit_post_landing_pad (&eh_seq, tf->region);
+      lower_eh_constructs_1 (state, finally);
+      gimple_seq_add_seq (&tf->top_p_seq, finally);

-      x = gimple_build_goto (lab);
-      gimple_seq_add_stmt (&eh_seq, x);
+      if (tf->may_throw)
+	{
+	  emit_post_landing_pad (&eh_seq, tf->region);
+
+	  x = gimple_build_goto (lab);
+	  gimple_seq_add_stmt (&eh_seq, x);
+	}
     }
 }

@@ -1062,6 +1112,18 @@ lower_try_finally_onedest (struct leh_st
   finally = gimple_try_cleanup (tf->top_p);
   tf->top_p_seq = gimple_try_eval (tf->top_p);

+  /* Since there's only one destination, and the destination edge can only
+     either be EH or non-EH, that implies that all of our incoming edges
+     are of the same type.  Therefore we can lower EH_ELSE immediately.  */
+  x = get_eh_else (finally);
+  if (x)
+    {
+      if (tf->may_throw)
+        finally = gimple_eh_else_e_body (x);
+      else
+        finally = gimple_eh_else_n_body (x);
+    }
+
   lower_eh_constructs_1 (state, finally);

   if (tf->may_throw)
@@ -1132,11 +1194,18 @@ lower_try_finally_copy (struct leh_state
   gimple_seq finally;
   gimple_seq new_stmt;
   gimple_seq seq;
-  gimple x;
+  gimple x, eh_else;
   tree tmp;
   location_t tf_loc = gimple_location (tf->try_finally_expr);

   finally = gimple_try_cleanup (tf->top_p);
+
+  /* Notice EH_ELSE, and simplify some of the remaining code
+     by considering FINALLY to be the normal return path only.  */
+  eh_else = get_eh_else (finally);
+  if (eh_else)
+    finally = gimple_eh_else_n_body (eh_else);
+
   tf->top_p_seq = gimple_try_eval (tf->top_p);
   new_stmt = NULL;

@@ -1153,7 +1222,12 @@ lower_try_finally_copy (struct leh_state

   if (tf->may_throw)
     {
-      seq = lower_try_finally_dup_block (finally, state);
+      /* We don't need to copy the EH path of EH_ELSE,
+	 since it is only emitted once.  */
+      if (eh_else)
+        seq = gimple_eh_else_e_body (eh_else);
+      else
+        seq = lower_try_finally_dup_block (finally, state);
       lower_eh_constructs_1 (state, seq);

       emit_post_landing_pad (&eh_seq, tf->region);
@@ -1252,7 +1326,7 @@ lower_try_finally_switch (struct leh_sta
   tree last_case;
   VEC (tree,heap) *case_label_vec;
   gimple_seq switch_body;
-  gimple x;
+  gimple x, eh_else;
   tree tmp;
   gimple switch_stmt;
   gimple_seq finally;
@@ -1263,9 +1337,10 @@ lower_try_finally_switch (struct leh_sta
   location_t finally_loc;

   switch_body = gimple_seq_alloc ();
+  finally = gimple_try_cleanup (tf->top_p);
+  eh_else = get_eh_else (finally);

   /* Mash the TRY block to the head of the chain.  */
-  finally = gimple_try_cleanup (tf->top_p);
   tf->top_p_seq = gimple_try_eval (tf->top_p);

   /* The location of the finally is either the last stmt in the finally
@@ -1281,7 +1356,7 @@ lower_try_finally_switch (struct leh_sta
   nlabels = VEC_length (tree, tf->dest_array);
   return_index = nlabels;
   eh_index = return_index + tf->may_return;
-  fallthru_index = eh_index + tf->may_throw;
+  fallthru_index = eh_index + (tf->may_throw && !eh_else);
   ndests = fallthru_index + tf->may_fallthru;

   finally_tmp = create_tmp_var (integer_type_node, "finally_tmp");
@@ -1319,7 +1394,23 @@ lower_try_finally_switch (struct leh_sta
       gimple_seq_add_stmt (&switch_body, x);
     }

-  if (tf->may_throw)
+  /* For EH_ELSE, emit the exception path (plus resx) now, then
+     subsequently we only need consider the normal path.  */
+  if (eh_else)
+    {
+      if (tf->may_throw)
+	{
+	  finally = gimple_eh_else_e_body (eh_else);
+	  lower_eh_constructs_1 (state, finally);
+
+	  emit_post_landing_pad (&eh_seq, tf->region);
+	  gimple_seq_add_seq (&eh_seq, finally);
+	  emit_resx (&eh_seq, tf->region);
+	}
+
+      finally = gimple_eh_else_n_body (eh_else);
+    }
+  else if (tf->may_throw)
     {
       emit_post_landing_pad (&eh_seq, tf->region);

@@ -1452,12 +1543,22 @@ lower_try_finally_switch (struct leh_sta
    the estimate of the size of the switch machinery we'd have to add.  */

 static bool
-decide_copy_try_finally (int ndests, gimple_seq finally)
+decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally)
 {
   int f_estimate, sw_estimate;
+  gimple eh_else;
+
+  /* If there's an EH_ELSE involved, the exception path is separate
+     and really doesn't come into play for this computation.  */
+  eh_else = get_eh_else (finally);
+  if (eh_else)
+    {
+      ndests -= may_throw;
+      finally = gimple_eh_else_n_body (eh_else);
+    }

   if (!optimize)
-    return false;
+    return ndests == 1;

   /* Finally estimate N times, plus N gotos.  */
   f_estimate = count_insns_seq (finally, &eni_size_weights);
@@ -1563,7 +1664,8 @@ lower_try_finally (struct leh_state *sta
   /* We can easily special-case redirection to a single destination.  */
   else if (ndests == 1)
     lower_try_finally_onedest (state, &this_tf);
-  else if (decide_copy_try_finally (ndests, gimple_try_cleanup (tp)))
+  else if (decide_copy_try_finally (ndests, this_tf.may_throw,
+				    gimple_try_cleanup (tp)))
     lower_try_finally_copy (state, &this_tf);
   else
     lower_try_finally_switch (state, &this_tf);
@@ -1928,6 +2030,9 @@ lower_eh_constructs_2 (struct leh_state
 		case GIMPLE_EH_MUST_NOT_THROW:
 		    replace = lower_eh_must_not_throw (state, stmt);
 		    break;
+		case GIMPLE_EH_ELSE:
+		    /* This code is only valid with GIMPLE_TRY_FINALLY.  */
+		    gcc_unreachable ();
 		default:
 		    replace = lower_cleanup (state, stmt);
 		    break;
@@ -1942,6 +2047,10 @@ lower_eh_constructs_2 (struct leh_state
       /* Return since we don't want gsi_next () */
       return;

+ case GIMPLE_EH_ELSE:
+ /* We should be eliminating this in lower_try_finally et al. */
+ gcc_unreachable ();
+
default:
/* A type, a decl, or some kind of statement that we're not
interested in. Don't walk them. */
@@ -2832,6 +2941,10 @@ refactor_eh_r (gimple_seq seq)
case GIMPLE_EH_FILTER:
refactor_eh_r (gimple_eh_filter_failure (one));
break;
+ case GIMPLE_EH_ELSE:
+ refactor_eh_r (gimple_eh_else_n_body (one));
+ refactor_eh_r (gimple_eh_else_e_body (one));
+ break;
default:
break;
}
Index: gcc/gimple-pretty-print.c
===================================================================
--- gcc/gimple-pretty-print.c (.../trunk) (revision 180744)
+++ gcc/gimple-pretty-print.c (.../branches/transactional-memory) (revision 180773)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.
#include "tree-pass.h"
#include "gimple.h"
#include "value-prof.h"
+#include "trans-mem.h"


 #define INDENT(SPACE)							\
   do { int i; for (i = 0; i < SPACE; i++) pp_space (buffer); } while (0)
@@ -162,6 +163,7 @@ debug_gimple_seq (gimple_seq seq)
      'd' - outputs an int as a decimal,
      's' - outputs a string,
      'n' - outputs a newline,
+     'x' - outputs an int as hexadecimal,
      '+' - increases indent by 2 then outputs a newline,
      '-' - decreases indent by 2 then outputs a newline.   */

@@ -216,6 +218,10 @@ dump_gimple_fmt (pretty_printer *buffer,
                 newline_and_indent (buffer, spc);
                 break;

+              case 'x':
+                pp_scalar (buffer, "%x", va_arg (args, int));
+                break;
+
               case '+':
                 spc += 2;
                 newline_and_indent (buffer, spc);
@@ -622,6 +628,7 @@ static void
 dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
 {
   tree lhs = gimple_call_lhs (gs);
+  tree fn = gimple_call_fn (gs);

   if (flags & TDF_ALIAS)
     {
@@ -648,8 +655,7 @@ dump_gimple_call (pretty_printer *buffer
 	dump_gimple_fmt (buffer, spc, flags, "%G <%s, %T", gs,
 			 internal_fn_name (gimple_call_internal_fn (gs)), lhs);
       else
-	dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T",
-			 gs, gimple_call_fn (gs), lhs);
+	dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T", gs, fn, lhs);
       if (gimple_call_num_args (gs) > 0)
         {
           pp_string (buffer, ", ");
@@ -672,7 +678,7 @@ dump_gimple_call (pretty_printer *buffer
       if (gimple_call_internal_p (gs))
 	pp_string (buffer, internal_fn_name (gimple_call_internal_fn (gs)));
       else
-	print_call_name (buffer, gimple_call_fn (gs), flags);
+	print_call_name (buffer, fn, flags);
       pp_string (buffer, " (");
       dump_gimple_call_args (buffer, gs, flags);
       pp_character (buffer, ')');
@@ -689,9 +695,63 @@ dump_gimple_call (pretty_printer *buffer

   if (gimple_call_return_slot_opt_p (gs))
     pp_string (buffer, " [return slot optimization]");
-
   if (gimple_call_tail_p (gs))
     pp_string (buffer, " [tail call]");
+
+  /* Dump the arguments of _ITM_beginTransaction sanely.  */
+  if (TREE_CODE (fn) == ADDR_EXPR)
+    fn = TREE_OPERAND (fn, 0);
+  if (TREE_CODE (fn) == FUNCTION_DECL && DECL_IS_TM_CLONE (fn))
+    pp_string (buffer, " [tm-clone]");
+  if (TREE_CODE (fn) == FUNCTION_DECL
+      && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
+      && DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_START
+      /* Check we're referring to Intel's TM specifications.  */
+      && !strcmp (IDENTIFIER_POINTER (DECL_NAME (fn)),
+		  "__builtin__ITM_beginTransaction")
+      && gimple_call_num_args (gs) > 0
+      )
+    {
+      tree t = gimple_call_arg (gs, 0);
+      unsigned HOST_WIDE_INT props;
+      gcc_assert (TREE_CODE (t) == INTEGER_CST);
+
+      pp_string (buffer, " [ ");
+
+      /* Get the transaction code properties.  */
+      props = TREE_INT_CST_LOW (t);
+
+      if (props & PR_INSTRUMENTEDCODE)
+	pp_string (buffer, "instrumentedCode ");
+      if (props & PR_UNINSTRUMENTEDCODE)
+	pp_string (buffer, "uninstrumentedCode ");
+      if (props & PR_HASNOXMMUPDATE)
+	pp_string (buffer, "hasNoXMMUpdate ");
+      if (props & PR_HASNOABORT)
+	pp_string (buffer, "hasNoAbort ");
+      if (props & PR_HASNOIRREVOCABLE)
+	pp_string (buffer, "hasNoIrrevocable ");
+      if (props & PR_DOESGOIRREVOCABLE)
+	pp_string (buffer, "doesGoIrrevocable ");
+      if (props & PR_HASNOSIMPLEREADS)
+	pp_string (buffer, "hasNoSimpleReads ");
+      if (props & PR_AWBARRIERSOMITTED)
+	pp_string (buffer, "awBarriersOmitted ");
+      if (props & PR_RARBARRIERSOMITTED)
+	pp_string (buffer, "RaRBarriersOmitted ");
+      if (props & PR_UNDOLOGCODE)
+	pp_string (buffer, "undoLogCode ");
+      if (props & PR_PREFERUNINSTRUMENTED)
+	pp_string (buffer, "preferUninstrumented ");
+      if (props & PR_EXCEPTIONBLOCK)
+	pp_string (buffer, "exceptionBlock ");
+      if (props & PR_HASELSE)
+	pp_string (buffer, "hasElse ");
+      if (props & PR_READONLY)
+	pp_string (buffer, "readOnly ");
+
+      pp_string (buffer, "]");
+    }
 }


@@ -947,6 +1007,24 @@ dump_gimple_eh_must_not_throw (pretty_pr }


+/* Dump a GIMPLE_EH_ELSE tuple on the pretty_printer BUFFER, SPC spaces of
+ indent. FLAGS specifies details to show in the dump (see TDF_* in
+ tree-pass.h). */
+
+static void
+dump_gimple_eh_else (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ if (flags & TDF_RAW)
+ dump_gimple_fmt (buffer, spc, flags,
+ "%G <%+N_BODY <%S>%nE_BODY <%S>%->", gs,
+ gimple_eh_else_n_body (gs), gimple_eh_else_e_body (gs));
+ else
+ dump_gimple_fmt (buffer, spc, flags,
+ "<<<if_normal_exit>>>%+{%S}%-<<<else_eh_exit>>>%+{%S}",
+ gimple_eh_else_n_body (gs), gimple_eh_else_e_body (gs));
+}
+
+
/* Dump a GIMPLE_RESX tuple on the pretty_printer BUFFER, SPC spaces of
indent. FLAGS specifies details to show in the dump (see TDF_* in
tree-pass.h). */
@@ -1269,6 +1347,86 @@ dump_gimple_omp_return (pretty_printer *
}
}


+/* Dump a GIMPLE_TRANSACTION tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_transaction (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ unsigned subcode = gimple_transaction_subcode (gs);
+
+ if (flags & TDF_RAW)
+ {
+ dump_gimple_fmt (buffer, spc, flags,
+ "%G [SUBCODE=%x,LABEL=%T] <%+BODY <%S> >",
+ gs, subcode, gimple_transaction_label (gs),
+ gimple_transaction_body (gs));
+ }
+ else
+ {
+ if (subcode & GTMA_IS_OUTER)
+ pp_string (buffer, "__transaction_atomic [[outer]]");
+ else if (subcode & GTMA_IS_RELAXED)
+ pp_string (buffer, "__transaction_relaxed");
+ else
+ pp_string (buffer, "__transaction_atomic");
+ subcode &= ~GTMA_DECLARATION_MASK;
+
+ if (subcode || gimple_transaction_label (gs))
+ {
+ pp_string (buffer, " //");
+ if (gimple_transaction_label (gs))
+ {
+ pp_string (buffer, " LABEL=");
+ dump_generic_node (buffer, gimple_transaction_label (gs),
+ spc, flags, false);
+ }
+ if (subcode)
+ {
+ pp_string (buffer, " SUBCODE=[ ");
+ if (subcode & GTMA_HAVE_ABORT)
+ {
+ pp_string (buffer, "GTMA_HAVE_ABORT ");
+ subcode &= ~GTMA_HAVE_ABORT;
+ }
+ if (subcode & GTMA_HAVE_LOAD)
+ {
+ pp_string (buffer, "GTMA_HAVE_LOAD ");
+ subcode &= ~GTMA_HAVE_LOAD;
+ }
+ if (subcode & GTMA_HAVE_STORE)
+ {
+ pp_string (buffer, "GTMA_HAVE_STORE ");
+ subcode &= ~GTMA_HAVE_STORE;
+ }
+ if (subcode & GTMA_MAY_ENTER_IRREVOCABLE)
+ {
+ pp_string (buffer, "GTMA_MAY_ENTER_IRREVOCABLE ");
+ subcode &= ~GTMA_MAY_ENTER_IRREVOCABLE;
+ }
+ if (subcode & GTMA_DOES_GO_IRREVOCABLE)
+ {
+ pp_string (buffer, "GTMA_DOES_GO_IRREVOCABLE ");
+ subcode &= ~GTMA_DOES_GO_IRREVOCABLE;
+ }
+ if (subcode)
+ pp_printf (buffer, "0x%x ", subcode);
+ pp_string (buffer, "]");
+ }
+ }
+
+ if (!gimple_seq_empty_p (gimple_transaction_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '{');
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_transaction_body (gs),
+ spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '}');
+ }
+ }
+}
+
/* Dump a GIMPLE_ASM tuple on the pretty_printer BUFFER, SPC spaces of
indent. FLAGS specifies details to show in the dump (see TDF_* in
tree-pass.h). */
@@ -1855,6 +2013,10 @@ dump_gimple_stmt (pretty_printer *buffer
dump_gimple_eh_must_not_throw (buffer, gs, spc, flags);
break;


+    case GIMPLE_EH_ELSE:
+      dump_gimple_eh_else (buffer, gs, spc, flags);
+      break;
+
     case GIMPLE_RESX:
       dump_gimple_resx (buffer, gs, spc, flags);
       break;
@@ -1877,6 +2039,10 @@ dump_gimple_stmt (pretty_printer *buffer
       pp_string (buffer, " predictor.");
       break;

+    case GIMPLE_TRANSACTION:
+      dump_gimple_transaction (buffer, gs, spc, flags);
+      break;
+
     default:
       GIMPLE_NIY;
     }
Index: gcc/gimplify.c
===================================================================
--- gcc/gimplify.c	(.../trunk)	(revision 180744)
+++ gcc/gimplify.c	(.../branches/transactional-memory)	(revision 180773)
@@ -413,6 +413,8 @@ create_tmp_var_name (const char *prefix)
       char *preftmp = ASTRDUP (prefix);

       remove_suffix (preftmp, strlen (preftmp));
+      clean_symbol_name (preftmp);
+
       prefix = preftmp;
     }

@@ -1072,6 +1074,12 @@ voidify_wrapper_expr (tree wrapper, tree
 		}
 	      break;

+	    case TRANSACTION_EXPR:
+	      TREE_SIDE_EFFECTS (*p) = 1;
+	      TREE_TYPE (*p) = void_type_node;
+	      p = &TRANSACTION_EXPR_BODY (*p);
+	      break;
+
 	    default:
 	      goto out;
 	    }
@@ -6527,6 +6535,53 @@ gimplify_omp_atomic (tree *expr_p, gimpl
    return GS_ALL_DONE;
 }

+/* Gimplify a TRANSACTION_EXPR.  This involves gimplification of the
+   body, and adding some EH bits.  */
+
+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_seq body = NULL;
+  struct gimplify_ctx gctx;
+  int subcode = 0;
+
+  /* Wrap the transaction body in a BIND_EXPR so we have a context
+     where to put decls for OpenMP.  */
+  if (TREE_CODE (tbody) != BIND_EXPR)
+    {
+      tree bind = build3 (BIND_EXPR, void_type_node, NULL, tbody, NULL);
+      TREE_SIDE_EFFECTS (bind) = 1;
+      SET_EXPR_LOCATION (bind, EXPR_LOCATION (tbody));
+      TRANSACTION_EXPR_BODY (expr) = bind;
+    }
+
+  push_gimplify_context (&gctx);
+  temp = voidify_wrapper_expr (*expr_p, NULL);
+
+  g = gimplify_and_return_first (TRANSACTION_EXPR_BODY (expr), &body);
+  pop_gimplify_context (g);
+
+  g = 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);
+
+  gimplify_seq_add_stmt (pre_p, g);
+
+  if (temp)
+    {
+      *expr_p = temp;
+      return GS_OK;
+    }
+
+  *expr_p = NULL_TREE;
+  return GS_ALL_DONE;
+}
+
 /* Convert the GENERIC expression tree *EXPR_P to GIMPLE.  If the
    expression produces a value to be used as an operand inside a GIMPLE
    statement, the value will be stored back in *EXPR_P.  This value will
@@ -7251,6 +7306,10 @@ gimplify_expr (tree *expr_p, gimple_seq
 	  ret = gimplify_omp_atomic (expr_p, pre_p);
 	  break;

+        case TRANSACTION_EXPR:
+          ret = gimplify_transaction (expr_p, pre_p);
+          break;
+
 	case TRUTH_AND_EXPR:
 	case TRUTH_OR_EXPR:
 	case TRUTH_XOR_EXPR:
Index: gcc/calls.c
===================================================================
--- gcc/calls.c	(.../trunk)	(revision 180744)
+++ gcc/calls.c	(.../branches/transactional-memory)	(revision 180773)
@@ -496,7 +496,60 @@ emit_call_1 (rtx funexp, tree fntree ATT
 static int
 special_function_p (const_tree fndecl, int flags)
 {
-  if (fndecl && DECL_NAME (fndecl)
+  if (fndecl == NULL)
+    return flags;
+
+  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      switch (DECL_FUNCTION_CODE (fndecl))
+	{
+	case BUILT_IN_TM_COMMIT:
+	case BUILT_IN_TM_COMMIT_EH:
+	case BUILT_IN_TM_ABORT:
+	case BUILT_IN_TM_IRREVOCABLE:
+	case BUILT_IN_TM_GETTMCLONE_IRR:
+	case BUILT_IN_TM_MEMCPY:
+	case BUILT_IN_TM_MEMMOVE:
+        case BUILT_IN_TM_MEMSET:
+	CASE_BUILT_IN_TM_STORE (1):
+	CASE_BUILT_IN_TM_STORE (2):
+	CASE_BUILT_IN_TM_STORE (4):
+	CASE_BUILT_IN_TM_STORE (8):
+	CASE_BUILT_IN_TM_STORE (FLOAT):
+	CASE_BUILT_IN_TM_STORE (DOUBLE):
+	CASE_BUILT_IN_TM_STORE (LDOUBLE):
+	CASE_BUILT_IN_TM_STORE (M64):
+	CASE_BUILT_IN_TM_STORE (M128):
+	CASE_BUILT_IN_TM_STORE (M256):
+	CASE_BUILT_IN_TM_LOAD (1):
+	CASE_BUILT_IN_TM_LOAD (2):
+	CASE_BUILT_IN_TM_LOAD (4):
+	CASE_BUILT_IN_TM_LOAD (8):
+	CASE_BUILT_IN_TM_LOAD (FLOAT):
+	CASE_BUILT_IN_TM_LOAD (DOUBLE):
+	CASE_BUILT_IN_TM_LOAD (LDOUBLE):
+	CASE_BUILT_IN_TM_LOAD (M64):
+	CASE_BUILT_IN_TM_LOAD (M128):
+	CASE_BUILT_IN_TM_LOAD (M256):
+	case BUILT_IN_TM_LOG:
+	case BUILT_IN_TM_LOG_1:
+	case BUILT_IN_TM_LOG_2:
+	case BUILT_IN_TM_LOG_4:
+	case BUILT_IN_TM_LOG_8:
+	case BUILT_IN_TM_LOG_FLOAT:
+	case BUILT_IN_TM_LOG_DOUBLE:
+	case BUILT_IN_TM_LOG_LDOUBLE:
+	case BUILT_IN_TM_LOG_M64:
+	case BUILT_IN_TM_LOG_M128:
+	case BUILT_IN_TM_LOG_M256:
+	  flags |= ECF_TM_OPS;
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  if (DECL_NAME (fndecl)
       && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) <= 17
       /* Exclude functions not at the file scope, or not `extern',
 	 since they are not the magic functions we would otherwise
@@ -644,6 +697,9 @@ flags_from_decl_or_type (const_tree exp)
       if (TREE_NOTHROW (exp))
 	flags |= ECF_NOTHROW;

+      if (DECL_IS_TM_CLONE (exp))
+	flags |= ECF_TM_OPS;
+
       flags = special_function_p (exp, flags);
     }
   else if (TYPE_P (exp) && TYPE_READONLY (exp))
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c	(.../trunk)	(revision 180744)
+++ gcc/tree-inline.c	(.../branches/transactional-memory)	(revision 180773)
@@ -1365,6 +1365,12 @@ remap_gimple_stmt (gimple stmt, copy_bod
 	    = gimple_build_omp_critical (s1, gimple_omp_critical_name (stmt));
 	  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));
+ break;
+
default:
gcc_unreachable ();
}
@@ -3600,6 +3606,11 @@ estimate_num_insns (gimple stmt, eni_wei
return (weights->omp_cost
+ estimate_num_insns_seq (gimple_omp_body (stmt), weights));


+    case GIMPLE_TRANSACTION:
+      return (weights->tm_cost
+	      + estimate_num_insns_seq (gimple_transaction_body (stmt),
+					weights));
+
     default:
       gcc_unreachable ();
     }
@@ -3639,6 +3650,7 @@ init_inline_once (void)
   eni_size_weights.target_builtin_call_cost = 1;
   eni_size_weights.div_mod_cost = 1;
   eni_size_weights.omp_cost = 40;
+  eni_size_weights.tm_cost = 10;
   eni_size_weights.time_based = false;
   eni_size_weights.return_cost = 1;

@@ -3650,6 +3662,7 @@ init_inline_once (void)
   eni_time_weights.target_builtin_call_cost = 1;
   eni_time_weights.div_mod_cost = 10;
   eni_time_weights.omp_cost = 40;
+  eni_time_weights.tm_cost = 40;
   eni_time_weights.time_based = true;
   eni_time_weights.return_cost = 2;
 }
Index: gcc/tree-inline.h
===================================================================
--- gcc/tree-inline.h	(.../trunk)	(revision 180744)
+++ gcc/tree-inline.h	(.../branches/transactional-memory)	(revision 180773)
@@ -144,6 +144,9 @@ typedef struct eni_weights_d
   /* Cost for omp construct.  */
   unsigned omp_cost;

+  /* Cost for tm transaction.  */
+  unsigned tm_cost;
+
   /* Cost of return.  */
   unsigned return_cost;

Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c	(.../trunk)	(revision 180744)
+++ gcc/gimple.c	(.../branches/transactional-memory)	(revision 180773)
@@ -743,6 +743,17 @@ gimple_build_eh_must_not_throw (tree dec
   return p;
 }

+/* Build a GIMPLE_EH_ELSE statement.  */
+
+gimple
+gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
+{
+  gimple p = gimple_alloc (GIMPLE_EH_ELSE, 0);
+  gimple_eh_else_set_n_body (p, n_body);
+  gimple_eh_else_set_e_body (p, e_body);
+  return p;
+}
+
 /* Build a GIMPLE_TRY statement.

    EVAL is the expression to evaluate.
@@ -1146,6 +1157,17 @@ gimple_build_omp_atomic_store (tree val)
   return p;
 }

+/* Build a GIMPLE_TRANSACTION statement. */
+
+gimple
+gimple_build_transaction (gimple_seq body, tree label)
+{
+ gimple p = gimple_alloc (GIMPLE_TRANSACTION, 0);
+ gimple_transaction_set_body (p, body);
+ gimple_transaction_set_label (p, label);
+ return p;
+}
+
/* Build a GIMPLE_PREDICT statement. PREDICT is one of the predictors from
predict.def, OUTCOME is NOT_TAKEN or TAKEN. */


@@ -1331,7 +1353,7 @@ walk_gimple_seq (gimple_seq seq, walk_st
 {
   gimple_stmt_iterator gsi;

-  for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
+  for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
     {
       tree ret = walk_gimple_stmt (&gsi, callback_stmt, callback_op, wi);
       if (ret)
@@ -1340,8 +1362,12 @@ walk_gimple_seq (gimple_seq seq, walk_st
 	     to hold it.  */
 	  gcc_assert (wi);
 	  wi->callback_result = ret;
-	  return gsi_stmt (gsi);
+
+	  return wi->removed_stmt ? NULL : gsi_stmt (gsi);
 	}
+
+      if (!wi->removed_stmt)
+	gsi_next (&gsi);
     }

   if (wi)
@@ -1680,6 +1706,13 @@ walk_gimple_op (gimple stmt, walk_tree_f
 	return ret;
       break;

+    case GIMPLE_TRANSACTION:
+      ret = walk_tree (gimple_transaction_label_ptr (stmt), callback_op,
+		       wi, pset);
+      if (ret)
+	return ret;
+      break;
+
       /* Tuples that do not have operands.  */
     case GIMPLE_NOP:
     case GIMPLE_RESX:
@@ -1730,10 +1763,13 @@ walk_gimple_stmt (gimple_stmt_iterator *
   gimple stmt = gsi_stmt (*gsi);

   if (wi)
-    wi->gsi = *gsi;
+    {
+      wi->gsi = *gsi;
+      wi->removed_stmt = false;

-  if (wi && wi->want_locations && gimple_has_location (stmt))
-    input_location = gimple_location (stmt);
+      if (wi->want_locations && gimple_has_location (stmt))
+	input_location = gimple_location (stmt);
+    }

ret = NULL;

@@ -1751,6 +1787,8 @@ walk_gimple_stmt (gimple_stmt_iterator *
       gcc_assert (tree_ret == NULL);

       /* Re-read stmt in case the callback changed it.  */
+      if (wi && wi->removed_stmt)
+	return NULL;
       stmt = gsi_stmt (*gsi);
     }

@@ -1786,6 +1824,17 @@ walk_gimple_stmt (gimple_stmt_iterator *
 	return wi->callback_result;
       break;

+ case GIMPLE_EH_ELSE:
+ ret = walk_gimple_seq (gimple_eh_else_n_body (stmt),
+ callback_stmt, callback_op, wi);
+ if (ret)
+ return wi->callback_result;
+ ret = walk_gimple_seq (gimple_eh_else_e_body (stmt),
+ callback_stmt, callback_op, wi);
+ if (ret)
+ return wi->callback_result;
+ break;
+
case GIMPLE_TRY:
ret = walk_gimple_seq (gimple_try_eval (stmt), callback_stmt, callback_op,
wi);
@@ -1813,8 +1862,8 @@ walk_gimple_stmt (gimple_stmt_iterator *
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
- ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt, callback_op,
- wi);
+ ret = walk_gimple_seq (gimple_omp_body (stmt), callback_stmt,
+ callback_op, wi);
if (ret)
return wi->callback_result;
break;
@@ -1826,6 +1875,13 @@ walk_gimple_stmt (gimple_stmt_iterator *
return wi->callback_result;
break;


+    case GIMPLE_TRANSACTION:
+      ret = walk_gimple_seq (gimple_transaction_body (stmt),
+			     callback_stmt, callback_op, wi);
+      if (ret)
+	return wi->callback_result;
+      break;
+
     default:
       gcc_assert (!gimple_has_substatements (stmt));
       break;
@@ -2252,6 +2308,13 @@ gimple_copy (gimple stmt)
 	  gimple_eh_filter_set_types (copy, t);
 	  break;

+	case GIMPLE_EH_ELSE:
+	  new_seq = gimple_seq_copy (gimple_eh_else_n_body (stmt));
+	  gimple_eh_else_set_n_body (copy, new_seq);
+	  new_seq = gimple_seq_copy (gimple_eh_else_e_body (stmt));
+	  gimple_eh_else_set_e_body (copy, new_seq);
+	  break;
+
 	case GIMPLE_TRY:
 	  new_seq = gimple_seq_copy (gimple_try_eval (stmt));
 	  gimple_try_set_eval (copy, new_seq);
@@ -2327,6 +2390,11 @@ gimple_copy (gimple stmt)
 	  gimple_omp_set_body (copy, new_seq);
 	  break;

+        case GIMPLE_TRANSACTION:
+	  new_seq = gimple_seq_copy (gimple_transaction_body (stmt));
+	  gimple_transaction_set_body (copy, new_seq);
+	  break;
+
 	case GIMPLE_WITH_CLEANUP_EXPR:
 	  new_seq = gimple_seq_copy (gimple_wce_cleanup (stmt));
 	  gimple_wce_set_cleanup (copy, new_seq);
@@ -2785,7 +2853,7 @@ is_gimple_address (const_tree t)
 /* Strip out all handled components that produce invariant
    offsets.  */

-static const_tree
+const_tree
 strip_invariant_refs (const_tree op)
 {
   while (handled_component_p (op))
@@ -3085,6 +3153,8 @@ get_call_expr_in (tree t)
     t = TREE_OPERAND (t, 1);
   if (TREE_CODE (t) == WITH_SIZE_EXPR)
     t = TREE_OPERAND (t, 0);
+  if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
+    t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CALL_EXPR)
     return t;
   return NULL_TREE;
Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h	(.../trunk)	(revision 180744)
+++ gcc/gimple.h	(.../branches/transactional-memory)	(revision 180773)
@@ -105,6 +105,7 @@ enum gf_mask {
     GF_CALL_NOTHROW		= 1 << 5,
     GF_CALL_ALLOCA_FOR_VAR	= 1 << 6,
     GF_CALL_INTERNAL		= 1 << 7,
+    GF_CALL_NOINLINE		= 1 << 8,
     GF_OMP_PARALLEL_COMBINED	= 1 << 0,

/* True on an GIMPLE_OMP_RETURN statement if the return does not require
@@ -487,6 +488,15 @@ struct GTY(()) gimple_statement_eh_filte
gimple_seq failure;
};


+/* GIMPLE_EH_ELSE */
+
+struct GTY(()) gimple_statement_eh_else {
+  /* [ WORD 1-4 ]  */
+  struct gimple_statement_base gsbase;
+
+  /* [ WORD 5,6 ] */
+  gimple_seq n_body, e_body;
+};

/* GIMPLE_EH_MUST_NOT_THROW */

@@ -757,6 +767,43 @@ struct GTY(()) gimple_statement_omp_atom
   tree val;
 };

+/* GIMPLE_TRANSACTION. */
+
+/* Bits to be stored in the GIMPLE_TRANSACTION subcode. */
+
+/* The __transaction_atomic was declared [[outer]] or it is
+ __transaction_relaxed. */
+#define GTMA_IS_OUTER (1u << 0)
+#define GTMA_IS_RELAXED (1u << 1)
+#define GTMA_DECLARATION_MASK (GTMA_IS_OUTER | GTMA_IS_RELAXED)
+
+/* The transaction is seen to not have an abort. */
+#define GTMA_HAVE_ABORT (1u << 2)
+/* The transaction is seen to have loads or stores. */
+#define GTMA_HAVE_LOAD (1u << 3)
+#define GTMA_HAVE_STORE (1u << 4)
+/* The transaction MAY enter serial irrevocable mode in its dynamic scope. */
+#define GTMA_MAY_ENTER_IRREVOCABLE (1u << 5)
+/* The transaction WILL enter serial irrevocable mode.
+ An irrevocable block post-dominates the entire transaction, such
+ that all invocations of the transaction will go serial-irrevocable.
+ In such case, we don't bother instrumenting the transaction, and
+ tell the runtime that it should begin the transaction in
+ serial-irrevocable mode. */
+#define GTMA_DOES_GO_IRREVOCABLE (1u << 6)
+
+struct GTY(()) gimple_statement_transaction
+{
+ /* [ WORD 1-10 ] */
+ struct gimple_statement_with_memory_ops_base gsbase;
+
+ /* [ WORD 11 ] */
+ gimple_seq body;
+
+ /* [ WORD 12 ] */
+ tree label;
+};
+
#define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) SYM,
enum gimple_statement_structure_enum {
#include "gsstruct.def"
@@ -779,6 +826,7 @@ union GTY ((desc ("gimple_statement_stru
struct gimple_statement_catch GTY ((tag ("GSS_CATCH"))) gimple_catch;
struct gimple_statement_eh_filter GTY ((tag ("GSS_EH_FILTER"))) gimple_eh_filter;
struct gimple_statement_eh_mnt GTY ((tag ("GSS_EH_MNT"))) gimple_eh_mnt;
+ struct gimple_statement_eh_else GTY ((tag ("GSS_EH_ELSE"))) gimple_eh_else;
struct gimple_statement_phi GTY ((tag ("GSS_PHI"))) gimple_phi;
struct gimple_statement_eh_ctrl GTY ((tag ("GSS_EH_CTRL"))) gimple_eh_ctrl;
struct gimple_statement_try GTY ((tag ("GSS_TRY"))) gimple_try;
@@ -793,6 +841,7 @@ union GTY ((desc ("gimple_statement_stru
struct gimple_statement_omp_continue GTY ((tag ("GSS_OMP_CONTINUE"))) gimple_omp_continue;
struct gimple_statement_omp_atomic_load GTY ((tag ("GSS_OMP_ATOMIC_LOAD"))) gimple_omp_atomic_load;
struct gimple_statement_omp_atomic_store GTY ((tag ("GSS_OMP_ATOMIC_STORE"))) gimple_omp_atomic_store;
+ struct gimple_statement_transaction GTY((tag ("GSS_TRANSACTION"))) gimple_transaction;
};


 /* In gimple.c.  */
@@ -846,6 +895,7 @@ gimple gimple_build_asm_vec (const char
 gimple gimple_build_catch (tree, gimple_seq);
 gimple gimple_build_eh_filter (tree, gimple_seq);
 gimple gimple_build_eh_must_not_throw (tree);
+gimple gimple_build_eh_else (gimple_seq, gimple_seq);
 gimple gimple_build_try (gimple_seq, gimple_seq, enum gimple_try_flags);
 gimple gimple_build_wce (gimple_seq);
 gimple gimple_build_resx (int);
@@ -868,6 +918,7 @@ gimple gimple_build_omp_single (gimple_s
 gimple gimple_build_cdt (tree, tree);
 gimple gimple_build_omp_atomic_load (tree, tree);
 gimple gimple_build_omp_atomic_store (tree);
+gimple gimple_build_transaction (gimple_seq, tree);
 gimple gimple_build_predict (enum br_predictor, enum prediction);
 enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
 void sort_case_labels (VEC(tree,heap) *);
@@ -986,6 +1037,7 @@ extern bool walk_stmt_load_store_ops (gi
 				      bool (*)(gimple, tree, void *),
 				      bool (*)(gimple, tree, void *));
 extern bool gimple_ior_addresses_taken (bitmap, gimple);
+extern const_tree strip_invariant_refs (const_tree);
 extern bool gimple_call_builtin_p (gimple, enum built_in_function);
 extern bool gimple_asm_clobbers_memory_p (const_gimple);

@@ -1077,6 +1129,9 @@ extern tree canonicalize_cond_expr_cond
 /* In omp-low.c.  */
 extern tree omp_reduction_init (tree, tree);

+/* In trans-mem.c.  */
+extern void diagnose_tm_safe_errors (tree);
+
 /* In tree-nested.c.  */
 extern void lower_nested_functions (tree);
 extern void insert_field_into_struct (tree, tree);
@@ -1135,6 +1190,7 @@ gimple_has_substatements (gimple g)
     case GIMPLE_BIND:
     case GIMPLE_CATCH:
     case GIMPLE_EH_FILTER:
+    case GIMPLE_EH_ELSE:
     case GIMPLE_TRY:
     case GIMPLE_OMP_FOR:
     case GIMPLE_OMP_MASTER:
@@ -1146,6 +1202,7 @@ gimple_has_substatements (gimple g)
     case GIMPLE_OMP_SINGLE:
     case GIMPLE_OMP_CRITICAL:
     case GIMPLE_WITH_CLEANUP_EXPR:
+    case GIMPLE_TRANSACTION:
       return true;

     default:
@@ -2436,6 +2493,22 @@ gimple_call_alloca_for_var_p (gimple s)
   return (s->gsbase.subcode & GF_CALL_ALLOCA_FOR_VAR) != 0;
 }

+/* Return true if S is a noinline call.  */
+
+static inline bool
+gimple_call_noinline_p (gimple s)
+{
+  GIMPLE_CHECK (s, GIMPLE_CALL);
+  return (s->gsbase.subcode & GF_CALL_NOINLINE) != 0;
+}
+
+static inline void
+gimple_call_set_noinline_p (gimple s)
+{
+  GIMPLE_CHECK (s, GIMPLE_CALL);
+  s->gsbase.subcode |= GF_CALL_NOINLINE;
+}
+
 /* Copy all the GF_CALL_* flags from ORIG_CALL to DEST_CALL.  */

 static inline void
@@ -3178,6 +3251,35 @@ gimple_eh_must_not_throw_set_fndecl (gim
   gs->gimple_eh_mnt.fndecl = decl;
 }

+/* GIMPLE_EH_ELSE accessors.  */
+
+static inline gimple_seq
+gimple_eh_else_n_body (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  return gs->gimple_eh_else.n_body;
+}
+
+static inline gimple_seq
+gimple_eh_else_e_body (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  return gs->gimple_eh_else.e_body;
+}
+
+static inline void
+gimple_eh_else_set_n_body (gimple gs, gimple_seq seq)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  gs->gimple_eh_else.n_body = seq;
+}
+
+static inline void
+gimple_eh_else_set_e_body (gimple gs, gimple_seq seq)
+{
+  GIMPLE_CHECK (gs, GIMPLE_EH_ELSE);
+  gs->gimple_eh_else.e_body = seq;
+}

/* GIMPLE_TRY accessors. */

@@ -4556,6 +4658,67 @@ gimple_omp_continue_set_control_use (gim
   g->gimple_omp_continue.control_use = use;
 }

+/* Return the body for the GIMPLE_TRANSACTION statement GS.  */
+
+static inline gimple_seq
+gimple_transaction_body (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return gs->gimple_transaction.body;
+}
+
+/* Return the label associated with a GIMPLE_TRANSACTION.  */
+
+static inline tree
+gimple_transaction_label (const_gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return gs->gimple_transaction.label;
+}
+
+static inline tree *
+gimple_transaction_label_ptr (gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return &gs->gimple_transaction.label;
+}
+
+/* Return the subcode associated with a GIMPLE_TRANSACTION.  */
+
+static inline unsigned int
+gimple_transaction_subcode (const_gimple gs)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  return gs->gsbase.subcode;
+}
+
+/* Set BODY to be the body for the GIMPLE_TRANSACTION statement GS.  */
+
+static inline void
+gimple_transaction_set_body (gimple gs, gimple_seq body)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  gs->gimple_transaction.body = body;
+}
+
+/* Set the label associated with a GIMPLE_TRANSACTION.  */
+
+static inline void
+gimple_transaction_set_label (gimple gs, tree label)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  gs->gimple_transaction.label = label;
+}
+
+/* Set the subcode associated with a GIMPLE_TRANSACTION.  */
+
+static inline void
+gimple_transaction_set_subcode (gimple gs, unsigned int subcode)
+{
+  GIMPLE_CHECK (gs, GIMPLE_TRANSACTION);
+  gs->gsbase.subcode = subcode;
+}
+

/* Return a pointer to the return value for GIMPLE_RETURN GS. */

@@ -4982,6 +5145,12 @@ struct walk_stmt_info
      will be visited more than once.  */
   struct pointer_set_t *pset;

+  /* Operand returned by the callbacks.  This is set when calling
+     walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
+     returns non-NULL, this field will contain the tree returned by
+     the last callback.  */
+  tree callback_result;
+
   /* Indicates whether the operand being examined may be replaced
      with something that matches is_gimple_val (if true) or something
      slightly more complicated (if false).  "Something" technically
@@ -4994,23 +5163,20 @@ struct walk_stmt_info
      statement 'foo (&var)', the flag VAL_ONLY will initially be set
      to true, however, when walking &var, the operand of that
      ADDR_EXPR does not need to be a GIMPLE value.  */
-  bool val_only;
+  BOOL_BITFIELD val_only : 1;

   /* True if we are currently walking the LHS of an assignment.  */
-  bool is_lhs;
+  BOOL_BITFIELD is_lhs : 1;

   /* Optional.  Set to true by the callback functions if they made any
      changes.  */
-  bool changed;
+  BOOL_BITFIELD changed : 1;

   /* True if we're interested in location information.  */
-  bool want_locations;
+  BOOL_BITFIELD want_locations : 1;

-  /* Operand returned by the callbacks.  This is set when calling
-     walk_gimple_seq.  If the walk_stmt_fn or walk_tree_fn callback
-     returns non-NULL, this field will contain the tree returned by
-     the last callback.  */
-  tree callback_result;
+  /* True if we've removed the statement that was processed.  */
+  BOOL_BITFIELD removed_stmt : 1;
 };

/* Callback for walk_gimple_stmt. Called for every statement found


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]