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