This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[trans-mem] make it compile w/ tuples
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 15 Oct 2008 09:47:50 -0700
- Subject: [trans-mem] make it compile w/ tuples
I'm now working on re-designing how TM regions are expanded, so I
stubbed out anything I thought I'd have to re-write. So it doesn't
actually *do* anything at the moment. But at least it compiles.
r~
* Makefile.in (gtm-low.o): Don't depend on gtm-defines.h.
* builtin-types.def: Don't include it.
* c-common.c (handle_gtm_unknown_attribute): Stub out
setting DECL_IS_GTM_UNKNOWN.
* c-decl.c (merge_decls): Don't propogate it.
* c-parser.c (c_parser_gtm): Remove decl.
* c-typeck.c (c_finish_gtm_txn): Don't special-case for OpenMP;
make that the only case.
* cgraphbuild.c (prepare_gtm_clone): Use MAIN_NAME_P. Use concat
for resetting the assembler name.
* defaults.h (TINYSTM_VERSION_0_9_5): Set.
* gimple-low.c (struct lower_data): Add in_transaction.
(mark_gtm_save_vars): Remove.
(lower_gtm_directive): Simplify.
(record_vars_into_tm): Split out from record_vars_into. When
inside a transaction, set DECL_IS_GTM_PURE_VAR.
(lower_gimple_bind): Call it.
* gimple-pretty-print.c (dump_gimple_gtm_txn): New.
(dump_gimple_gtm_other): New.
(dump_gimple_stmt): Call them.
* gimple.c (gcc_for_code): Add GTM codes.
(gimple_size): Restructure based on GSS codes.
(gimple_build_gtm_txn): New.
(walk_gimple_stmt): Add GTM codes.
(gimple_rhs_class_table): Make GTM_LOAD/STORE be GIMPLE_SINGLE_RHS.
* gimple.def (GIMPLE_GTM_TXN, GIMPLE_GTM_RETURN, GIMPLE_GTM_ABORT): New.
* gimple.h (struct gimple_statement_seq): Rename from
gimple_statement_omp. Update all users.
(is_gimple_gtm): New.
* gtm-low.c (new_gtm_region): Remove type code.
(build_gtm_regions_1): Gimplify.
(build_gtm_regions): Don't do dominance here.
(remove_gtm_stmts): Gimpify.
(collapse_gtm_regions, query_STM_for_flat_nesting): Remove.
(set_gtm_pure_var, is_gtm_pure_var): Remove.
(requires_barrier): Merge requires_read_barrier and
requires_write_barrier; rewrite to match memory variables only.
(get_real_stm_decl, get_uint_stm_decl, insert_temporary,
may_repair_rhs, compensate_for_taking_the_address,
compose_stm_store_call, compose_stm_load_call,
insert_rhs_stm_call, replace_lhs, maybe_replace_rhs_stmt,
replace_txn_mod_stmt, build_txn_call_expr, replace_txn_stmt,
setup_recover_bb, setup_begin_bb, expand_gtm_abort,
maybe_insert_stm_new, insert_stm_init_thread,
maybe_insert_stm_init_thread, insert_stm_exit_thread,
maybe_insert_stm_exit_thread, expand_gtm_txn_marker,
expand_gtm_return, insert_stm_init, insert_stm_exit,
init_label_table, record_bb_into_table, check_and_mark_edges,
instrument_edges, instrument_return_expr, expand_gtm,
annotate_gtm_function_body): Remove.
(maybe_transactify_assign, maybe_transactify_call): New.
(transactify_stmt): New.
(checkpoint_live_in_variables, checkpoint_gtm_txn): If 0.
* omp-low.c (lower_gtm_txn): Remove.
(diagnose_sb_1): Don't call it.
* passes.c (pass_checkpoint_gtm): Disable.
* tree-flow.h (NUM_BB_TXN): Remove.
(struct gtm_region): Remove txn_bbs, type.
* tree-pretty-print.c (dump_generic_node): Handle GTM codes.
* tree.def (GTM_LOAD, GTM_STORE): Add.
(GTM_RETURN): Remove.
* tree.h (GTM_DIRECTIVE_P): Remove.
(DECL_IS_GTM_UNKNOWN): Disable.
--- Makefile.in (revision 141060)
+++ Makefile.in (local)
@@ -2023,7 +2023,7 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $
gtm-low.o : gtm-low.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) $(TREE_GIMPLE_H) $(TREE_INLINE_H) langhooks.h $(DIAGNOSTIC_H) \
$(TREE_FLOW_H) $(TIMEVAR_H) $(FLAGS_H) $(EXPR_H) toplev.h tree-pass.h \
- $(GGC_H) $(SPLAY_TREE_H) $(OPTABS_H) $(CFGLOOP_H) gtm-defines.h
+ $(GGC_H) $(SPLAY_TREE_H) $(OPTABS_H) $(CFGLOOP_H)
ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
$(HASHTAB_H) $(TOPLEV_H) $(PARAMS_H) hosthooks.h $(HOSTHOOKS_DEF_H)
--- builtin-types.def (revision 141060)
+++ builtin-types.def (local)
@@ -475,8 +475,6 @@ DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VO
BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
-#include "gtm-defines.h"
-
/* GTM special types go here */
#ifdef GTM_EXPL_HANDLE
--- c-common.c (revision 141060)
+++ c-common.c (local)
@@ -6502,8 +6502,9 @@ handle_gtm_unknown_attribute (tree *node
int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL)
- DECL_IS_GTM_UNKNOWN (*node) = 1;
- /* ??? TODO: Support types. */
+ {
+ /* DECL_IS_GTM_UNKNOWN (*node) = 1; */
+ }
else
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
--- c-decl.c (revision 141060)
+++ c-decl.c (local)
@@ -1718,7 +1718,6 @@ merge_decls (tree newdecl, tree olddecl,
DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
DECL_IS_GTM_PURE (newdecl) |= DECL_IS_GTM_PURE (olddecl);
DECL_IS_GTM_CALLABLE (newdecl) |= DECL_IS_GTM_CALLABLE (olddecl);
- DECL_IS_GTM_UNKNOWN (newdecl) |= DECL_IS_GTM_UNKNOWN (olddecl);
}
/* Merge the storage class information. */
--- c-parser.c (revision 141060)
+++ c-parser.c (local)
@@ -913,7 +913,6 @@ static struct c_expr c_parser_postfix_ex
struct c_type_name *);
static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
struct c_expr);
-static tree c_parser_gtm (c_parser *);
static tree c_parser_gtm_atomic (c_parser *);
static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
--- c-typeck.c (revision 141060)
+++ c-typeck.c (local)
@@ -8881,55 +8881,20 @@ c_begin_gtm_txn (void)
return block;
}
-/* Parse like OMP_PARALLEL in case
- OpenMP is used. The lowering
- pass of OpenMP will do the rest.
- In case the OMP lowering pass is not
- triggered simply introduce a new stmt_list
- while encountering a BIND_EXPR. Then
- gimple-low.c should behave nicely and
- add the GTM_RETURN at the end of the
- transaction. */
+/* Create a transaction node. */
tree
c_finish_gtm_txn (tree block)
{
- if (flag_openmp)
- {
- tree stmt;
-
- block = c_end_compound_stmt (block, true);
-
- stmt = make_node (GTM_TXN);
- TREE_TYPE (stmt) = void_type_node;
- GTM_TXN_BODY (stmt) = block;
+ tree stmt;
- return add_stmt (stmt);
- }
- else
- {
- tree stmt;
- tree new_body;
- tree gtm_ret;
-
- block = c_end_compound_stmt (block, true);
-
- stmt = make_node (GTM_TXN);
- TREE_TYPE (stmt) = void_type_node;
- new_body = block;
-
- if (TREE_CODE (block) == BIND_EXPR)
- {
- new_body = alloc_stmt_list ();
- append_to_statement_list (block, &new_body);
- gtm_ret = make_node (GTM_RETURN);
- append_to_statement_list (gtm_ret, &new_body);
- }
+ block = c_end_compound_stmt (block, true);
- GTM_TXN_BODY (stmt) = new_body;
+ stmt = make_node (GTM_TXN);
+ TREE_TYPE (stmt) = void_type_node;
+ GTM_TXN_BODY (stmt) = block;
- return add_stmt (stmt);
- }
+ return add_stmt (stmt);
}
/* Create a GTM_ABORT node and add it. */
--- cgraphbuild.c (revision 141060)
+++ cgraphbuild.c (local)
@@ -131,16 +131,12 @@ prepare_gtm_clone (struct cgraph_node *n
struct cgraph_node *tm_node;
tree decl, old_decl, id;
struct function *saved_cfun;
- size_t len;
- char *tm_name;
if (!flag_gtm || flag_openmp)
return;
/* No need for a TM clone of the main function */
- const char *orig = get_name (node->decl);
- if ((strncmp (orig, "main", 4) == 0)
- && (strlen (orig) == 4))
+ if (MAIN_NAME_P (DECL_NAME (node->decl)))
return;
/* Do not prepare functions that are already instances
@@ -155,7 +151,7 @@ prepare_gtm_clone (struct cgraph_node *n
/* Defer redirecting callers of the node to the
new versioned node to the gtm expansion pass. */
- tm_node = cgraph_function_versioning (node, NULL, NULL);
+ tm_node = cgraph_function_versioning (node, NULL, NULL, NULL);
if (tm_node == NULL)
return;
@@ -171,13 +167,15 @@ prepare_gtm_clone (struct cgraph_node *n
set_cfun (DECL_STRUCT_FUNCTION (decl));
/* Substitute decl name. */
- len = strlen (orig);
- tm_name = (char *) xmalloc (sizeof (char) * (len + 4));
- strncpy (tm_name, orig, len);
- strcpy (tm_name + len, "Txn");
- id = get_identifier (tm_name);
- DECL_NAME (decl) = id;
- SET_DECL_ASSEMBLER_NAME(decl, id);
+ {
+ char *tm_name;
+
+ tm_name = concat (get_name (node->decl), ".Txn", NULL);
+ id = get_identifier (tm_name);
+ DECL_NAME (decl) = id;
+ SET_DECL_ASSEMBLER_NAME (decl, id);
+ free (tm_name);
+ }
#ifdef GTM_EXPL_HANDLE
/* Create parameter declaration for txn_handle and add
--- cp/cp-gimplify.c (revision 141060)
+++ cp/cp-gimplify.c (local)
@@ -372,8 +372,8 @@ cp_gimplify_omp_for (tree *expr_p, gimpl
gimplify_and_add (for_stmt, &seq);
stmt = gimple_seq_last_stmt (seq);
if (gimple_code (stmt) == GIMPLE_OMP_FOR)
- gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block,
- gimple_omp_body (stmt)));
+ gimple_seq_set_body (stmt, finish_bc_block (bc_continue, cont_block,
+ gimple_seq_body (stmt)));
else
seq = finish_bc_block (bc_continue, cont_block, seq);
gimple_seq_add_seq (pre_p, seq);
--- defaults.h (revision 141060)
+++ defaults.h (local)
@@ -949,6 +949,8 @@ along with GCC; see the file COPYING3.
In particular the explicit passing of transaction handles and
the implicit handling of transaction handles are distinguished. */
+#define TINYSTM_VERSION_0_9_5
+
#ifdef TINYSTM_VERSION_0_9_0b1
#define GTM_EXPL_HANDLE
#undef GTM_IMPL_HANDLE
--- gimple-low.c (revision 141060)
+++ gimple-low.c (local)
@@ -77,12 +77,16 @@ struct lower_data
/* True if the function calls __builtin_setjmp. */
bool calls_builtin_setjmp;
+
+ /* True if we're lowering inside a transaction. */
+ bool in_transaction;
};
static void lower_stmt (gimple_stmt_iterator *, struct lower_data *);
static void lower_gimple_bind (gimple_stmt_iterator *, struct lower_data *);
static void lower_gimple_return (gimple_stmt_iterator *, struct lower_data *);
static void lower_builtin_setjmp (gimple_stmt_iterator *);
+static void record_vars_into_tm (tree, tree, bool);
/* Lower the body of current_function_decl from High GIMPLE into Low
@@ -217,108 +221,6 @@ struct gimple_opt_pass pass_lower_cf =
}
};
-static void
-mark_gtm_save_vars (tree vars)
-{
- for (; vars; vars = TREE_CHAIN (vars))
- {
- tree var = vars;
- if (TREE_CODE (var) == VAR_DECL)
- DECL_IS_GTM_PURE_VAR (var) = 1;
- }
- return ;
-}
-
-/* Lower the GTM directive statement pointed by TSI. DATA is
- passed through the recursion. */
-
-static void
-lower_gtm_directive (tree_stmt_iterator *tsi, struct lower_data *data)
-{
- tree stmt;
-
- stmt = tsi_stmt (*tsi);
- tree body = GTM_TXN_BODY (stmt);
- if (TREE_CODE (body) == STATEMENT_LIST)
- {
- tree temp;
- tree_stmt_iterator ttsi = tsi_start (body);
- if (!tsi_end_p (ttsi))
- {
- temp = tsi_stmt (ttsi);
- }
- else gcc_unreachable();
- if (TREE_CODE (temp) == BIND_EXPR)
- {
- tree vars = BIND_EXPR_VARS (temp);
-
- if (vars)
- {
- mark_gtm_save_vars(vars);
- }
- if (TREE_CODE (BIND_EXPR_BODY (temp)) == STATEMENT_LIST)
- {
- tree temp2;
- tree_stmt_iterator ttsi = tsi_start (BIND_EXPR_BODY (temp));
-
- if (!tsi_end_p (ttsi))
- {
- temp2 = tsi_stmt (ttsi);
- }
- else gcc_unreachable();
-
- if (TREE_CODE (temp2) == BIND_EXPR)
- {
- tree vars = BIND_EXPR_VARS (temp2);
-
- if (vars)
- {
- mark_gtm_save_vars(vars);
- }
- }
- }
- }
- }
- else
- {
- if (TREE_CODE (body) == BIND_EXPR)
- {
- tree vars = BIND_EXPR_VARS (body);
-
- if (vars)
- {
- mark_gtm_save_vars(vars);
- }
- }
- if (TREE_CODE (BIND_EXPR_BODY (body)) == STATEMENT_LIST)
- {
- tree temp;
- tree_stmt_iterator ttsi = tsi_start (BIND_EXPR_BODY (body));
-
- if (!tsi_end_p (ttsi))
- {
- temp = tsi_stmt (ttsi);
- }
- else gcc_unreachable();
-
- if (TREE_CODE (temp) == BIND_EXPR)
- {
- tree vars = BIND_EXPR_VARS (temp);
-
- if (vars)
- {
- mark_gtm_save_vars(vars);
- }
- }
- }
- }
-
- lower_stmt_body (body, data);
- tsi_link_before (tsi, stmt, TSI_SAME_STMT);
- tsi_link_before (tsi, body, TSI_SAME_STMT);
- GTM_TXN_BODY (stmt) = NULL_TREE;
- tsi_delink (tsi);
-}
/* Lower sequence SEQ. Unlike gimplification the statements are not relowered
when they are changed -- if this has to be done, the lowering routine must
@@ -334,6 +236,26 @@ lower_sequence (gimple_seq seq, struct l
}
+/* Lower the GTM directive statement pointed by TSI. DATA is
+ passed through the recursion. */
+
+static void
+lower_gtm_directive (gimple_stmt_iterator *gsi, struct lower_data *data)
+{
+ bool old_in_transaction = data->in_transaction;
+ gimple stmt = gsi_stmt (*gsi);
+
+ data->in_transaction = true;
+
+ lower_sequence (gimple_seq_body (stmt), data);
+ gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
+ gsi_insert_seq_before (gsi, gimple_seq_body (stmt), GSI_SAME_STMT);
+ gimple_seq_set_body (stmt, NULL);
+ gsi_remove (gsi, false);
+
+ data->in_transaction = old_in_transaction;
+}
+
/* Lower the OpenMP directive statement pointed by GSI. DATA is
passed through the recursion. */
@@ -344,10 +266,10 @@ lower_omp_directive (gimple_stmt_iterato
stmt = gsi_stmt (*gsi);
- lower_sequence (gimple_omp_body (stmt), data);
+ lower_sequence (gimple_seq_body (stmt), data);
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
- gsi_insert_seq_before (gsi, gimple_omp_body (stmt), GSI_SAME_STMT);
- gimple_omp_set_body (stmt, NULL);
+ gsi_insert_seq_before (gsi, gimple_seq_body (stmt), GSI_SAME_STMT);
+ gimple_seq_set_body (stmt, NULL);
gsi_remove (gsi, false);
}
@@ -433,7 +355,7 @@ lower_stmt (gimple_stmt_iterator *gsi, s
return;
case GIMPLE_GTM_TXN:
- lower_gtm_directive (tsi, data);
+ lower_gtm_directive (gsi, data);
return;
default:
@@ -480,7 +402,8 @@ lower_gimple_bind (gimple_stmt_iterator
}
}
- record_vars (gimple_bind_vars (stmt));
+ record_vars_into_tm (gimple_bind_vars (stmt), current_function_decl,
+ data->in_transaction);
lower_sequence (gimple_bind_body (stmt), data);
if (new_block)
@@ -894,10 +817,11 @@ lower_builtin_setjmp (gimple_stmt_iterat
}
-/* Record the variables in VARS into function FN. */
+/* Record the variables in VARS into function FN. If IN_TRANSACTION is
+ true, mark them DECL_IS_GTM_PURE_VAR. */
-void
-record_vars_into (tree vars, tree fn)
+static void
+record_vars_into_tm (tree vars, tree fn, bool in_transaction)
{
if (fn != current_function_decl)
push_cfun (DECL_STRUCT_FUNCTION (fn));
@@ -918,19 +842,31 @@ record_vars_into (tree vars, tree fn)
/* Record the variable. */
cfun->local_decls = tree_cons (NULL_TREE, var,
cfun->local_decls);
+
+ /* If we're inside a transaction, mark it for NOT checkpointing. */
+ if (in_transaction)
+ DECL_IS_GTM_PURE_VAR (var) = 1;
}
if (fn != current_function_decl)
pop_cfun ();
}
+/* Record the variables in VARS into function FN. */
+
+void
+record_vars_into (tree vars, tree fn)
+{
+ record_vars_into_tm (vars, fn, false);
+}
+
/* Record the variables in VARS into current_function_decl. */
void
record_vars (tree vars)
{
- record_vars_into (vars, current_function_decl);
+ record_vars_into_tm (vars, current_function_decl, false);
}
--- gimple-pretty-print.c (revision 141060)
+++ gimple-pretty-print.c (local)
@@ -757,7 +757,7 @@ dump_gimple_omp_for (pretty_printer *buf
if (flags & TDF_RAW)
{
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
dump_omp_clauses (buffer, gimple_omp_for_clauses (gs), spc, flags);
dump_gimple_fmt (buffer, spc, flags, " >,");
for (i = 0; i < gimple_omp_for_collapse (gs); i++)
@@ -821,12 +821,12 @@ dump_gimple_omp_for (pretty_printer *buf
pp_character (buffer, ')');
}
- if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ if (!gimple_seq_empty_p (gimple_seq_body (gs)))
{
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '{');
pp_newline (buffer);
- dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ dump_gimple_seq (buffer, gimple_seq_body (gs), spc + 4, flags);
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '}');
}
@@ -865,7 +865,7 @@ dump_gimple_omp_single (pretty_printer *
if (flags & TDF_RAW)
{
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
dump_omp_clauses (buffer, gimple_omp_single_clauses (gs), spc, flags);
dump_gimple_fmt (buffer, spc, flags, " >");
}
@@ -873,12 +873,12 @@ dump_gimple_omp_single (pretty_printer *
{
pp_string (buffer, "#pragma omp single");
dump_omp_clauses (buffer, gimple_omp_single_clauses (gs), spc, flags);
- if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ if (!gimple_seq_empty_p (gimple_seq_body (gs)))
{
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '{');
pp_newline (buffer);
- dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ dump_gimple_seq (buffer, gimple_seq_body (gs), spc + 4, flags);
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '}');
}
@@ -894,7 +894,7 @@ dump_gimple_omp_sections (pretty_printer
if (flags & TDF_RAW)
{
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
dump_omp_clauses (buffer, gimple_omp_sections_clauses (gs), spc, flags);
dump_gimple_fmt (buffer, spc, flags, " >");
}
@@ -909,12 +909,12 @@ dump_gimple_omp_sections (pretty_printer
pp_character (buffer, '>');
}
dump_omp_clauses (buffer, gimple_omp_sections_clauses (gs), spc, flags);
- if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ if (!gimple_seq_empty_p (gimple_seq_body (gs)))
{
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '{');
pp_newline (buffer);
- dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ dump_gimple_seq (buffer, gimple_seq_body (gs), spc + 4, flags);
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '}');
}
@@ -929,7 +929,7 @@ dump_gimple_omp_block (pretty_printer *b
{
if (flags & TDF_RAW)
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
else
{
switch (gimple_code (gs))
@@ -946,12 +946,12 @@ dump_gimple_omp_block (pretty_printer *b
default:
gcc_unreachable ();
}
- if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ if (!gimple_seq_empty_p (gimple_seq_body (gs)))
{
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '{');
pp_newline (buffer);
- dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ dump_gimple_seq (buffer, gimple_seq_body (gs), spc + 4, flags);
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '}');
}
@@ -966,7 +966,7 @@ dump_gimple_omp_critical (pretty_printer
{
if (flags & TDF_RAW)
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
else
{
pp_string (buffer, "#pragma omp critical");
@@ -977,12 +977,12 @@ dump_gimple_omp_critical (pretty_printer
flags, false);
pp_character (buffer, ')');
}
- if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ if (!gimple_seq_empty_p (gimple_seq_body (gs)))
{
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '{');
pp_newline (buffer);
- dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ dump_gimple_seq (buffer, gimple_seq_body (gs), spc + 4, flags);
newline_and_indent (buffer, spc + 2);
pp_character (buffer, '}');
}
@@ -1007,6 +1007,45 @@ dump_gimple_omp_return (pretty_printer *
}
}
+/* Dump a GIMPLE_GTM_TXN tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_gtm_txn (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ if (flags & TDF_RAW)
+ dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
+ gimple_seq_body (gs));
+ else
+ {
+ pp_string (buffer, "__tm_atomic");
+ if (!gimple_seq_empty_p (gimple_seq_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '{');
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_seq_body (gs), spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_character (buffer, '}');
+ }
+ }
+}
+
+/* Dump a GIMPLE_GTM_RETURN or GIMPLE_GTM_ABORT tuple on the
+ pretty_printer BUFFER. */
+
+static void
+dump_gimple_gtm_other (pretty_printer *buffer, gimple gs, int spc, int flags)
+{
+ if (flags & TDF_RAW)
+ {
+ dump_gimple_fmt (buffer, spc, flags, "%G", gs);
+ }
+ else if (gimple_code (gs) == GIMPLE_GTM_RETURN)
+ pp_string (buffer, "__tm_return");
+ else if (gimple_code (gs) == GIMPLE_GTM_ABORT)
+ pp_string (buffer, "__tm_abort");
+}
+
/* 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). */
@@ -1168,7 +1207,7 @@ dump_gimple_omp_parallel (pretty_printer
if (flags & TDF_RAW)
{
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
dump_omp_clauses (buffer, gimple_omp_parallel_clauses (gs), spc, flags);
dump_gimple_fmt (buffer, spc, flags, " >, %T, %T%n>",
gimple_omp_parallel_child_fn (gs),
@@ -1192,7 +1231,7 @@ dump_gimple_omp_parallel (pretty_printer
pp_string (buffer, "???");
pp_string (buffer, ")]");
}
- body = gimple_omp_body (gs);
+ body = gimple_seq_body (gs);
if (body && gimple_code (gimple_seq_first_stmt (body)) != GIMPLE_BIND)
{
newline_and_indent (buffer, spc + 2);
@@ -1222,7 +1261,7 @@ dump_gimple_omp_task (pretty_printer *bu
if (flags & TDF_RAW)
{
dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
- gimple_omp_body (gs));
+ gimple_seq_body (gs));
dump_omp_clauses (buffer, gimple_omp_task_clauses (gs), spc, flags);
dump_gimple_fmt (buffer, spc, flags, " >, %T, %T, %T, %T, %T%n>",
gimple_omp_task_child_fn (gs),
@@ -1249,7 +1288,7 @@ dump_gimple_omp_task (pretty_printer *bu
pp_string (buffer, "???");
pp_string (buffer, ")]");
}
- body = gimple_omp_body (gs);
+ body = gimple_seq_body (gs);
if (body && gimple_code (gimple_seq_first_stmt (body)) != GIMPLE_BIND)
{
newline_and_indent (buffer, spc + 2);
@@ -1583,6 +1622,15 @@ dump_gimple_stmt (pretty_printer *buffer
pp_string (buffer, " predictor.");
break;
+ case GIMPLE_GTM_TXN:
+ dump_gimple_gtm_txn (buffer, gs, spc, flags);
+ break;
+
+ case GIMPLE_GTM_RETURN:
+ case GIMPLE_GTM_ABORT:
+ dump_gimple_gtm_other (buffer, gs, spc, flags);
+ break;
+
default:
GIMPLE_NIY;
}
--- gimple.c (revision 141060)
+++ gimple.c (local)
@@ -117,7 +117,7 @@ gss_for_code (enum gimple_code code)
case GIMPLE_OMP_FOR: return GSS_OMP_FOR;
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
- case GIMPLE_OMP_SECTION: return GSS_OMP;
+ case GIMPLE_OMP_SECTION: return GSS_SEQ;
case GIMPLE_OMP_RETURN:
case GIMPLE_OMP_SECTIONS_SWITCH: return GSS_BASE;
case GIMPLE_OMP_CONTINUE: return GSS_OMP_CONTINUE;
@@ -128,6 +128,9 @@ gss_for_code (enum gimple_code code)
case GIMPLE_OMP_ATOMIC_LOAD: return GSS_OMP_ATOMIC_LOAD;
case GIMPLE_OMP_ATOMIC_STORE: return GSS_OMP_ATOMIC_STORE;
case GIMPLE_PREDICT: return GSS_BASE;
+ case GIMPLE_GTM_TXN: return GSS_SEQ;
+ case GIMPLE_GTM_RETURN:
+ case GIMPLE_GTM_ABORT: return GSS_BASE;
default: gcc_unreachable ();
}
}
@@ -141,64 +144,53 @@ gimple_size (enum gimple_code code)
{
enum gimple_statement_structure_enum gss = gss_for_code (code);
- if (gss == GSS_WITH_OPS)
- return sizeof (struct gimple_statement_with_ops);
- else if (gss == GSS_WITH_MEM_OPS)
- return sizeof (struct gimple_statement_with_memory_ops);
-
- switch (code)
+ switch (gss)
{
- case GIMPLE_ASM:
- return sizeof (struct gimple_statement_asm);
- case GIMPLE_NOP:
+ case GSS_BASE:
return sizeof (struct gimple_statement_base);
- case GIMPLE_BIND:
+ case GSS_WITH_OPS:
+ return sizeof (struct gimple_statement_with_ops);
+ case GSS_WITH_MEM_OPS:
+ return sizeof (struct gimple_statement_with_memory_ops);
+ case GSS_SEQ:
+ return sizeof (struct gimple_statement_seq);
+ case GSS_BIND:
return sizeof (struct gimple_statement_bind);
- case GIMPLE_CATCH:
+ case GSS_CATCH:
return sizeof (struct gimple_statement_catch);
- case GIMPLE_EH_FILTER:
+ case GSS_EH_FILTER:
return sizeof (struct gimple_statement_eh_filter);
- case GIMPLE_TRY:
- return sizeof (struct gimple_statement_try);
- case GIMPLE_RESX:
+ case GSS_PHI:
+ return sizeof (struct gimple_statement_phi);
+ case GSS_RESX:
return sizeof (struct gimple_statement_resx);
- case GIMPLE_OMP_CRITICAL:
+ case GSS_TRY:
+ return sizeof (struct gimple_statement_try);
+ case GSS_WCE:
+ return sizeof (struct gimple_statement_wce);
+ case GSS_ASM:
+ return sizeof (struct gimple_statement_asm);
+ case GSS_OMP_CRITICAL:
return sizeof (struct gimple_statement_omp_critical);
- case GIMPLE_OMP_FOR:
+ case GSS_OMP_FOR:
return sizeof (struct gimple_statement_omp_for);
- case GIMPLE_OMP_PARALLEL:
+ case GSS_OMP_PARALLEL:
return sizeof (struct gimple_statement_omp_parallel);
- case GIMPLE_OMP_TASK:
+ case GSS_OMP_TASK:
return sizeof (struct gimple_statement_omp_task);
- case GIMPLE_OMP_SECTION:
- case GIMPLE_OMP_MASTER:
- case GIMPLE_OMP_ORDERED:
- return sizeof (struct gimple_statement_omp);
- case GIMPLE_OMP_RETURN:
- return sizeof (struct gimple_statement_base);
- case GIMPLE_OMP_CONTINUE:
- return sizeof (struct gimple_statement_omp_continue);
- case GIMPLE_OMP_SECTIONS:
+ case GSS_OMP_SECTIONS:
return sizeof (struct gimple_statement_omp_sections);
- case GIMPLE_OMP_SECTIONS_SWITCH:
- return sizeof (struct gimple_statement_base);
- case GIMPLE_OMP_SINGLE:
+ case GSS_OMP_SINGLE:
return sizeof (struct gimple_statement_omp_single);
- case GIMPLE_OMP_ATOMIC_LOAD:
+ case GSS_OMP_CONTINUE:
+ return sizeof (struct gimple_statement_omp_continue);
+ case GSS_OMP_ATOMIC_LOAD:
return sizeof (struct gimple_statement_omp_atomic_load);
- case GIMPLE_OMP_ATOMIC_STORE:
+ case GSS_OMP_ATOMIC_STORE:
return sizeof (struct gimple_statement_omp_atomic_store);
- case GIMPLE_WITH_CLEANUP_EXPR:
- return sizeof (struct gimple_statement_wce);
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- return sizeof (struct gimple_statement_with_ops);
- case GIMPLE_PREDICT:
- return sizeof (struct gimple_statement_base);
default:
- break;
+ gcc_unreachable ();
}
-
- gcc_unreachable ();
}
@@ -841,7 +833,7 @@ gimple_build_omp_critical (gimple_seq bo
gimple p = gimple_alloc (GIMPLE_OMP_CRITICAL, 0);
gimple_omp_critical_set_name (p, name);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
return p;
}
@@ -860,7 +852,7 @@ gimple_build_omp_for (gimple_seq body, t
{
gimple p = gimple_alloc (GIMPLE_OMP_FOR, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
gimple_omp_for_set_clauses (p, clauses);
p->gimple_omp_for.collapse = collapse;
p->gimple_omp_for.iter = GGC_CNEWVEC (struct gimple_omp_for_iter, collapse);
@@ -884,7 +876,7 @@ gimple_build_omp_parallel (gimple_seq bo
{
gimple p = gimple_alloc (GIMPLE_OMP_PARALLEL, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
gimple_omp_parallel_set_clauses (p, clauses);
gimple_omp_parallel_set_child_fn (p, child_fn);
gimple_omp_parallel_set_data_arg (p, data_arg);
@@ -909,7 +901,7 @@ gimple_build_omp_task (gimple_seq body,
{
gimple p = gimple_alloc (GIMPLE_OMP_TASK, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
gimple_omp_task_set_clauses (p, clauses);
gimple_omp_task_set_child_fn (p, child_fn);
gimple_omp_task_set_data_arg (p, data_arg);
@@ -930,7 +922,7 @@ gimple_build_omp_section (gimple_seq bod
{
gimple p = gimple_alloc (GIMPLE_OMP_SECTION, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
return p;
}
@@ -945,7 +937,7 @@ gimple_build_omp_master (gimple_seq body
{
gimple p = gimple_alloc (GIMPLE_OMP_MASTER, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
return p;
}
@@ -975,7 +967,7 @@ gimple_build_omp_ordered (gimple_seq bod
{
gimple p = gimple_alloc (GIMPLE_OMP_ORDERED, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
return p;
}
@@ -1006,7 +998,7 @@ gimple_build_omp_sections (gimple_seq bo
{
gimple p = gimple_alloc (GIMPLE_OMP_SECTIONS, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
gimple_omp_sections_set_clauses (p, clauses);
return p;
@@ -1033,7 +1025,7 @@ gimple_build_omp_single (gimple_seq body
{
gimple p = gimple_alloc (GIMPLE_OMP_SINGLE, 0);
if (body)
- gimple_omp_set_body (p, body);
+ gimple_seq_set_body (p, body);
gimple_omp_single_set_clauses (p, clauses);
return p;
@@ -1077,6 +1069,17 @@ gimple_build_omp_atomic_store (tree val)
return p;
}
+/* Build a GIMPLE_GTM_TXN statement. */
+
+gimple
+gimple_build_gtm_txn (gimple_seq body)
+{
+ gimple p = gimple_alloc (GIMPLE_GTM_TXN, 0);
+ if (body)
+ gimple_seq_set_body (p, body);
+ return p;
+}
+
/* Build a GIMPLE_PREDICT statement. PREDICT is one of the predictors from
predict.def, OUTCOME is NOT_TAKEN or TAKEN. */
@@ -1767,8 +1770,9 @@ 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);
+ case GIMPLE_GTM_TXN:
+ ret = walk_gimple_seq (gimple_seq_body (stmt), callback_stmt,
+ callback_op, wi);
if (ret)
return wi->callback_result;
break;
@@ -2208,9 +2212,10 @@ gimple_copy (gimple stmt)
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_GTM_TXN:
copy_omp_body:
- new_seq = gimple_seq_copy (gimple_omp_body (stmt));
- gimple_omp_set_body (copy, new_seq);
+ new_seq = gimple_seq_copy (gimple_seq_body (stmt));
+ gimple_seq_set_body (copy, new_seq);
break;
case GIMPLE_WITH_CLEANUP_EXPR:
@@ -2570,7 +2575,9 @@ get_gimple_rhs_num_ops (enum tree_code c
|| (SYM) == POLYNOMIAL_CHREC \
|| (SYM) == DOT_PROD_EXPR \
|| (SYM) == VEC_COND_EXPR \
- || (SYM) == REALIGN_LOAD_EXPR) ? GIMPLE_SINGLE_RHS \
+ || (SYM) == REALIGN_LOAD_EXPR \
+ || (SYM) == GTM_LOAD \
+ || (SYM) == GTM_STORE) ? GIMPLE_SINGLE_RHS \
: GIMPLE_INVALID_RHS),
#define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS,
--- gimple.def (revision 141060)
+++ gimple.def (local)
@@ -355,3 +355,13 @@ DEFGSCODE(GIMPLE_PREDICT, "gimple_predic
This tuple should not exist outside of the gimplifier proper. */
DEFGSCODE(GIMPLE_WITH_CLEANUP_EXPR, "gimple_with_cleanup_expr", NULL)
+
+/* GIMPLE_GTX_TXN <BODY> represents __tm_atomic blocks.
+ BODY is the sequence of statements inside the transaction. */
+DEFGSCODE(GIMPLE_GTM_TXN, "gimple_gtm_txn", NULL)
+
+/* GIMPLE_GTM_RETURN marks the end of a transaction. */
+DEFGSCODE(GIMPLE_GTM_RETURN, "gimple_gtm_return", NULL)
+
+/* GIMPLE_GTM_ABORT marks a user abort of the transaction. */
+DEFGSCODE(GIMPLE_GTM_ABORT, "gimple_gtm_abort", NULL)
--- gimple.h (revision 141060)
+++ gimple.h (local)
@@ -391,9 +391,9 @@ struct gimple_statement_with_memory_ops
};
-/* OpenMP statements (#pragma omp). */
+/* Statements with embedded blocks (#pragma omp, gtm). */
-struct gimple_statement_omp GTY(())
+struct gimple_statement_seq GTY(())
{
/* [ WORD 1-4 ] */
struct gimple_statement_base gsbase;
@@ -571,7 +571,7 @@ struct gimple_statement_asm GTY(())
struct gimple_statement_omp_critical GTY(())
{
/* [ WORD 1-5 ] */
- struct gimple_statement_omp omp;
+ struct gimple_statement_seq omp;
/* [ WORD 6 ]
Critical section name. */
@@ -602,7 +602,7 @@ struct gimple_omp_for_iter GTY(())
struct gimple_statement_omp_for GTY(())
{
/* [ WORD 1-5 ] */
- struct gimple_statement_omp omp;
+ struct gimple_statement_seq omp;
/* [ WORD 6 ] */
tree clauses;
@@ -625,7 +625,7 @@ struct gimple_statement_omp_for GTY(())
struct gimple_statement_omp_parallel GTY(())
{
/* [ WORD 1-5 ] */
- struct gimple_statement_omp omp;
+ struct gimple_statement_seq omp;
/* [ WORD 6 ]
Clauses. */
@@ -668,7 +668,7 @@ struct gimple_statement_omp_task GTY(())
struct gimple_statement_omp_sections GTY(())
{
/* [ WORD 1-5 ] */
- struct gimple_statement_omp omp;
+ struct gimple_statement_seq omp;
/* [ WORD 6 ] */
tree clauses;
@@ -701,7 +701,7 @@ struct gimple_statement_omp_continue GTY
struct gimple_statement_omp_single GTY(())
{
/* [ WORD 1-5 ] */
- struct gimple_statement_omp omp;
+ struct gimple_statement_seq omp;
/* [ WORD 6 ] */
tree clauses;
@@ -749,7 +749,7 @@ union gimple_statement_d GTY ((desc ("gi
struct gimple_statement_base GTY ((tag ("GSS_BASE"))) gsbase;
struct gimple_statement_with_ops GTY ((tag ("GSS_WITH_OPS"))) gsops;
struct gimple_statement_with_memory_ops GTY ((tag ("GSS_WITH_MEM_OPS"))) gsmem;
- struct gimple_statement_omp GTY ((tag ("GSS_OMP"))) omp;
+ struct gimple_statement_seq GTY ((tag ("GSS_SEQ"))) seq;
struct gimple_statement_bind GTY ((tag ("GSS_BIND"))) gimple_bind;
struct gimple_statement_catch GTY ((tag ("GSS_CATCH"))) gimple_catch;
struct gimple_statement_eh_filter GTY ((tag ("GSS_EH_FILTER"))) gimple_eh_filter;
@@ -816,6 +816,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_gtm_txn (gimple_seq);
gimple gimple_build_predict (enum br_predictor, enum prediction);
enum gimple_statement_structure_enum gimple_statement_structure (gimple);
enum gimple_statement_structure_enum gss_for_assign (enum tree_code);
@@ -3232,20 +3233,20 @@ gimple_switch_set_default_label (gimple
}
-/* Return the body for the OMP statement GS. */
+/* Return the body for the SEQ statement GS. */
static inline gimple_seq
-gimple_omp_body (gimple gs)
+gimple_seq_body (gimple gs)
{
- return gs->omp.body;
+ return gs->seq.body;
}
-/* Set BODY to be the body for the OMP statement GS. */
+/* Set BODY to be the body for the SEQ statement GS. */
static inline void
-gimple_omp_set_body (gimple gs, gimple_seq body)
+gimple_seq_set_body (gimple gs, gimple_seq body)
{
- gs->omp.body = body;
+ gs->seq.body = body;
}
@@ -4169,6 +4170,14 @@ is_gimple_omp (const_gimple stmt)
|| gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
}
+/* Returns true when the gimple statement STMT is a GTM type. */
+
+static inline bool
+is_gimple_gtm (const_gimple stmt)
+{
+ return (gimple_code (stmt) == GIMPLE_GTM_TXN
+ || gimple_code (stmt) == GIMPLE_GTM_RETURN);
+}
/* Returns TRUE if statement G is a GIMPLE_NOP. */
--- gsstruct.def (revision 141060)
+++ gsstruct.def (local)
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.
DEFGSSTRUCT(GSS_BASE, "base")
DEFGSSTRUCT(GSS_WITH_OPS, "with_ops")
DEFGSSTRUCT(GSS_WITH_MEM_OPS, "with_mem_ops")
-DEFGSSTRUCT(GSS_OMP, "omp")
+DEFGSSTRUCT(GSS_SEQ, "seq")
DEFGSSTRUCT(GSS_BIND, "bind")
DEFGSSTRUCT(GSS_CATCH, "catch")
DEFGSSTRUCT(GSS_EH_FILTER, "eh_filter")
--- gtm-low.c (revision 141060)
+++ gtm-low.c (local)
@@ -1,5 +1,5 @@
-/* Lowering pass for transactional memory directives.
- Converts markers of transactions into explicit calls to
+/* Lowering pass for transactional memory directives.
+ Converts markers of transactions into explicit calls to
the STM runtime library.
Copyright (C) 2008 Free Software Foundation, Inc.
@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>.
+ <http://www.gnu.org/licenses/>.
*/
@@ -28,8 +28,7 @@
#include "tm.h"
#include "tree.h"
#include "rtl.h"
-#include "tree-gimple.h"
-#include "tree-inline.h"
+#include "gimple.h"
#include "langhooks.h"
#include "diagnostic.h"
#include "tree-flow.h"
@@ -45,49 +44,26 @@
#include "optabs.h"
#include "cfgloop.h"
#include "tree-ssa-live.h"
+#include "tree-flow.h"
-struct gtm_region *root_gtm_region;
-unsigned int label_index;
-unsigned int e_index;
-edge edges_to_instrument[NUM_BB_TXN];
-
-/* Function declarations for GTM expansion and checkpointing. */
-void check_and_mark_edges (struct gtm_region *, basic_block);
-char *check_call_expr (tree);
-void checkpoint_live_in_variables (struct gtm_region *, block_stmt_iterator *, basic_block);
-void compensate_for_taking_the_address (tree);
-static void expand_gtm_abort (block_stmt_iterator *, enum bsi_iterator_update, tree);
+struct gtm_region *root_gtm_region;
/* Debugging dumps for transactional regions. */
void dump_gtm_region (FILE *, struct gtm_region *, int);
void debug_gtm_region (struct gtm_region *);
void debug_all_gtm_regions (void);
-void execute_lower_gtm (void);
-void execute_checkpoint_gtm (void);
-static bool gate_expand_gtm (void);
-static bool gate_checkpoint_gtm (void);
-
-void init_label_table (void);
-tree insert_temporary (block_stmt_iterator, tree);
-void instrument_edges (tree);
-void instrument_return_expr (block_stmt_iterator *, tree);
-
-void may_repair_rhs (tree, block_stmt_iterator, tree);
-void record_bb_into_table (struct gtm_region *, basic_block);
-
-
/* Dump the gtm region tree rooted at REGION. */
+
void
dump_gtm_region (FILE *file, struct gtm_region *region, int indent)
{
- fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
- tree_code_name[region->type]);
+ fprintf (file, "%*sbb %d: GTM_TXN\n", indent, "", region->entry->index);
if (region->inner)
dump_gtm_region (file, region->inner, indent + 4);
-
+
if (region->exit)
fprintf (file, "%*sbb %d: GTM_RETURN\n", indent, "",
region->exit->index);
@@ -109,14 +85,14 @@ debug_all_gtm_regions (void)
}
/* Create a new gtm region starting at STMT inside region PARENT. */
+
struct gtm_region *
-new_gtm_region (basic_block bb, enum tree_code type, struct gtm_region *parent)
+new_gtm_region (basic_block bb, struct gtm_region *parent)
{
- struct gtm_region *region = xcalloc (1, sizeof (*region));
+ struct gtm_region *region = XCNEW (struct gtm_region);
region->outer = parent;
region->entry = bb;
- region->type = type;
if (parent)
{
@@ -137,6 +113,7 @@ new_gtm_region (basic_block bb, enum tre
}
/* Release the memory associated with the region tree rooted at REGION. */
+
static void
free_gtm_region_1 (struct gtm_region *region)
{
@@ -156,1598 +133,316 @@ void
free_gtm_regions (void)
{
struct gtm_region *r, *n;
+
for (r = root_gtm_region; r ; r = n)
{
n = r->next;
free_gtm_region_1 (r);
}
+
root_gtm_region = NULL;
}
/* Helper for build_gtm_regions. Scan the dominator tree starting at
block BB. PARENT is the region that contains BB. If SINGLE_TREE is
- true, the function ends once a single tree is built (like constructing omp region trees). */
+ true, the function ends once a single tree is built. */
+
static void
build_gtm_regions_1 (basic_block bb, struct gtm_region *parent,
bool single_tree)
{
- block_stmt_iterator si;
- tree stmt;
+ gimple_stmt_iterator gsi;
+ gimple stmt;
basic_block son;
+ struct gtm_region *region;
- si = bsi_last (bb);
- if (!bsi_end_p (si)) /* bsi_stmt should not be NULL */
+ gsi = gsi_last_bb (bb);
+ if (!gsi_end_p (gsi))
{
- if (GTM_DIRECTIVE_P (bsi_stmt (si)))
+ stmt = gsi_stmt (gsi);
+ switch (gimple_code (stmt))
{
- struct gtm_region *region;
- enum tree_code code;
- stmt = bsi_stmt (si);
- code = TREE_CODE (stmt);
- if (code == GTM_RETURN)
- {
- /* STMT is the return point out of region PARENT. Mark it
- as the exit point and make PARENT the immediately
- enclosing region. */
- gcc_assert (parent);
- region = parent;
- region->exit = bb;
- parent = parent->outer;
- }
- else if (code == GTM_TXN)
- {
- /* Otherwise, this directive becomes the parent for a new
- region. GTM_TXN is the only one left for now. */
- region = new_gtm_region (bb, code, parent);
- parent = region;
- }
+ case GIMPLE_GTM_TXN:
+ region = new_gtm_region (bb, parent);
+ break;
+
+ case GIMPLE_GTM_RETURN:
+ /* STMT is the return point out of region PARENT. Mark it
+ as the exit point and make PARENT the immediately enclosing
+ region. */
+ gcc_assert (parent);
+ region = parent;
+ region->exit = bb;
+ parent = parent->outer;
+ break;
+
+ default:
+ break;
}
}
+
if (single_tree && !parent)
return;
-
+
for (son = first_dom_son (CDI_DOMINATORS, bb);
son;
son = next_dom_son (CDI_DOMINATORS, son))
build_gtm_regions_1 (son, parent, single_tree);
}
-/* Scan the CFG and build a tree of GTM regions.
+/* Scan the CFG and build a tree of GTM regions.
Return the root of the GTM region tree. */
+
static void
build_gtm_regions (void)
{
gcc_assert (root_gtm_region == NULL);
- calculate_dominance_info (CDI_DOMINATORS);
build_gtm_regions_1 (ENTRY_BLOCK_PTR, NULL, false);
}
/* Remove entry and exit marker from region. */
-static void
+
+static void ATTRIBUTE_UNUSED
remove_gtm_stmts (struct gtm_region *region)
{
- basic_block entry_bb, exit_bb;
- block_stmt_iterator si;
- tree stmt;
-
- entry_bb = region->entry;
- exit_bb = region->exit;
-
- gcc_assert (entry_bb);
- gcc_assert (exit_bb);
-
- si = bsi_last (entry_bb);
- stmt = bsi_stmt (si);
-
- gcc_assert (TREE_CODE (stmt) == GTM_TXN);
-
- bsi_remove (&si, true);
- single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
-
- if (exit_bb)
- {
- si = bsi_last (exit_bb);
- gcc_assert (!bsi_end_p (si)
- && TREE_CODE (bsi_stmt (si)) == GTM_RETURN);
-
- bsi_remove (&si, true);
- single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
- }
-
- return ;
-}
+ gimple_stmt_iterator gsi;
-/* If the STM only supports flat nesting, all
- nested transactions are collapsed into
- the outermost one. */
-static void
-collapse_gtm_regions (struct gtm_region *region)
-{
- while (region)
- {
- /* Collapse only the inner regions. */
- if (region->inner)
- {
- remove_gtm_stmts (region->inner);
- collapse_gtm_regions (region->inner);
- free (region->inner);
- region->inner = NULL;
- }
+ gcc_assert (region->entry);
+ gcc_assert (region->exit);
- gcc_assert ((region->type) == GTM_TXN);
- region = region->next;
- }
+ gsi = gsi_last_bb (region->entry);
+ gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_GTM_TXN);
+ gsi_remove (&gsi, true);
- return ;
+ gsi = gsi_last_bb (region->exit);
+ gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_GTM_RETURN);
+ gsi_remove (&gsi, true);
}
-/* TODO: add mechanism to query the
- STM for supported features. */
-static bool
-query_STM_for_flat_nesting (void)
-{
- return true;
-}
-/* This is an enhancement to the TM concept.
- It allows the programmer to specify where
- to drop some instrumentation. Variables in
- the source code can be marked as tm_pure.
- The helper function sets the corresponding
- attribute. */
-static void
-set_gtm_pure_var (tree t)
-{
- if ((TREE_CODE (t) == INDIRECT_REF)
- || (TREE_CODE (t) == COMPONENT_REF)
- || (TREE_CODE (t) == ARRAY_REF))
- {
- return set_gtm_pure_var (TREE_OPERAND (t, 0));
- }
-
- if (TREE_CODE (t) == VAR_DECL)
- {
- DECL_IS_GTM_PURE_VAR (t) = 1;
- }
- return ;
-}
+/* Determine whether X has to be instrumented using a read
+ or write barrier. */
-/* This is an enhancement to the TM concept.
- It allows the programmer to specify where
- to drop some instrumentation. Variables in
- the source code can be marked as tm_pure.
- The helper function checks whether the
- attribute was specified. */
static bool
-is_gtm_pure_var (tree t)
+requires_barrier (tree x)
{
- if ((TREE_CODE (t) == INDIRECT_REF)
- || (TREE_CODE (t) == COMPONENT_REF)
- || (TREE_CODE (t) == ARRAY_REF))
- {
- return is_gtm_pure_var (TREE_OPERAND (t, 0));
- }
+ while (handled_component_p (x))
+ x = TREE_OPERAND (x, 0);
- if (TREE_CODE (t) == VAR_DECL)
+ switch (TREE_CODE (x))
{
- if (DECL_IS_GTM_PURE_VAR (t) == 1)
- {
- return true;
- }
- }
- return false;
-}
+ case INDIRECT_REF:
+ /* ??? Use must-alias information to reduce this. */
+ return true;
+
+ case ALIGN_INDIRECT_REF:
+ case MISALIGNED_INDIRECT_REF:
+ gcc_unreachable ();
+
+ case VAR_DECL:
+ if (DECL_IS_GTM_PURE_VAR (x))
+ return false;
+ if (is_global_var (x))
+ return !TREE_READONLY (x);
+ return TREE_ADDRESSABLE (x);
-/* Determine whether operand has to be
- instrumented using a read barrier. */
-/* TODO: check if _all_ cases are covered. */
-static bool
-requires_read_barrier (tree operand)
-{
- if (TREE_CODE (operand) == SSA_NAME)
- operand = SSA_NAME_VAR (operand);
-
- /* Check whether we may drop some instrumentation. */
- if (is_gtm_pure_var (operand))
- return false;
-
- if ((TREE_CODE (operand) == COMPONENT_REF)
- || (TREE_CODE (operand) == INDIRECT_REF)
- || (TREE_CODE (operand) == ARRAY_REF))
- return true;
-
- /* Casts are ignored - descent recursively. */
- if ((TREE_CODE (operand) == NOP_EXPR)
- || (TREE_CODE (operand) == FLOAT_EXPR)
- || (TREE_CODE (operand) == FIX_TRUNC_EXPR))
- return requires_read_barrier (TREE_OPERAND (operand, 0));
-
- /* In case the variable is defined inside the scope of
- the transaction, there is no need for instrumentation. */
- if (TREE_CODE (operand) == VAR_DECL)
- if (DECL_IS_GTM_PURE_VAR (operand))
+ default:
return false;
-
- if ((CONSTANT_CLASS_P (operand))
- || (DECL_ARTIFICIAL (operand)))
- return false;
- else
- return ((TREE_CODE (operand) == VAR_DECL && is_global_var (operand))
- || (POINTER_TYPE_P (TREE_TYPE (operand)))
- || (TREE_ADDRESSABLE (operand)));
-}
-
-/* Determine whether operand has to be instrumented
- using a write barrier. */
-/* TODO: check if _all_ cases are covered. */
-static bool
-requires_write_barrier (tree operand)
-{
- if (TREE_CODE (operand) == SSA_NAME)
- operand = SSA_NAME_VAR (operand);
-
- /* Check whether we may drop some instrumentation. */
- if (is_gtm_pure_var (operand))
- return false;
-
- if ( (TREE_CODE (operand) == COMPONENT_REF)
- || (TREE_CODE (operand) == INDIRECT_REF)
- || (TREE_CODE (operand) == ARRAY_REF))
- return true;
-
- if ((CONSTANT_CLASS_P (operand))
- || (DECL_ARTIFICIAL (operand)))
- return false;
- else
- return ((TREE_CODE (operand) == VAR_DECL && is_global_var (operand))
- || (POINTER_TYPE_P (TREE_TYPE (operand)))
- || (TREE_ADDRESSABLE (operand)));
-}
-
-/* Helper function returning the declaration
- of a builtin stm function if the operand
- has a type real. */
-static tree
-get_real_stm_decl (bool store, tree op)
-{
- tree decl;
- tree type = TYPE_MAIN_VARIANT (TREE_TYPE (op));
- if (!store)
- {
- if (type == double_type_node)
- decl = built_in_decls [BUILT_IN_GTM_LOAD_DOUBLE];
- else
- {
- gcc_assert (type == float_type_node);
- decl = built_in_decls [BUILT_IN_GTM_LOAD_FLOAT];
- }
- }
- else
- {
- if (type == double_type_node)
- decl = built_in_decls [BUILT_IN_GTM_STORE_DOUBLE];
- else
- {
- gcc_assert (type == float_type_node);
- decl = built_in_decls [BUILT_IN_GTM_STORE_FLOAT];
- }
- }
- gcc_assert(decl);
-
- return decl;
-}
-
-/* Returns function decl determined by
- type size of operand. */
-static tree
-get_uint_stm_decl (int builtin, tree op)
-{
- HOST_WIDE_INT index;
- tree decl;
- tree type = TYPE_MAIN_VARIANT (TREE_TYPE (op));
-
- index = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
- index = exact_log2 (index);
-
- if (index >= 0 && index <= 4)
- decl = built_in_decls[builtin + index + 1];
- else
- gcc_unreachable();
-
- gcc_assert(decl);
-
- return decl;
-}
-
-/* Insert new temporary variable that
- lives in a GIMPLE register and issue
- a load of the "old" variable. */
-tree
-insert_temporary (block_stmt_iterator bsi, tree op)
-{
- tree new_var;
- tree stmt;
-
- new_var = create_tmp_var (TREE_TYPE (op), get_name(op));
- stmt = build_gimple_modify_stmt (new_var, op);
-
- stmt = unshare_expr (stmt);
-
- bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
- return new_var;
-}
-
-/* Check whether variables used in stmts are the
- ones to replace by a use of a GIMPLE register.
- If they match the replacement is done. */
-void
-may_repair_rhs (tree rhs, block_stmt_iterator bsi, tree op)
-{
- tree new_var;
-
- if (UNARY_CLASS_P (rhs))
- {
- if (op == rhs)
- {
- new_var = insert_temporary (bsi, op);
- tree stmt = bsi_stmt (bsi);
- GIMPLE_STMT_OPERAND (stmt, 1) = new_var;
- }
- }
- else
- {
- if (BINARY_CLASS_P (rhs))
- {
- if (TREE_OPERAND (rhs, 0) == op)
- {
- new_var = insert_temporary (bsi, op);
- TREE_OPERAND (rhs, 0) = new_var;
- }
- if (TREE_OPERAND (rhs, 1) == op)
- {
- new_var = insert_temporary (bsi, op);
- TREE_OPERAND (rhs, 1) = new_var;
- }
- }
}
-
- return;
}
-/* Compensate for taking the address of a local variable.
- By using the address of the variable, the variable escapes
- the local scope and becomes global.
- Since global variables on GIMPLE have to be transferred to
- registers before they can be used, this behaviour has to
- be added. */
-void
-compensate_for_taking_the_address (tree op)
-{
- basic_block bb;
- block_stmt_iterator bsi;
- tree stmt;
- tree rhs;
-
- FOR_EACH_BB (bb)
- {
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- stmt = bsi_stmt (bsi);
-
- /* TODO: add more possible uses of a variable here! */
- if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
- {
- rhs = GIMPLE_STMT_OPERAND (stmt, 1);
- may_repair_rhs(rhs, bsi, op);
- }
-
- if (TREE_CODE (stmt) == CALL_EXPR)
- {
- tree arg;
- call_expr_arg_iterator iter;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, stmt)
- may_repair_rhs (arg, bsi, op);
- }
- }
- }
-
- return ;
-}
-
-/* Helper function that
- composes the STM store function call. */
-static tree
-compose_stm_store_call (tree op, tree txn_handle, tree value)
-{
- tree call;
- tree decl;
- bool compensate = false;
-
- if (TREE_CODE (op) == SSA_NAME)
- op = SSA_NAME_VAR (op);
-
- if (!TREE_ADDRESSABLE (op))
- compensate = true;
-
- if (TREE_CODE (TREE_TYPE (op)) == INTEGER_TYPE)
- decl = get_uint_stm_decl (BUILT_IN_GTM_STORE_N, op);
-
- if (TREE_CODE (TREE_TYPE (op)) == POINTER_TYPE)
- {
-#ifdef TINYSTM_VERSION_0_9_0b1
- decl = built_in_decls [BUILT_IN_GTM_STORE_PTR];
-#endif
-#ifdef TANGER
- decl = built_in_decls [BUILT_IN_GTM_STORE_PTR];
-#endif
-#ifdef TINYSTM_VERSION_0_9_5
- decl = built_in_decls [BUILT_IN_GTM_STORE_PTR];
-#endif
- }
-
- if (TREE_CODE (TREE_TYPE (op)) == REAL_TYPE)
- decl = get_real_stm_decl (true, op);
+/* Subsituting a MODIFY_STMT with calls to the STM runtime. */
- gcc_assert (decl);
-
- if (txn_handle != NULL_TREE)
- call = build_call_expr (decl, 3, txn_handle,
- build_fold_addr_expr (op), value);
- else
- call = build_call_expr (decl, 2, build_fold_addr_expr (op), value);
-
- if (compensate)
- compensate_for_taking_the_address (op);
-
- return call;
-}
-
-/* Helper function that composes
- the STM load function call. */
-static tree
-compose_stm_load_call (tree op, tree txn_handle)
-{
- tree decl = NULL_TREE;
- tree call;
- bool compensate = false;
-
- if (TREE_CODE (op) == SSA_NAME)
- op = SSA_NAME_VAR (op);
-
- if (!TREE_ADDRESSABLE (op))
- compensate = true;
-
- if (TREE_CODE (TREE_TYPE (op)) == INTEGER_TYPE)
- decl = get_uint_stm_decl(BUILT_IN_GTM_LOAD_N, op);
-
- if (TREE_CODE (TREE_TYPE (op)) == REAL_TYPE)
- decl = get_real_stm_decl(false, op);
-
- if (TREE_CODE (TREE_TYPE (op)) == POINTER_TYPE)
- {
-#ifdef TINYSTM_VERSION_0_9_0b1
- decl = built_in_decls [BUILT_IN_GTM_LOAD_PTR];
-#endif
-#ifdef TANGER
- decl = built_in_decls [BUILT_IN_GTM_LOAD_PTR];
-#endif
-#ifdef TINYSTM_VERSION_0_9_5
- decl = built_in_decls [BUILT_IN_GTM_LOAD_PTR];
-#endif
- }
-
- gcc_assert (decl);
-
- if (txn_handle != NULL_TREE)
- {
- call = build_call_expr (decl, 2, txn_handle,
- build_fold_addr_expr(op));
- }
- else
- {
- call = build_call_expr (decl, 1, build_fold_addr_expr(op));
- }
-
- if (compensate)
- compensate_for_taking_the_address (op);
-
- return call;
-}
-
-/* Emits call to stm_load including the
- txn_handle and address of the variable. */
-static tree
-insert_rhs_stm_call (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree op, tree txn_handle)
-{
- tree stmt;
- tree t_load = create_tmp_var (TREE_TYPE (op), "txn_tmp");
-
- tree call = compose_stm_load_call (op, txn_handle);
-
- stmt = build_gimple_modify_stmt (t_load, call);
- stmt = unshare_expr (stmt);
- bsi_insert_before (bsi, stmt, m);
-
- return t_load;
-}
-
-/* Introduce temporary variable if necessary
- and emit call to stm_store. */
static void
-replace_lhs (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree op, tree txn_handle)
+maybe_transactify_assign (gimple stmt)
{
- tree t_store;
- tree stmt, call;
- tree op_type = TREE_TYPE (op);
- tree mod_stmt = bsi_stmt (*bsi);
- tree rhs = GIMPLE_STMT_OPERAND (mod_stmt, 1);
-
- if ((!CONSTANT_CLASS_P (rhs))
- && (!is_gimple_formal_tmp_var (rhs)))
- {
- t_store = create_tmp_var (op_type, "txn_tmp");
- stmt = build_gimple_modify_stmt (t_store, rhs);
- stmt = unshare_expr (stmt);
- bsi_insert_before (bsi, stmt, m);
- }
- else
- {
- t_store = rhs;
- }
-
- call = compose_stm_store_call(op, txn_handle, t_store);
- call = unshare_expr (call);
- bsi_insert_after (bsi, call, m);
- bsi_remove (bsi, true);
-
- return ;
-}
+ bool load_p = requires_barrier (gimple_assign_rhs1 (stmt));
+ bool store_p = requires_barrier (gimple_assign_lhs (stmt));
-/* Check whether the operands need a read
- barrier and insert it.
- TODO: relax handling of ARRAY_REFs. */
-static void
-maybe_replace_rhs_stmt (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree stmt, tree txn_handle)
-{
- tree t_load;
- tree op1, op2;
- tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-
- if ((UNARY_CLASS_P (rhs))
- || (CONSTANT_CLASS_P (rhs))
- || (TREE_CODE (rhs) == VAR_DECL))
- {
- op1 = rhs;
- if (requires_read_barrier (op1))
- {
- if (TREE_CODE (op1) == NOP_EXPR)
- op1 = TREE_OPERAND (op1, 0);
- t_load = insert_rhs_stm_call (bsi, m, op1, txn_handle);
- GIMPLE_STMT_OPERAND (stmt, 1) = t_load;
- }
- }
- else
+ if (load_p)
{
- if (BINARY_CLASS_P (rhs))
- {
- op1 = TREE_OPERAND (rhs, 0);
- if (requires_read_barrier (op1))
- {
- t_load = insert_rhs_stm_call (bsi, m, op1, txn_handle);
- TREE_OPERAND (rhs, 0) = t_load;
- }
- op2 = TREE_OPERAND (rhs, 1);
- if (requires_read_barrier (op2))
- {
- t_load = insert_rhs_stm_call (bsi, m, op2, txn_handle);
- TREE_OPERAND (rhs, 1) = t_load;
- }
- }
- else
- {
- if ((POINTER_TYPE_P (TREE_TYPE (rhs))
- || (TREE_CODE (rhs) == COMPONENT_REF)
- || ((TREE_CODE (rhs) == INDIRECT_REF)
- && (DECL_IS_GTM_PURE_VAR (TREE_OPERAND (rhs, 0)) != 1))
- || (TREE_CODE (rhs) == ARRAY_REF))
- && (TREE_CODE (rhs) != CALL_EXPR)
- )
- {
- op1 = rhs;
- t_load = insert_rhs_stm_call (bsi, m, op1, txn_handle);
- GIMPLE_STMT_OPERAND (stmt, 1) = t_load;
- }
- }
+ gcc_assert (!store_p);
+ gimple_assign_set_rhs_code (stmt, GTM_LOAD);
}
-
- return ;
-}
-
-/* Subsituting a MODIFY_STMT
- with calls to the STM runtime,
- the worst case looks like this:
-
- t1 = stm_load(b);
- t2 = stm_load(c);
- t3 = t1 * t2;
- stm_store(a, t3);
-
- substitutes for:
-
- a = b * c; */
-static void
-replace_txn_mod_stmt (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree txn_handle)
-{
-
- tree stmt = bsi_stmt (*bsi);
- tree lhs = GIMPLE_STMT_OPERAND (stmt, 0);
- tree rhs = GIMPLE_STMT_OPERAND (stmt, 1);
-
- /* Propagate GTM_PURE_VAR in case of an assignment
- to a temporary variable. */
- if (is_gtm_pure_var (rhs))
- set_gtm_pure_var (lhs);
-
- maybe_replace_rhs_stmt (bsi, m, stmt, txn_handle);
-
- if (requires_write_barrier (lhs))
- {
- replace_lhs (bsi, m, lhs, txn_handle);
- }
-
- return ;
-}
-
-/* Build and return a call to a transactional function.
- Add one parameter to pass a transaction handle. */
-tree
-build_txn_call_expr (tree orig_ce, struct cgraph_node *tm_node, tree txn_handle)
-{
- tree arglist = CALL_EXPR_ARGS (orig_ce);
-
- if (txn_handle)
- {
- arglist = chainon (arglist, build_tree_list (NULL_TREE, txn_handle));
- }
-
- return build_function_call_expr (tm_node->decl, arglist);
-}
-
-/* Return function name or NULL if function
- is a STM compiler builtin. */
-char *
-check_call_expr (tree ce)
-{
- char *name = get_name (get_callee_fndecl (ce));
-#ifdef TANGER
- if (strncmp(name, "__builtin_tanger_stm", 20) != 0)
- return name;
-#else
- if (strncmp(name, "__builtin_stm", 13) != 0)
- return name;
-#endif
- return NULL;
+ else if (store_p)
+ gimple_assign_set_rhs_code (stmt, GTM_STORE);
}
-/* Helper function that replaces call expressions inside
- transactions and issues a warning if no transactional
+/* Helper function that replaces call expressions inside
+ transactions and issues a warning if no transactional
clone is found. */
-void
-replace_call_expr_in_txn (tree ce, tree stmt, tree txn_handle)
-{
- bool redirected = false;
- char *name;
- name = check_call_expr (ce);
- if (name)
- {
- tree fn_decl = get_callee_fndecl (ce);
- struct cgraph_node *node = cgraph_node (fn_decl);
- struct cgraph_node *orig_node = node;
-
- /* find transactional clone of function */
- while (node && node->next_clone)
- {
- node = node->next_clone;
- if (DECL_IS_GTM_CLONE (node->decl))
- break;
- }
-
- if (DECL_IS_GTM_CLONE (node->decl))
- {
- struct cgraph_edge *callers = orig_node->callers;
-
- /* find appropriate call stmt to redirect */
- while (callers)
- {
- if (callers->call_stmt != stmt)
- callers = callers->next_caller;
- else break;
- }
-
- /* substitute call stmt. */
- if (callers)
- {
- tree txn_ce;
- txn_ce = build_txn_call_expr (ce, node, txn_handle);
- if (TREE_CODE (stmt) == CALL_EXPR)
- {
- block_stmt_iterator bsi = bsi_for_stmt (stmt);
- bsi_insert_before (&bsi, txn_ce, BSI_SAME_STMT);
- bsi_remove (&bsi, true);
- }
- else
- GIMPLE_STMT_OPERAND (stmt, 1) = txn_ce;
-
- cgraph_redirect_edge_callee (callers, node);
- if (dump_file)
- fprintf(dump_file, "redirected edge to %s\n", get_name (node->decl));
- redirected = true;
- }
- }
-
- /* Redirect calls to malloc and related functions to transactional versions if available. */
-#ifdef TANGER
- if ((DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_MALLOC)
- ||(DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_CALLOC)
- || (DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_REALLOC)
- || (DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_FREE))
- {
- tree txn_ce;
- tree new_decl;
- if (DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_MALLOC)
- new_decl = built_in_decls[BUILT_IN_GTM_MALLOC];
- if (DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_CALLOC)
- new_decl = built_in_decls[BUILT_IN_GTM_CALLOC];
- if (DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_REALLOC)
- new_decl = built_in_decls[BUILT_IN_GTM_REALLOC];
- if (DECL_FUNCTION_CODE (fn_decl) == BUILT_IN_FREE)
- new_decl = built_in_decls[BUILT_IN_GTM_FREE];
-
- tree arglist = CALL_EXPR_ARGS (ce);
-
- if (txn_handle)
- {
- arglist = chainon (arglist, build_tree_list (NULL_TREE, txn_handle));
- }
- txn_ce = build_function_call_expr (new_decl, arglist);
- if (DECL_FUNCTION_CODE (fn_decl) != BUILT_IN_FREE)
- txn_ce = build_gimple_modify_stmt (GIMPLE_STMT_OPERAND (stmt, 0), txn_ce);
-
- block_stmt_iterator bsi = bsi_for_stmt (stmt);
- bsi_insert_before (&bsi, txn_ce, BSI_SAME_STMT);
- bsi_remove (&bsi, true);
-
- }
-#endif
- /* In case the function call was not redirected and the function not marked as const or tm_pure,
- issue a warning. */
- /* TODO: handling of calls to irrevocable functions can be expanded here. */
- if ((!redirected)
- && (TREE_READONLY(node->decl) != 1)
- && (DECL_IS_GTM_PURE (node->decl) != 1))
- {
- warning (0, "GTM: irrevocable functions not supported. Call to %qs potentially breaks isolation of transactions.", name);
- warning (0, "GTM: No transactional clone found for %qs.", name);
- }
- }
- return ;
-}
-
-/* This function expands the stmts within a
- transaction so that the corresponding STM
- versions of the stmt is called. */
static void
-replace_txn_stmt (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree txn_handle)
+maybe_transactify_call (gimple stmt)
{
- tree stmt = bsi_stmt(*bsi);
-
- /* TODO redirect call to tm clone use get_call_expr_in */
- tree ce = get_call_expr_in (stmt);
- if (ce)
- replace_call_expr_in_txn (ce, stmt, txn_handle);
-
- switch TREE_CODE (stmt) {
-
- case MODIFY_EXPR:
- case GIMPLE_MODIFY_STMT:
- replace_txn_mod_stmt (bsi, m, txn_handle);
- break;
-
- case CALL_EXPR:
- /* already handled above. */
- break;
-
- case GTM_ABORT:
- expand_gtm_abort (bsi, m, txn_handle);
- break;
-
- default:
- break;
- }
-
- return;
-}
-
-/* Mark recover_bb with a GTM-Return marker
- which is replaced by variables restoring the
- previous state during the checkpoint_gtm-pass. */
-static void
-setup_recover_bb (basic_block bb, tree label)
-{
- block_stmt_iterator bsi = bsi_start (bb);
- tree stmt = build1 (LABEL_EXPR, void_type_node, label);
-
- stmt = unshare_expr (stmt);
- bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
- stmt = make_node (GTM_RETURN);
- stmt = unshare_expr (stmt);
- bsi_insert_before (&bsi, stmt, BSI_SAME_STMT);
-
- return ;
-}
-
-/* Helper function that emits a call to STM
- run-time indicating the start of a transaction. */
-static void
-setup_begin_bb (basic_block bb, tree txn_handle, tree jmp_buf)
-{
- tree txn_begin;
- tree decl;
- tree read_only = build_int_cst (integer_type_node, 0);
- block_stmt_iterator bsi = bsi_start (bb);
-
- decl = built_in_decls[BUILT_IN_GTM_TXN_BEGIN];
-
- if (txn_handle != NULL_TREE)
- txn_begin = build_call_expr (decl, 3, txn_handle,
- jmp_buf, build_fold_addr_expr (read_only));
- else
- txn_begin = build_call_expr (decl, 2, jmp_buf,
- build_fold_addr_expr (read_only));
- txn_begin = unshare_expr (txn_begin);
- bsi_insert_before (&bsi, txn_begin, BSI_SAME_STMT);
-
- return ;
-}
-
-/* Helper function that emits call to
- abort the transaction in an STM-specific way. */
-static void
-expand_gtm_abort (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree txn_handle)
-{
- tree decl;
- tree call;
-
- decl = built_in_decls [BUILT_IN_GTM_ABORT];
- if (txn_handle != NULL_TREE)
- call = build_call_expr (decl, 1, txn_handle);
- else
- call = build_call_expr (decl, 0);
- call = unshare_expr (call);
- bsi_insert_before (bsi, call, m);
- bsi_remove(bsi, true);
-
- return ;
-}
-
-#ifdef GTM_EXPL_HANDLE
-/* Insert call to stm_init at beginning of function. */
-static tree
-maybe_insert_stm_new (enum bsi_iterator_update m)
-{
- basic_block bb;
-
- FOR_EACH_BB (bb)
- {
- int idx = bb->index;
- /* TODO find a better place to put this call (works so far) */
- if (idx == 2)
- {
- /* Avoid redundant calls to stm_new */
- block_stmt_iterator bsi = bsi_start (bb);
- tree mod = bsi_stmt (bsi);
- if (TREE_CODE (mod) == GIMPLE_MODIFY_STMT)
- {
- tree ce = GIMPLE_STMT_OPERAND (mod, 1);
- if (TREE_CODE (ce) == CALL_EXPR)
- {
- char *name = get_name (get_callee_fndecl (ce));
-#ifdef TINYSTM_VERSION_0_9_0b1
- if (strncmp (name, "__builtin_stm_new", 17) == 0)
-#endif
-#ifdef TANGER
- if (strncmp (name, "__builtin_tanger_stm_get_tx", 27) == 0)
-#endif
- {
- return GIMPLE_STMT_OPERAND (mod, 0);
- }
- }
- }
-
- /* stm_txn_t *tx;
- tx = stm_new (); */
- tree ptr_void = build_pointer_type (void_type_node);
- tree txn_handle = create_tmp_var (ptr_void, "txn_handle");
- tree decl = built_in_decls[BUILT_IN_GTM_NEW];
- tree call = build_call_expr (decl, 0);
- tree stmt = build_gimple_modify_stmt (txn_handle, call);
- stmt = unshare_expr (stmt);
- bsi_insert_before (&bsi, stmt, m);
-
- return txn_handle;
- }
- }
- return NULL_TREE;
-}
-#endif
-
-#ifndef TINYSTM_VERSION_0_9_0b1
-/* Helper function to insert call to stm_init_thread. */
-static void
-insert_stm_init_thread (block_stmt_iterator bsi)
-{
- tree decl = built_in_decls[BUILT_IN_GTM_INIT_THREAD];
- tree call = build_call_expr (decl, 0);
- call = unshare_expr (call);
- bsi_insert_before (&bsi, call, BSI_SAME_STMT);
-}
-
-/* Insert call to stm_init_thread at beginning of function. */
-static void
-maybe_insert_stm_init_thread (void)
-{
- basic_block bb;
-
- FOR_EACH_BB (bb)
- {
- int idx = bb->index;
- /* TODO find a better place to put this call (works so far) */
- if (idx == 2)
- {
- block_stmt_iterator bsi = bsi_start (bb);
-
- /* Avoid redundant calls to stm_init_thread */
- tree tmp = bsi_stmt (bsi);
- if (TREE_CODE (tmp) == CALL_EXPR)
- {
- char *name = get_name (get_callee_fndecl (tmp));
-#ifdef TINYSTM_VERSION_0_9_5
- if (strncmp (name, "__builtin_stm_init_thread", 25) == 0)
- return ;
-#endif
-#ifdef TANGER
- if (strncmp (name, "__builtin_tanger_stm_thread_init", 32) == 0)
- return ;
-#endif
- }
- insert_stm_init_thread (bsi);
- return ;
- }
- }
- return ;
-}
-
-/* Helper function inserting calls to stm_exit_thread. */
-static void
-insert_stm_exit_thread (block_stmt_iterator bsi, bool after)
-{
- tree decl = built_in_decls[BUILT_IN_GTM_EXIT_THREAD];
- tree call = build_call_expr (decl, 0);
- call = unshare_expr (call);
-
- if (after)
- bsi_insert_after (&bsi, call, BSI_SAME_STMT);
- else
- bsi_insert_before (&bsi, call, BSI_SAME_STMT);
-
- return ;
-}
-
-/* Helper function inserting calls to stm_exit_thread at RET_EXPR. */
-static void
-insert_stm_exit_thread_ret_expr (block_stmt_iterator bsi_last_bb)
-{
- bool after = false;
-
- gcc_assert (!bsi_end_p (bsi_last_bb));
- tree ret_expr = bsi_stmt (bsi_last_bb);
-
- gcc_assert (ret_expr);
-
- if (TREE_CODE (ret_expr) == RETURN_EXPR)
- {
- if (!bsi_end_p (bsi_last_bb))
- {
- block_stmt_iterator save = bsi_last_bb;
- bsi_prev (&bsi_last_bb);
- if (! bsi_end_p (bsi_last_bb))
- {
- after = true;
- tree bef_ret = bsi_stmt (bsi_last_bb);
- if (TREE_CODE (bef_ret) == CALL_EXPR)
- {
- char *name = get_name (get_callee_fndecl (bef_ret));
-#ifdef TINYSTM_VERSION_0_9_5
- if (strncmp (name, "__builtin_stm_exit_thread", 25) == 0)
- return ;
-#endif
-#ifdef TANGER
- if (strncmp (name, "__builtin_tanger_stm_thread_exit", 32) == 0)
- return ;
-#endif
- }
- }
- else
- {
- bsi_last_bb = save;
- after = false;
- }
- insert_stm_exit_thread (bsi_last_bb, after);
- }
- }
- else
- {
- gcc_unreachable();
- }
- return ;
-}
+ bool redirected = false;
+ tree fn_decl;
+ struct cgraph_node *node, *orig_node;
+ int flags;
-/* Insert call to stm_exit_thread at the end of function. */
-static void
-maybe_insert_stm_exit_thread(void)
-{
- basic_block last_bb;
- block_stmt_iterator bsi_last_bb;
- edge e;
- edge_iterator ei;
+ flags = gimple_call_flags (stmt);
+ if (flags & ECF_CONST)
+ return;
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ fn_decl = gimple_call_fndecl (stmt);
+ if (!fn_decl)
{
- last_bb = e->src;
- bsi_last_bb = bsi_last (last_bb);
- insert_stm_exit_thread_ret_expr (bsi_last_bb);
+ warning (0, "Indirect call potentially breaks isolation of transactions");
+ return;
}
- return ;
-}
-#endif
-
-/* Expand the begin of an transaction to
- set up the transaction in an STM-specific way. */
-static tree
-expand_gtm_txn_marker (struct gtm_region *region, block_stmt_iterator *bsi, enum bsi_iterator_update m, basic_block recover_bb, basic_block begin_bb)
-{
- tree decl;
- tree txn_handle;
- tree sigsetjmp, ssjval;
- tree mask;
- tree jmp_buf;
- tree get;
- tree stmt;
- tree list;
- tree recover_label;
- tree ptr_void = build_pointer_type (void_type_node);
-
- /* stm_txn_t *tx;
- tx = stm_new (); */
-#ifdef GTM_EXPL_HANDLE
- txn_handle = maybe_insert_stm_new (m);
-#endif
- /* TODO check if this condition still holds for other STMs. */
-#ifndef TINYSTM_VERSION_0_9_0b1
- insert_stm_init_thread(*bsi);
- txn_handle = NULL_TREE;
-#endif
-
- /* jmp_buf *e;
- e = stm_get_env (tx); */
- jmp_buf = create_tmp_var (ptr_void, "jmp_buf");
- decl = built_in_decls[BUILT_IN_GTM_GET_ENV];
- if (txn_handle != NULL_TREE)
- get = build_call_expr (decl, 1, txn_handle);
- else
- get = build_call_expr (decl, 0);
- stmt = build_gimple_modify_stmt (jmp_buf, get);
- stmt = unshare_expr (stmt);
- bsi_insert_before (bsi, stmt, m);
-
- /* CHECK: if sigsetjmp is called with a non-zero
- argument it saves the signal mask
- as part of the environment.
- Currently the setjmp call is done manually.
- TODO: Future work would be to use GCC's EH machinery. */
- ssjval = create_tmp_var (integer_type_node, "ssj_value");
- mask = build_int_cst (integer_type_node, 0);
- list = build_function_type_list (integer_type_node, ptr_type_node, NULL_TREE);
- decl = build_decl (FUNCTION_DECL, get_identifier ("_setjmp"), list);
- sigsetjmp = build_call_expr (decl, 1, jmp_buf);
- stmt = build_gimple_modify_stmt (ssjval, sigsetjmp);
- stmt = unshare_expr (stmt);
- bsi_insert_before (bsi, stmt, m);
- region->setjmp_stmt = stmt;
-
- recover_label = create_artificial_label ();
-
- stmt = build3 (COND_EXPR, void_type_node,
- fold_build2 (EQ_EXPR, boolean_type_node, ssjval, integer_zero_node),
- NULL_TREE,
- NULL_TREE);
- stmt = unshare_expr (stmt);
- bsi_insert_after (bsi, stmt, m);
-
- setup_recover_bb (recover_bb, recover_label);
- setup_begin_bb (begin_bb, txn_handle, jmp_buf);
-
- return txn_handle;
-}
-
-/* Helper function that emits call to
- commit the transaction in an STM-specific way. */
-static void
-expand_gtm_return (block_stmt_iterator *bsi, enum bsi_iterator_update m, tree txn_handle, bool end_txn)
-{
- tree decl;
- tree call;
- tree stm_commit_retval;
- tree stmt;
-
- decl = built_in_decls[BUILT_IN_GTM_TXN_COMMIT];
- if (txn_handle != NULL_TREE)
- call = build_call_expr (decl, 1, txn_handle);
- else
- call = build_call_expr (decl, 0);
-
- stm_commit_retval = create_tmp_var (integer_type_node, "stm_commit");
- add_referenced_var (stm_commit_retval);
-
- stmt = fold_build2 (GIMPLE_MODIFY_STMT, integer_type_node,
- stm_commit_retval, call);
- stmt = unshare_expr (stmt);
- bsi_insert_before (bsi, stmt, m);
-
-#ifdef TINYSTM_VERSION_0_9_5
- if (end_txn)
- maybe_insert_stm_exit_thread();
-#endif
-
-#ifdef TANGER
- if (end_txn)
- insert_stm_exit_thread(*bsi, true);
-#endif
+ if (DECL_IS_GTM_PURE (fn_decl))
+ return;
- return ;
-}
+ orig_node = node = cgraph_node (fn_decl);
-/* Insert call to stm_init at beginning of main function. */
-static void
-insert_stm_init(void)
-{
- /* TODO allow other functions here, since only C has a mandatory "main" entry point. */
- char *name = get_name (current_function_decl);
- if ((strncmp(name, "main", 4) != 0)
- || (strlen(name) > 4))
- return ;
-
- basic_block bb;
-
- FOR_EACH_BB (bb)
- {
- int idx = bb->index;
- /* TODO find a better place to put this call (works so far) */
- if (idx == 2)
- {
- block_stmt_iterator bsi = bsi_start (bb);
- tree decl;
- tree call;
-
- decl = built_in_decls[BUILT_IN_GTM_INIT];
- call = build_call_expr (decl, 0);
- call = unshare_expr (call);
-
- bsi_insert_before (&bsi, call, BSI_SAME_STMT);
- return ;
- }
- }
-
- gcc_unreachable();
- return ;
-}
-
-/* Insert call to stm_exit at the end of main function. */
-static void
-insert_stm_exit(void)
-{
- /* TODO allow other functions here, since only C has a mandatory "main" entry point. */
- char *name = get_name (current_function_decl);
- if ((strlen(name) > 4)
- || (strncmp(name, "main", 4) != 0))
- return ;
-
- tree decl;
- tree call;
-
- basic_block last_bb;
- block_stmt_iterator bsi_last_bb;
-
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ /* Find transactional clone of function. */
+ while (node && node->next_clone)
{
- last_bb = e->src;
- bsi_last_bb = bsi_last (last_bb);
- gcc_assert (!bsi_end_p (bsi_last_bb));
-
- tree tmp = bsi_stmt (bsi_last_bb);
- if (TREE_CODE (tmp) == RETURN_EXPR)
- {
- decl = built_in_decls[BUILT_IN_GTM_EXIT];
- call = build_call_expr (decl, 0);
- call = unshare_expr (call);
- bsi_insert_before (&bsi_last_bb, call, BSI_SAME_STMT);
- }
- else
- {
- gcc_unreachable();
- }
+ node = node->next_clone;
+ if (DECL_IS_GTM_CLONE (node->decl))
+ break;
}
- return ;
-}
-
-/* Initialize global data structures.*/
-void
-init_label_table (void)
-{
- unsigned int i;
-
- label_index = 0;
- e_index = 0;
-
- for (i = 0; i < NUM_BB_TXN; i++)
- edges_to_instrument[i] = NULL;
-
- return ;
-}
-
-/* Helper function marking all basic blocks
- of a transaction. */
-void
-record_bb_into_table (struct gtm_region *region, basic_block bb)
-{
- if (dump_file)
- fprintf (dump_file, "Record TXN Basic block %d\n", bb->index);
- region->txn_bbs[label_index] = bb->index;
- label_index++;
-
- return ;
-}
-
-/* Helper function that checks whether an edge from a
- basic block leaves the scope of a transaction. If
- it does the edge is marked for instrumentation. */
-void
-check_and_mark_edges (struct gtm_region *region, basic_block bb)
-{
- edge_iterator ei;
- edge e;
- unsigned int j;
- basic_block succ;
- bool found = false;
- FOR_EACH_EDGE (e, ei, bb->succs)
+ if (DECL_IS_GTM_CLONE (node->decl))
{
- succ = e->dest;
+ struct cgraph_edge *callers = orig_node->callers;
- for (j = 0; j < label_index; j++)
+ /* Find appropriate call stmt to redirect */
+ while (callers)
{
- if (region->txn_bbs[j] == succ->index)
- {
- if (dump_file)
- fprintf (dump_file, "found BB index %d in TXN\n", succ->index);
- found = true;
- break;
- }
+ if (callers->call_stmt == stmt)
+ break;
+ callers = callers->next_caller;
}
-
- if ((!found)
- && (succ != ENTRY_BLOCK_PTR)
- && (succ != EXIT_BLOCK_PTR))
+
+ /* Substitute call stmt. */
+ if (callers)
{
+ gimple_call_set_fndecl (stmt, node->decl);
+ cgraph_redirect_edge_callee (callers, node);
if (dump_file)
- fprintf (dump_file, "Did _NOT_ find BB index %d in TXN\n", succ->index);
-
- edges_to_instrument[e_index] = e;
- e_index++;
+ fprintf (dump_file, "redirected edge to %s\n",
+ get_name (node->decl));
+ redirected = true;
}
}
- return ;
-}
-
-/* Instrument all previously recorded edges with
- a call to stm_commit. */
-void
-instrument_edges (tree txn_handle)
-{
- unsigned int j;
- edge e;
-
- for (j = 0; j < e_index ; j++)
- {
- e = edges_to_instrument[j];
- gcc_assert (e);
-
- basic_block stm_commit_bb = split_edge (e);
- block_stmt_iterator bsi = bsi_start (stm_commit_bb);
- expand_gtm_return (&bsi, BSI_SAME_STMT, txn_handle, false);
- gcc_assert (single_succ_edge (stm_commit_bb)->flags = EDGE_FALLTHRU);
- }
-
- return ;
+ /* In case the function call was not redirected and the function
+ not marked as const or tm_pure, issue a warning. */
+ /* ??? Handling of calls to irrevocable functions can be expanded here. */
+ if (!redirected)
+ warning (0, "Call to %qD potentially breaks isolation of transactions.",
+ fn_decl);
}
-/* Instruments a return expression with a call to stm_commit. */
-void
-instrument_return_expr (block_stmt_iterator *bsi, tree txn_handle)
-{
- tree stmt = bsi_stmt (*bsi);
-
- if (TREE_CODE (stmt) == RETURN_EXPR)
- {
- expand_gtm_return (bsi, BSI_SAME_STMT, txn_handle, false);
- }
-
- return ;
-}
+/* This function expands the stmts within a transaction so that
+ the corresponding STM versions of the stmt is called. */
-/* Instruments transactions with calls to the STM runtime.
- Inserts new basic blocks at the beginning of the transaction
- to allow for variable saving and restoring (checkpointing)
- on SSA level. */
-static void
-expand_gtm_txn (struct gtm_region *region)
+static void ATTRIBUTE_UNUSED
+transactify_stmt (gimple_stmt_iterator *gsi)
{
- basic_block entry_bb, exit_bb, bb;
- block_stmt_iterator bsi;
-
- tree txn;
- tree txn_handle;
-
- entry_bb = region->entry;
- exit_bb = region->exit;
-
- gcc_assert (entry_bb);
- gcc_assert (exit_bb);
-
- bsi = bsi_last (entry_bb);
- txn = bsi_stmt (bsi);
-
- gcc_assert (TREE_CODE (txn) == GTM_TXN);
- init_label_table ();
-
- /* Split basic blocks and make edges: */
- /* BB with setjmp (entry_bb) -> BBrestore
- BB with setjmp (entry_bb) -> BBtxnbegin
- BBrestore -> BBtxnbegin
- */
- basic_block begin_bb = split_edge (single_succ_edge (entry_bb));
- basic_block recover_bb = split_edge (single_succ_edge (entry_bb));
-
- /* TODO redirect edge instead of destroy/create */
- /* Content to the basic blocks is added here. */
- txn_handle = expand_gtm_txn_marker (region, &bsi, BSI_SAME_STMT, recover_bb, begin_bb);
- bsi_remove (&bsi, true);
- remove_edge (single_succ_edge (entry_bb));
- make_edge (entry_bb, recover_bb, EDGE_FALSE_VALUE);
- make_edge (entry_bb, begin_bb, EDGE_TRUE_VALUE);
-
- single_succ_edge (begin_bb)->flags = EDGE_FALLTHRU;
- remove_edge (single_succ_edge (recover_bb));
- make_edge (recover_bb, begin_bb, EDGE_FALLTHRU);
-
- gcc_assert (exit_bb->next_bb);
+ gimple stmt = gsi_stmt (*gsi);
- FOR_BB_BETWEEN (bb, begin_bb, exit_bb->next_bb, next_bb)
+ switch (gimple_code (stmt))
{
- if (!bb)
- continue;
-
- record_bb_into_table (region, bb);
+ case GIMPLE_CALL:
+ maybe_transactify_call (stmt);
+ break;
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- instrument_return_expr (&bsi, txn_handle);
- replace_txn_stmt (&bsi, BSI_SAME_STMT, txn_handle);
- }
- }
-
- FOR_BB_BETWEEN (bb, begin_bb, exit_bb, next_bb)
- {
- if (!bb)
- continue;
+ case GIMPLE_ASSIGN:
+ /* Only memory reads/writes need to be instrumented. */
+ if (gimple_assign_single_p (stmt))
+ maybe_transactify_assign (stmt);
+ break;
- check_and_mark_edges (region, bb);
+ default:
+ break;
}
-
- instrument_edges (txn_handle);
-
- bsi = bsi_last (exit_bb);
- gcc_assert (!bsi_end_p (bsi)
- && TREE_CODE (bsi_stmt (bsi)) == GTM_RETURN);
-
- expand_gtm_return (&bsi, BSI_SAME_STMT, txn_handle, true);
- bsi_remove (&bsi, true);
-
- return;
}
-/* Instrument the GTM region tree rooted at REGION.
- We start with the inner regions first. */
-/* TODO adjust for nested transactions! */
-static void
-expand_gtm (struct gtm_region *region)
-{
- while (region)
- {
- /* First, expand the inner regions. */
- if (region->inner)
- expand_gtm (region->inner);
-
- gcc_assert ((region->type) == GTM_TXN);
- expand_gtm_txn (region);
- region = region->next;
- }
-}
+/* Main entry point for expanding GTM-GIMPLE into runtime calls to the STM. */
-/* TM function cloning: helper function that helps to
- annotate function body of GTM clone.
- Transactions from the original version are removed. */
-static void
-annotate_gtm_function_body (void)
-{
- tree txn_handle;
- /* By construction txn_handle is last parameter of the
- argument list of the function. */
-#ifdef GTM_EXPL_HANDLE
- txn_handle = tree_last (DECL_ARGUMENTS (current_function_decl));
-#endif
-
-#ifdef TINYSTM_VERSION_0_9_5
- txn_handle = NULL_TREE;
-#endif
-
- basic_block bb;
- block_stmt_iterator bsi;
- tree stmt;
-
- FOR_EACH_BB (bb)
- {
- for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
- {
- stmt = bsi_stmt (bsi);
- if (GTM_DIRECTIVE_P (stmt))
- {
- bsi_remove (&bsi, true);
- if (bsi_end_p (bsi)) break;
- }
- else
- replace_txn_stmt (&bsi, BSI_SAME_STMT, txn_handle);
- }
- }
-}
-
-/* Main entry point for expanding GTM-GIMPLE
- into runtime calls to the STM. */
static unsigned int
execute_expand_gtm (void)
{
- bool flat_nesting;
-
- /* In case we have to instrument
- a transactional clone. */
+ /* In case we have to instrument a transactional clone. */
if (DECL_IS_GTM_CLONE (current_function_decl))
{
if (!DECL_IS_GTM_PURE (current_function_decl))
- annotate_gtm_function_body();
- else
+ /* annotate_gtm_function_body () */ ;
+ else
{
- /* Function with tm_pure attribute specified. */
+#ifdef ENABLE_CHECKING
+ /* Function with tm_pure attribute specified. The front-end
+ should have generated the appropriate errors and dropped
+ the transaction trees on the floor. */
+ calculate_dominance_info (CDI_DOMINATORS);
build_gtm_regions ();
- if (root_gtm_region)
- {
- /* In case a tm_pure function attribute is combined with
- transactions, we end up here. Issue a warning and
- remove GTM markers. Since there is no standard how to
- treat this case, this may have to be changed. */
- warning (0, "GTM: ignored %qs used in function %qs declared as %qs.",
- "#pragma tm atomic",
- get_name (current_function_decl),
- "tm_pure");
- collapse_gtm_regions (root_gtm_region);
- remove_gtm_stmts (root_gtm_region);
- free (root_gtm_region);
- root_gtm_region = NULL;
- }
+ gcc_assert (root_gtm_region == NULL);
+ free_dominance_info (CDI_DOMINATORS);
+#endif
}
return 0;
}
-
- build_gtm_regions ();
- if (!root_gtm_region)
- {
- /* The reason for the following calls is that a
- program maybe transactified without using atomic regions
- inside the main-function. Here calls are inserted to ensure
- the proper initialisation of the STM library. */
- insert_stm_init();
- insert_stm_exit();
- return 0;
- }
-
- if (dump_file)
- {
- fprintf (dump_file, "\nGTM region tree\n\n");
- dump_gtm_region (dump_file, root_gtm_region, 0);
- fprintf (dump_file, "\n");
- }
-
- flat_nesting = query_STM_for_flat_nesting();
- if (flat_nesting)
+ calculate_dominance_info (CDI_DOMINATORS);
+ build_gtm_regions ();
+ if (root_gtm_region)
{
- collapse_gtm_regions (root_gtm_region);
-
if (dump_file)
{
- fprintf (dump_file, "\nGTM region tree after collapsing regions\n\n");
+ fprintf (dump_file, "\nGTM region tree\n\n");
dump_gtm_region (dump_file, root_gtm_region, 0);
fprintf (dump_file, "\n");
}
- }
-
- expand_gtm (root_gtm_region); /* instrumentation is done here. */
- insert_stm_init();
- insert_stm_exit();
+ /* expand_gtm (root_gtm_region); */
+ cleanup_tree_cfg ();
+ }
free_dominance_info (CDI_DOMINATORS);
-
- cleanup_tree_cfg ();
-
return 0;
}
-/* GTM expansion -- the default pass,
- run before creation of SSA form. */
+/* GTM expansion -- the default pass, run before creation of SSA form. */
+
static bool
gate_expand_gtm (void)
{
return flag_gtm;
}
-struct tree_opt_pass pass_expand_gtm =
- {
- "gtmexp", /* name */
- gate_expand_gtm, /* gate */
- execute_expand_gtm, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- 0, /* tv_id */
- PROP_gimple_any, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- TODO_dump_func, /* todo_flags_start */
- TODO_cleanup_cfg
- | TODO_ggc_collect, /* todo_flags_finish */
- 0 /* letter */
- };
+struct gimple_opt_pass pass_expand_gtm =
+{
+ {
+ GIMPLE_PASS,
+ "gtmexp", /* name */
+ gate_expand_gtm, /* gate */
+ execute_expand_gtm, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ PROP_gimple_any, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func
+ | TODO_cleanup_cfg
+ | TODO_ggc_collect, /* todo_flags_finish */
+ }
+};
+
-/* Calculate live ranges on SSA. Then checkpoint the
+#if 0
+/* Calculate live ranges on SSA. Then checkpoint the
live-in variables to the transaction. */
-void
-checkpoint_live_in_variables (struct gtm_region *region, block_stmt_iterator *bsi_recover, basic_block begin_bb)
+
+static void
+checkpoint_live_in_variables (struct gtm_region *region,
+ gimple_stmt_iterator *gsi_recover,
+ basic_block begin_bb)
{
int index = begin_bb->index;
block_stmt_iterator bsi_save = bsi_for_stmt (region->setjmp_stmt);
@@ -1759,7 +454,7 @@ checkpoint_live_in_variables (struct gtm
int p;
tree rep;
unsigned int i;
- unsigned int j;
+ unsigned int j;
bitmap_iterator bi;
map = init_var_map (num_ssa_names + 1);
@@ -1768,10 +463,10 @@ checkpoint_live_in_variables (struct gtm
for (j = 0; j < num_ssa_names; j++)
{
ssa_var = ssa_name (j);
- if (!ssa_var)
+ if (!ssa_var)
continue;
- if (TREE_CODE (ssa_var) == SSA_NAME)
+ if (TREE_CODE (ssa_var) == SSA_NAME)
{
register_ssa_partition (map, ssa_var);
p = partition_find (map->var_partition, SSA_NAME_VERSION (ssa_var));
@@ -1782,7 +477,7 @@ checkpoint_live_in_variables (struct gtm
liveinfo = calculate_live_ranges (map);
- /* If variable is live-in at beginning of the
+ /* If variable is live-in at beginning of the
transaction checkpoint its value. */
if (liveinfo->livein)
{
@@ -1792,20 +487,20 @@ checkpoint_live_in_variables (struct gtm
EXECUTE_IF_SET_IN_BITMAP (liveinfo->livein[index], 0, i, bi)
{
tree var = partition_to_var (map, i);
-
- /* TODO check restricts the use of temporaries by the compiler
+
+ /* TODO check restricts the use of temporaries by the compiler
may impact other optimisations.
- Maybe reordering this part of the checkpointing before introducing
+ Maybe reordering this part of the checkpointing before introducing
temporary variables would avoid this check. */
if ((!DECL_ARTIFICIAL (SSA_NAME_VAR (var)))
- && (!POINTER_TYPE_P (TREE_TYPE (var))))
+ && (!POINTER_TYPE_P (TREE_TYPE (var))))
{
- if (dump_file)
+ if (dump_file)
{
print_generic_expr (dump_file, var, TDF_SLIM);
fprintf (dump_file, " ");
}
- /* Create name for temporary variable
+ /* Create name for temporary variable
that checkpoints value of var. */
const char* orig = get_name (SSA_NAME_VAR (var));
int len = strlen (orig);
@@ -1813,13 +508,13 @@ checkpoint_live_in_variables (struct gtm
strncpy (name, "txn_save_", 9);
strncpy (name + 9, orig, len);
*(name + len + 9) = '\0';
-
+
/* Create temporary. */
tree type = TREE_TYPE (var);
tree save = create_tmp_var (type, name);
add_referenced_var (save);
tree stmt;
-
+
/* Create gimple statement for saving value of var. */
stmt = fold_build2 (GIMPLE_MODIFY_STMT, type, save, var);
tree real_save = make_ssa_name (save, stmt);
@@ -1839,7 +534,7 @@ checkpoint_live_in_variables (struct gtm
add_phi_arg (phi, new_var, FALLTHRU_EDGE (recover_bb));
add_phi_arg (phi, var, FALLTHRU_EDGE (save_bb));
tree new_var_phi = PHI_RESULT (phi);
-
+
free_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_DOMINATORS);
@@ -1862,26 +557,26 @@ checkpoint_live_in_variables (struct gtm
}
if (dump_file)
fprintf (dump_file, "\n");
-
+
}
update_ssa(TODO_update_ssa);
return ;
}
-/* Implements the checkpointing of transactions. */
-static void
+/* Implements the checkpointing of transactions. */
+static void
checkpoint_gtm_txn (struct gtm_region *region)
{
basic_block entry_bb = bb_for_stmt (region->setjmp_stmt);
edge branch = BRANCH_EDGE (entry_bb);
edge fall = FALLTHRU_EDGE (entry_bb);
-
+
basic_block begin_bb = fall->dest;
basic_block recover_bb = branch->dest;
basic_block next_bb = single_succ (recover_bb);
-
+
gcc_assert(begin_bb == next_bb);
block_stmt_iterator bsi_recover = bsi_start (recover_bb);
gcc_assert (TREE_CODE (bsi_stmt (bsi_recover)) == LABEL_EXPR);
@@ -1889,13 +584,11 @@ checkpoint_gtm_txn (struct gtm_region *r
bsi_next (&bsi_recover);
gcc_assert (TREE_CODE (bsi_stmt (bsi_recover)) == GTM_RETURN);
- checkpoint_live_in_variables (region, &bsi_recover, begin_bb);
- /* Remove the previously set GTM_RETURN markers
- from the recover basic block. */
- bsi_remove (&bsi_recover, true);
-
- return ;
-}
+ checkpoint_live_in_variables (region, &bsi_recover, begin_bb);
+ /* Remove the previously set GTM_RETURN markers
+ from the recover basic block. */
+ bsi_remove (&bsi_recover, true);
+}
/* Walk the region tree and start checkpointing. */
static void
@@ -1904,7 +597,7 @@ checkpoint_gtm (struct gtm_region *regio
while (region)
{
/* First, introduce checkpoints for the inner regions.
- TODO: testing. Overlapping of inner and outer
+ TODO: testing. Overlapping of inner and outer
regions not handled correctly.
Nesting of transactions not implemented correctly.*/
if (region->inner)
@@ -1914,7 +607,7 @@ checkpoint_gtm (struct gtm_region *regio
gcc_assert ((region->type) == GTM_TXN);
checkpoint_gtm_txn (region);
-
+
region = region->next;
}
}
@@ -1925,11 +618,11 @@ execute_checkpoint_gtm (void)
{
/* Regions are built during GTM expansion pass. */
if (!root_gtm_region)
- return ;
-
+ return;
+
/* Checkpointing is done here. */
- checkpoint_gtm (root_gtm_region);
-
+ checkpoint_gtm (root_gtm_region);
+
if (dump_file)
{
fprintf (dump_file, "\nGTM region tree after checkpointing\n\n");
@@ -1940,7 +633,7 @@ execute_checkpoint_gtm (void)
free_dominance_info (CDI_DOMINATORS);
cleanup_tree_cfg ();
free_gtm_regions ();
-
+
return;
}
@@ -1951,25 +644,22 @@ gate_checkpoint_gtm (void)
return flag_gtm;
}
-struct tree_opt_pass pass_checkpoint_gtm =
- {
- "gtmcheckpoint", /* name */
- gate_checkpoint_gtm, /* gate */
- execute_checkpoint_gtm, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- 0, /* tv_id */
- PROP_ssa | PROP_cfg, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_update_ssa |
- TODO_verify_ssa |
- TODO_dump_func, /* todo_flags_finish */
- 0 /* letter */
- };
-
-
-
-
+struct tree_opt_pass pass_checkpoint_gtm =
+{
+ "gtmcheckpoint", /* name */
+ gate_checkpoint_gtm, /* gate */
+ execute_checkpoint_gtm, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ PROP_ssa | PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_update_ssa |
+ TODO_verify_ssa |
+ TODO_dump_func, /* todo_flags_finish */
+ 0 /* letter */
+};
+#endif
--- omp-low.c (revision 141060)
+++ omp-low.c (local)
@@ -1622,7 +1622,7 @@ scan_omp_parallel (gimple_stmt_iterator
/* Ignore parallel directives with empty bodies, unless there
are copyin clauses. */
if (optimize > 0
- && empty_body_p (gimple_omp_body (stmt))
+ && empty_body_p (gimple_seq_body (stmt))
&& find_omp_clause (gimple_omp_parallel_clauses (stmt),
OMP_CLAUSE_COPYIN) == NULL)
{
@@ -1643,7 +1643,7 @@ scan_omp_parallel (gimple_stmt_iterator
gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
- scan_omp (gimple_omp_body (stmt), ctx);
+ scan_omp (gimple_seq_body (stmt), ctx);
if (TYPE_FIELDS (ctx->record_type) == NULL)
ctx->record_type = ctx->receiver_decl = NULL;
@@ -1665,7 +1665,7 @@ scan_omp_task (gimple_stmt_iterator *gsi
/* Ignore task directives with empty bodies. */
if (optimize > 0
- && empty_body_p (gimple_omp_body (stmt)))
+ && empty_body_p (gimple_seq_body (stmt)))
{
gsi_replace (gsi, gimple_build_nop (), false);
return;
@@ -1693,7 +1693,7 @@ scan_omp_task (gimple_stmt_iterator *gsi
create_omp_child_function (ctx, true);
}
- scan_omp (gimple_omp_body (stmt), ctx);
+ scan_omp (gimple_seq_body (stmt), ctx);
if (TYPE_FIELDS (ctx->record_type) == NULL)
{
@@ -1754,7 +1754,7 @@ scan_omp_for (gimple stmt, omp_context *
scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
}
- scan_omp (gimple_omp_body (stmt), ctx);
+ scan_omp (gimple_seq_body (stmt), ctx);
}
/* Scan an OpenMP sections directive. */
@@ -1766,7 +1766,7 @@ scan_omp_sections (gimple stmt, omp_cont
ctx = new_omp_context (stmt, outer_ctx);
scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
- scan_omp (gimple_omp_body (stmt), ctx);
+ scan_omp (gimple_seq_body (stmt), ctx);
}
/* Scan an OpenMP single directive. */
@@ -1785,7 +1785,7 @@ scan_omp_single (gimple stmt, omp_contex
TYPE_NAME (ctx->record_type) = name;
scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
- scan_omp (gimple_omp_body (stmt), ctx);
+ scan_omp (gimple_seq_body (stmt), ctx);
if (TYPE_FIELDS (ctx->record_type) == NULL)
ctx->record_type = NULL;
@@ -1981,7 +1981,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *g
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
ctx = new_omp_context (stmt, ctx);
- scan_omp (gimple_omp_body (stmt), ctx);
+ scan_omp (gimple_seq_body (stmt), ctx);
break;
case GIMPLE_BIND:
@@ -5419,11 +5419,11 @@ lower_omp_sections (gimple_stmt_iterator
lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
&ilist, &dlist, ctx);
- tgsi = gsi_start (gimple_omp_body (stmt));
+ tgsi = gsi_start (gimple_seq_body (stmt));
for (len = 0; !gsi_end_p (tgsi); len++, gsi_next (&tgsi))
continue;
- tgsi = gsi_start (gimple_omp_body (stmt));
+ tgsi = gsi_start (gimple_seq_body (stmt));
body = NULL;
for (i = 0; i < len; i++, gsi_next (&tgsi))
{
@@ -5436,9 +5436,9 @@ lower_omp_sections (gimple_stmt_iterator
gimple_seq_add_stmt (&body, sec_start);
- lower_omp (gimple_omp_body (sec_start), sctx);
- gimple_seq_add_seq (&body, gimple_omp_body (sec_start));
- gimple_omp_set_body (sec_start, NULL);
+ lower_omp (gimple_seq_body (sec_start), sctx);
+ gimple_seq_add_seq (&body, gimple_seq_body (sec_start));
+ gimple_seq_set_body (sec_start, NULL);
if (i == len - 1)
{
@@ -5489,7 +5489,7 @@ lower_omp_sections (gimple_stmt_iterator
gimple_seq_add_stmt (&new_body, t);
gimple_bind_set_body (new_stmt, new_body);
- gimple_omp_set_body (stmt, NULL);
+ gimple_seq_set_body (stmt, NULL);
gsi_replace (gsi_p, new_stmt, true);
}
@@ -5525,7 +5525,7 @@ lower_omp_single_simple (gimple single_s
tlabel, flabel);
gimple_seq_add_stmt (pre_p, cond);
gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
- gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
+ gimple_seq_add_seq (pre_p, gimple_seq_body (single_stmt));
gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
}
@@ -5586,7 +5586,7 @@ lower_omp_single_copy (gimple single_stm
gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
- gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
+ gimple_seq_add_seq (pre_p, gimple_seq_body (single_stmt));
copyin_seq = NULL;
lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
@@ -5622,7 +5622,7 @@ lower_omp_single (gimple_stmt_iterator *
bind_body = NULL;
lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
&bind_body, &dlist, ctx);
- lower_omp (gimple_omp_body (single_stmt), ctx);
+ lower_omp (gimple_seq_body (single_stmt), ctx);
gimple_seq_add_stmt (&bind_body, single_stmt);
@@ -5631,7 +5631,7 @@ lower_omp_single (gimple_stmt_iterator *
else
lower_omp_single_simple (single_stmt, &bind_body);
- gimple_omp_set_body (single_stmt, NULL);
+ gimple_seq_set_body (single_stmt, NULL);
gimple_seq_add_seq (&bind_body, dlist);
@@ -5678,10 +5678,10 @@ lower_omp_master (gimple_stmt_iterator *
gimplify_and_add (x, &tseq);
gimple_bind_add_seq (bind, tseq);
- lower_omp (gimple_omp_body (stmt), ctx);
- gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
- gimple_bind_add_seq (bind, gimple_omp_body (stmt));
- gimple_omp_set_body (stmt, NULL);
+ lower_omp (gimple_seq_body (stmt), ctx);
+ gimple_seq_set_body (stmt, maybe_catch_exception (gimple_seq_body (stmt)));
+ gimple_bind_add_seq (bind, gimple_seq_body (stmt));
+ gimple_seq_set_body (stmt, NULL);
gimple_bind_add_stmt (bind, gimple_build_label (lab));
@@ -5713,10 +5713,10 @@ lower_omp_ordered (gimple_stmt_iterator
x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_START], 0);
gimple_bind_add_stmt (bind, x);
- lower_omp (gimple_omp_body (stmt), ctx);
- gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
- gimple_bind_add_seq (bind, gimple_omp_body (stmt));
- gimple_omp_set_body (stmt, NULL);
+ lower_omp (gimple_seq_body (stmt), ctx);
+ gimple_seq_set_body (stmt, maybe_catch_exception (gimple_seq_body (stmt)));
+ gimple_bind_add_seq (bind, gimple_seq_body (stmt));
+ gimple_seq_set_body (stmt, NULL);
x = gimple_build_call (built_in_decls[BUILT_IN_GOMP_ORDERED_END], 0);
gimple_bind_add_stmt (bind, x);
@@ -5805,10 +5805,10 @@ lower_omp_critical (gimple_stmt_iterator
gimplify_and_add (lock, &tbody);
gimple_bind_set_body (bind, tbody);
- lower_omp (gimple_omp_body (stmt), ctx);
- gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
- gimple_bind_add_seq (bind, gimple_omp_body (stmt));
- gimple_omp_set_body (stmt, NULL);
+ lower_omp (gimple_seq_body (stmt), ctx);
+ gimple_seq_set_body (stmt, maybe_catch_exception (gimple_seq_body (stmt)));
+ gimple_bind_add_seq (bind, gimple_seq_body (stmt));
+ gimple_seq_set_body (stmt, NULL);
tbody = gimple_bind_body (bind);
gimplify_and_add (unlock, &tbody);
@@ -5888,14 +5888,14 @@ lower_omp_for (gimple_stmt_iterator *gsi
push_gimplify_context (&gctx);
lower_omp (gimple_omp_for_pre_body (stmt), ctx);
- lower_omp (gimple_omp_body (stmt), ctx);
+ lower_omp (gimple_seq_body (stmt), ctx);
block = make_node (BLOCK);
new_stmt = gimple_build_bind (NULL, NULL, block);
/* Move declaration of temporaries in the loop body before we make
it go away. */
- omp_for_body = gimple_omp_body (stmt);
+ omp_for_body = gimple_seq_body (stmt);
if (!gimple_seq_empty_p (omp_for_body)
&& gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
{
@@ -5938,7 +5938,7 @@ lower_omp_for (gimple_stmt_iterator *gsi
lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
gimple_seq_add_stmt (&body, stmt);
- gimple_seq_add_seq (&body, gimple_omp_body (stmt));
+ gimple_seq_add_seq (&body, gimple_seq_body (stmt));
gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
fd.loop.v));
@@ -5960,7 +5960,7 @@ lower_omp_for (gimple_stmt_iterator *gsi
TREE_USED (block) = 1;
gimple_bind_set_body (new_stmt, body);
- gimple_omp_set_body (stmt, NULL);
+ gimple_seq_set_body (stmt, NULL);
gimple_omp_for_set_pre_body (stmt, NULL);
gsi_replace (gsi_p, new_stmt, true);
}
@@ -6288,7 +6288,7 @@ lower_omp_taskreg (gimple_stmt_iterator
struct gimplify_ctx gctx;
clauses = gimple_omp_taskreg_clauses (stmt);
- par_bind = gimple_seq_first_stmt (gimple_omp_body (stmt));
+ par_bind = gimple_seq_first_stmt (gimple_seq_body (stmt));
par_body = gimple_bind_body (par_bind);
child_fn = ctx->cb.dst_fn;
if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
@@ -6335,7 +6335,7 @@ lower_omp_taskreg (gimple_stmt_iterator
lower_send_shared_vars (&ilist, &olist, ctx);
/* Once all the expansions are done, sequence all the different
- fragments inside gimple_omp_body. */
+ fragments inside gimple_seq_body. */
new_body = NULL;
@@ -6353,7 +6353,7 @@ lower_omp_taskreg (gimple_stmt_iterator
gimple_seq_add_seq (&new_body, par_olist);
new_body = maybe_catch_exception (new_body);
gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
- gimple_omp_set_body (stmt, new_body);
+ gimple_seq_set_body (stmt, new_body);
bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
gimple_bind_add_stmt (bind, stmt);
@@ -6369,38 +6369,6 @@ lower_omp_taskreg (gimple_stmt_iterator
pop_gimplify_context (NULL);
}
-/* Simply introduces a new stmt_list (needed by gimple-low.c).
- Further add the GTM_RETURN at the end of the TXN.
- TODO: check for omp constructs in txn! */
-
-static void
-lower_gtm_txn (tree *stmt_p, omp_context *ctx)
-{
- tree txn_body, txn_bind;
- tree new_body, t;
- tree stmt;
-
- stmt = *stmt_p;
-
- push_gimplify_context ();
-
- txn_bind = GTM_TXN_BODY (stmt);
-
- txn_body = BIND_EXPR_BODY (txn_bind);
- lower_omp (&txn_body, ctx);
-
- new_body = alloc_stmt_list ();
-
- append_to_statement_list (txn_bind, &new_body);
-
- t = make_node (GTM_RETURN);
- append_to_statement_list (t, &new_body);
- GTM_TXN_BODY (stmt) = new_body;
- *stmt_p = stmt;
-
- pop_gimplify_context (NULL_TREE);
-}
-
/* Callback for lower_omp_1. Return non-NULL if *tp needs to be
regimplified. If DATA is non-NULL, lower_omp_1 is outside
of OpenMP context, but with task_shared_vars set. */
@@ -6684,7 +6652,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi
/* The minimal context here is just the current OMP construct. */
inner_context = stmt;
wi->info = inner_context;
- walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
+ walk_gimple_seq (gimple_seq_body (stmt), diagnose_sb_1, NULL, wi);
wi->info = context;
break;
@@ -6695,7 +6663,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi
walk them. */
walk_gimple_seq (gimple_omp_for_pre_body (stmt),
diagnose_sb_1, NULL, wi);
- walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
+ walk_gimple_seq (gimple_seq_body (stmt), diagnose_sb_1, NULL, wi);
wi->info = context;
break;
@@ -6704,10 +6672,6 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi
(splay_tree_value) context);
break;
- case GTM_TXN:
- lower_gtm_txn (tp, ctx);
- break;
-
default:
break;
}
@@ -6741,7 +6705,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
wi->info = stmt;
- walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi);
+ walk_gimple_seq (gimple_seq_body (stmt), diagnose_sb_2, NULL, wi);
wi->info = context;
break;
@@ -6751,7 +6715,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi
walk them. */
walk_gimple_seq (gimple_omp_for_pre_body (stmt),
diagnose_sb_2, NULL, wi);
- walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_2, NULL, wi);
+ walk_gimple_seq (gimple_seq_body (stmt), diagnose_sb_2, NULL, wi);
wi->info = context;
break;
--- passes.c (revision 141060)
+++ passes.c (local)
@@ -552,7 +552,7 @@ init_optimization_passes (void)
{
struct opt_pass **p = &pass_all_early_optimizations.pass.sub;
NEXT_PASS (pass_rebuild_cgraph_edges);
- NEXT_PASS (pass_checkpoint_gtm);
+ /* NEXT_PASS (pass_checkpoint_gtm); */
NEXT_PASS (pass_early_inline);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_ccp);
--- tree-cfg.c (revision 141060)
+++ tree-cfg.c (local)
@@ -614,7 +614,7 @@ make_edges (void)
break;
case GIMPLE_GTM_TXN:
- cur_gtm_region = new_gtm_region (bb, code, cur_gtm_region);
+ cur_gtm_region = new_gtm_region (bb, cur_gtm_region);
fallthru = true;
break;
@@ -1993,7 +1993,7 @@ remove_useless_stmts_1 (gimple_stmt_iter
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
{
- gimple_seq body_seq = gimple_omp_body (stmt);
+ gimple_seq body_seq = gimple_seq_body (stmt);
gimple_stmt_iterator body_gsi = gsi_start (body_seq);
remove_useless_stmts_1 (&body_gsi, data);
@@ -2007,7 +2007,7 @@ remove_useless_stmts_1 (gimple_stmt_iter
{
/* Make sure the outermost GIMPLE_BIND isn't removed
as useless. */
- gimple_seq body_seq = gimple_omp_body (stmt);
+ gimple_seq body_seq = gimple_seq_body (stmt);
gimple bind = gimple_seq_first_stmt (body_seq);
gimple_seq bind_seq = gimple_bind_body (bind);
gimple_stmt_iterator bind_gsi = gsi_start (bind_seq);
@@ -2586,7 +2586,7 @@ is_ctrl_altering_stmt (gimple t)
return true;
/* GTM directives alter control flow. */
- if (GTM_DIRECTIVE_P (t))
+ if (is_gimple_gtm (t))
return true;
/* If a statement can throw, it alters control flow. */
@@ -5599,7 +5599,7 @@ move_stmt_r (gimple_stmt_iterator *gsi_p
p->remap_decls_p = false;
*handled_ops_p = true;
- walk_gimple_seq (gimple_omp_body (stmt), move_stmt_r, move_stmt_op, wi);
+ walk_gimple_seq (gimple_seq_body (stmt), move_stmt_r, move_stmt_op, wi);
p->remap_decls_p = save_remap_decls_p;
}
--- tree-flow.h (revision 141060)
+++ tree-flow.h (local)
@@ -675,10 +675,7 @@ extern tree find_omp_clause (tree, enum
tree copy_var_decl (tree, tree, tree);
-/* GTM region information.
- Concept and parts of the implementation
- borrowed from OpenMP implementation. */
-#define NUM_BB_TXN 512
+/* GTM region information. */
struct gtm_region
{
@@ -697,20 +694,13 @@ struct gtm_region
/* Block containing the GTM_RETURN as its last stmt. */
basic_block exit;
- /* Since the blocks change this is the stmt containing the setjmp after expansion. */
- tree setjmp_stmt;
-
- /* Contains the bb indexes belonging to the transaction.
- TODO allocate int array dynamically. */
- int txn_bbs [NUM_BB_TXN];
-
- enum tree_code type;
+ /* Since the blocks change this is the stmt containing the setjmp
+ after expansion. */
+ gimple setjmp_stmt;
};
-
extern struct gtm_region *root_gtm_region;
-extern struct gtm_region *new_gtm_region (basic_block, enum tree_code,
- struct gtm_region *);
+extern struct gtm_region *new_gtm_region (basic_block, struct gtm_region *);
extern void free_gtm_regions (void);
/*---------------------------------------------------------------------------
--- tree-inline.c (revision 141060)
+++ tree-inline.c (local)
@@ -1094,7 +1094,7 @@ remap_gimple_stmt (gimple stmt, copy_bod
break;
case GIMPLE_OMP_PARALLEL:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_parallel
(s1,
gimple_omp_parallel_clauses (stmt),
@@ -1103,7 +1103,7 @@ remap_gimple_stmt (gimple stmt, copy_bod
break;
case GIMPLE_OMP_TASK:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_task
(s1,
gimple_omp_task_clauses (stmt),
@@ -1115,7 +1115,7 @@ remap_gimple_stmt (gimple stmt, copy_bod
break;
case GIMPLE_OMP_FOR:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
s2 = remap_gimple_seq (gimple_omp_for_pre_body (stmt), id);
copy = gimple_build_omp_for (s1, gimple_omp_for_clauses (stmt),
gimple_omp_for_collapse (stmt), s2);
@@ -1138,34 +1138,34 @@ remap_gimple_stmt (gimple stmt, copy_bod
break;
case GIMPLE_OMP_MASTER:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_master (s1);
break;
case GIMPLE_OMP_ORDERED:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_ordered (s1);
break;
case GIMPLE_OMP_SECTION:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_section (s1);
break;
case GIMPLE_OMP_SECTIONS:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_sections
(s1, gimple_omp_sections_clauses (stmt));
break;
case GIMPLE_OMP_SINGLE:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy = gimple_build_omp_single
(s1, gimple_omp_single_clauses (stmt));
break;
case GIMPLE_OMP_CRITICAL:
- s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ s1 = remap_gimple_seq (gimple_seq_body (stmt), id);
copy
= gimple_build_omp_critical (s1, gimple_omp_critical_name (stmt));
break;
@@ -2958,7 +2958,7 @@ estimate_num_insns (gimple stmt, eni_wei
case GIMPLE_OMP_FOR:
return (weights->omp_cost
- + estimate_num_insns_seq (gimple_omp_body (stmt), weights)
+ + estimate_num_insns_seq (gimple_seq_body (stmt), weights)
+ estimate_num_insns_seq (gimple_omp_for_pre_body (stmt), weights));
case GIMPLE_OMP_PARALLEL:
@@ -2970,17 +2970,17 @@ estimate_num_insns (gimple stmt, eni_wei
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
return (weights->omp_cost
- + estimate_num_insns_seq (gimple_omp_body (stmt), weights));
+ + estimate_num_insns_seq (gimple_seq_body (stmt), weights));
/* These GTM directives are cheap enough. */
- case GTM_RETURN:
- case GTM_ABORT:
+ case GIMPLE_GTM_RETURN:
+ case GIMPLE_GTM_ABORT:
return 0;
/* The entire transaction, however, is expensive. */
- case GTM_TXN:
+ case GIMPLE_GTM_TXN:
return (weights->gtm_txn_cost
- + estimate_num_insns_seq (gimple_gtm_txn_body (stmt), weights));
+ + estimate_num_insns_seq (gimple_seq_body (stmt), weights));
default:
gcc_unreachable ();
--- tree-nested.c (revision 141060)
+++ tree-nested.c (local)
@@ -1154,11 +1154,11 @@ convert_nonlocal_reference_stmt (gimple_
info->new_local_var_chain = NULL;
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
if (info->new_local_var_chain)
declare_vars (info->new_local_var_chain,
- gimple_seq_first_stmt (gimple_omp_body (stmt)),
+ gimple_seq_first_stmt (gimple_seq_body (stmt)),
false);
info->new_local_var_chain = save_local_var_chain;
info->suppress_expansion = save_suppress;
@@ -1170,7 +1170,7 @@ convert_nonlocal_reference_stmt (gimple_
walk_gimple_omp_for (stmt, convert_nonlocal_reference_stmt,
convert_nonlocal_reference_op, info);
walk_body (convert_nonlocal_reference_stmt,
- convert_nonlocal_reference_op, info, gimple_omp_body (stmt));
+ convert_nonlocal_reference_op, info, gimple_seq_body (stmt));
info->suppress_expansion = save_suppress;
break;
@@ -1178,7 +1178,7 @@ convert_nonlocal_reference_stmt (gimple_
save_suppress = info->suppress_expansion;
convert_nonlocal_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
info->suppress_expansion = save_suppress;
break;
@@ -1186,7 +1186,7 @@ convert_nonlocal_reference_stmt (gimple_
save_suppress = info->suppress_expansion;
convert_nonlocal_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
info->suppress_expansion = save_suppress;
break;
@@ -1194,7 +1194,7 @@ convert_nonlocal_reference_stmt (gimple_
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
break;
default:
@@ -1549,11 +1549,11 @@ convert_local_reference_stmt (gimple_stm
info->new_local_var_chain = NULL;
walk_body (convert_local_reference_stmt, convert_local_reference_op, info,
- gimple_omp_body (stmt));
+ gimple_seq_body (stmt));
if (info->new_local_var_chain)
declare_vars (info->new_local_var_chain,
- gimple_seq_first_stmt (gimple_omp_body (stmt)), false);
+ gimple_seq_first_stmt (gimple_seq_body (stmt)), false);
info->new_local_var_chain = save_local_var_chain;
info->suppress_expansion = save_suppress;
break;
@@ -1564,7 +1564,7 @@ convert_local_reference_stmt (gimple_stm
walk_gimple_omp_for (stmt, convert_local_reference_stmt,
convert_local_reference_op, info);
walk_body (convert_local_reference_stmt, convert_local_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
info->suppress_expansion = save_suppress;
break;
@@ -1572,7 +1572,7 @@ convert_local_reference_stmt (gimple_stm
save_suppress = info->suppress_expansion;
convert_local_omp_clauses (gimple_omp_sections_clauses_ptr (stmt), wi);
walk_body (convert_local_reference_stmt, convert_local_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
info->suppress_expansion = save_suppress;
break;
@@ -1580,7 +1580,7 @@ convert_local_reference_stmt (gimple_stm
save_suppress = info->suppress_expansion;
convert_local_omp_clauses (gimple_omp_single_clauses_ptr (stmt), wi);
walk_body (convert_local_reference_stmt, convert_local_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
info->suppress_expansion = save_suppress;
break;
@@ -1588,7 +1588,7 @@ convert_local_reference_stmt (gimple_stm
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
walk_body (convert_local_reference_stmt, convert_local_reference_op,
- info, gimple_omp_body (stmt));
+ info, gimple_seq_body (stmt));
break;
default:
@@ -1866,7 +1866,7 @@ convert_gimple_call (gimple_stmt_iterato
case GIMPLE_OMP_TASK:
save_static_chain_added = info->static_chain_added;
info->static_chain_added = 0;
- walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
+ walk_body (convert_gimple_call, NULL, info, gimple_seq_body (stmt));
for (i = 0; i < 2; i++)
{
tree c, decl;
@@ -1903,7 +1903,7 @@ convert_gimple_call (gimple_stmt_iterato
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
- walk_body (convert_gimple_call, NULL, info, gimple_omp_body (stmt));
+ walk_body (convert_gimple_call, NULL, info, gimple_seq_body (stmt));
break;
default:
--- tree-pretty-print.c (revision 141060)
+++ tree-pretty-print.c (local)
@@ -1894,18 +1894,8 @@ dump_generic_node (pretty_printer *buffe
is_expr = false;
break;
- case GTM_ABORT:
- pp_string (buffer, "GTM_ABORT");
- is_expr = false;
- break;
-
- case GTM_RETURN:
- pp_string (buffer, "GTM_RETURN");
- is_expr = false;
- break;
-
case GTM_TXN:
- pp_string (buffer, "_Pragma(\"tm atomic\")");
+ pp_string (buffer, "__tm_atomic");
if (!(flags & TDF_SLIM) && GTM_TXN_BODY (node))
{
newline_and_indent (buffer, spc);
@@ -1918,6 +1908,11 @@ dump_generic_node (pretty_printer *buffe
is_expr = false;
break;
+ case GTM_ABORT:
+ pp_string (buffer, "GTM_ABORT");
+ is_expr = false;
+ break;
+
case REDUC_MAX_EXPR:
pp_string (buffer, " REDUC_MAX_EXPR < ");
dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
--- tree.def (revision 141060)
+++ tree.def (local)
@@ -1061,12 +1061,15 @@ DEFTREECODE (OMP_CLAUSE, "omp_clause", t
Operand 0: GTM_TXN_BODY: contains body of the transaction.*/
DEFTREECODE (GTM_TXN, "gtm_txn", tcc_statement, 1)
-/* Return from an GTM directive. */
-DEFTREECODE (GTM_RETURN, "gtm_return", tcc_statement, 0)
-
/* Abort an transaction. */
DEFTREECODE (GTM_ABORT, "gtm_abort", tcc_statement, 0)
+/* A read protected by a current transaction. */
+DEFTREECODE (GTM_LOAD, "gtm_load", tcc_expression, 1)
+
+/* A write protected by a current transaction. */
+DEFTREECODE (GTM_STORE, "gtm_store", tcc_expression, 1)
+
/* Reduction operations.
Operations that take a vector of elements and "reduce" it to a scalar
result (e.g. summing the elements of the vector, finding the minimum over
--- tree.h (revision 141060)
+++ tree.h (local)
@@ -177,12 +177,6 @@ extern const enum tree_code_class tree_c
#define EXPR_P(NODE) IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (NODE)))
-/* Returns nonzero iff NODE is an GTM directive. */
-
-#define GTM_DIRECTIVE_P(NODE) \
- (TREE_CODE (NODE) == GTM_TXN \
- || TREE_CODE (NODE) == GTM_RETURN)
-
/* Number of argument-words in each kind of tree-node. */
extern const unsigned char tree_code_length[];
@@ -3269,11 +3263,13 @@ struct tree_decl_non_common GTY(())
of a function - called only from inside transactions. */
#define DECL_IS_GTM_CLONE(NODE) (FUNCTION_DECL_CHECK (NODE)->function_decl.gtm_clone_flag)
+#if 0
/* Nonzero in a FUNCTION_DECL means this function should be treated
as "tm_unknown" function - behaviour of transactions depends
on STM system to supports irrevocable calls. */
#define DECL_IS_GTM_UNKNOWN(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.gtm_unknown_flag)
+#endif
/* Nonzero in a FUNCTION_DECL means this function should be treated
as "tm_callable" function - function maybe called from within a transaction. */