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 
