aboutsummaryrefslogtreecommitdiff
path: root/gcc/omp-low.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-05-24 23:31:59 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2019-05-24 23:31:59 +0200
commit6c7ae8c56f9341f180e097d5eb7ba05cb8eec413 (patch)
tree425965042d935027e8cc7045b383f6b7b6f714f9 /gcc/omp-low.c
parent09b4000c7c5b359ec62b5d621daf6ab95233ce10 (diff)
downloadgcc-6c7ae8c56f9341f180e097d5eb7ba05cb8eec413.zip
gcc-6c7ae8c56f9341f180e097d5eb7ba05cb8eec413.tar.gz
gcc-6c7ae8c56f9341f180e097d5eb7ba05cb8eec413.tar.bz2
tree-core.h (enum omp_clause_code): Add OMP_CLAUSE__CONDTEMP_.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE__CONDTEMP_. * tree.h (OMP_CLAUSE_DECL): Use OMP_CLAUSE__CONDTEMP_ instead of OMP_CLAUSE__REDUCTEMP_. * tree.c (omp_clause_num_ops, omp_clause_code_name): Add OMP_CLAUSE__CONDTEMP_. (walk_tree_1): Handle OMP_CLAUSE__CONDTEMP_. * tree-pretty-print.c (dump_omp_clause): Likewise. * tree-nested.c (convert_nonlocal_omp_clauses, convert_local_omp_clauses): Likewise. * gimplify.c (enum gimplify_omp_var_data): Use hexadecimal constants instead of decimal. Add GOVD_LASTPRIVATE_CONDITIONAL. (gimplify_scan_omp_clauses): Don't reject lastprivate conditional on OMP_FOR. (gimplify_omp_for): Warn and disable conditional modifier from lastprivate on loop iterators. * omp-general.h (struct omp_for_data): Add lastprivate_conditional member. * omp-general.c (omp_extract_for_data): Initialize it. * omp-low.c (struct omp_context): Add lastprivate_conditional_map member. (delete_omp_context): Delete it. (lower_lastprivate_conditional_clauses): New function. (lower_lastprivate_clauses): Add BODY_P and CSTMT_LIST arguments, handle lastprivate conditional clauses. (lower_reduction_clauses): Add CLIST argument, emit it into the critical section if any. (lower_omp_sections): Adjust lower_lastprivate_clauses and lower_reduction_clauses callers. (lower_omp_for_lastprivate): Add CLIST argument, pass it through to lower_lastprivate_clauses. (lower_omp_for): Call lower_lastprivate_conditional_clauses, adjust lower_omp_for_lastprivate and lower_reduction_clauses callers, emit clist into a critical section if not emitted there already by lower_reduction_clauses. (lower_omp_taskreg, lower_omp_teams): Adjust lower_reduction_clauses callers. (lower_omp_1): Handle GIMPLE_ASSIGNs storing into lastprivate conditional variables. * omp-expand.c (determine_parallel_type): Punt if OMP_CLAUSE__CONDTEMP_ clause is present. (expand_omp_for_generic, expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Handle lastprivate conditional. (expand_omp_for): Handle fd.lastprivate_conditional like fd.have_reductemp. gcc/testsuite/ * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect sorry for omp for. * c-c++-common/gomp/lastprivate-conditional-3.c: New test. libgomp/ * testsuite/libgomp.c-c++-common/lastprivate-conditional-1.c: New test. * testsuite/libgomp.c-c++-common/lastprivate-conditional-2.c: New test. From-SVN: r271610
Diffstat (limited to 'gcc/omp-low.c')
-rw-r--r--gcc/omp-low.c188
1 files changed, 167 insertions, 21 deletions
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 26ee70d..faab5d3 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -119,10 +119,14 @@ struct omp_context
and then offsets (if constant, otherwise NULL) for each entry. */
vec<tree> task_reductions;
- /* And a hash map from the reduction clauses to the registered array
+ /* A hash map from the reduction clauses to the registered array
elts. */
hash_map<tree, unsigned> *task_reduction_map;
+ /* And a hash map from the lastprivate(conditional:) variables to their
+ corresponding tracking loop iteration variables. */
+ hash_map<tree, tree> *lastprivate_conditional_map;
+
/* Nesting depth of this context. Used to beautify error messages re
invalid gotos. The outermost ctx is depth 1, with depth 0 being
reserved for the main body of the function. */
@@ -955,6 +959,8 @@ delete_omp_context (splay_tree_value value)
delete ctx->task_reduction_map;
}
+ delete ctx->lastprivate_conditional_map;
+
XDELETE (ctx);
}
@@ -5358,18 +5364,72 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
}
}
+/* Create temporary variables for lastprivate(conditional:) implementation
+ in context CTX with CLAUSES. */
+
+static void
+lower_lastprivate_conditional_clauses (tree *clauses, omp_context *ctx)
+{
+ struct omp_for_data fd;
+ tree iter_type = NULL_TREE;
+ tree cond_ptr = NULL_TREE;
+ tree iter_var = NULL_TREE;
+ for (tree c = *clauses; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ if (iter_type == NULL)
+ {
+ omp_extract_for_data (as_a <gomp_for *> (ctx->stmt), &fd, NULL);
+ iter_type = unsigned_type_for (fd.iter_type);
+ cond_ptr = create_tmp_var_raw (build_pointer_type (iter_type));
+ DECL_CONTEXT (cond_ptr) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (cond_ptr) = 1;
+ DECL_CHAIN (cond_ptr) = ctx->block_vars;
+ ctx->block_vars = cond_ptr;
+ iter_var = create_tmp_var_raw (iter_type);
+ DECL_CONTEXT (iter_var) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (iter_var) = 1;
+ DECL_CHAIN (iter_var) = ctx->block_vars;
+ ctx->block_vars = iter_var;
+ tree c2
+ = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ tree c3
+ = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__CONDTEMP_);
+ OMP_CLAUSE_DECL (c2) = cond_ptr;
+ OMP_CLAUSE_DECL (c3) = iter_var;
+ OMP_CLAUSE_CHAIN (c2) = c3;
+ OMP_CLAUSE_CHAIN (c3) = *clauses;
+ *clauses = c2;
+ ctx->lastprivate_conditional_map = new hash_map<tree, tree>;
+ }
+ tree v = create_tmp_var_raw (iter_type);
+ DECL_CONTEXT (v) = current_function_decl;
+ DECL_SEEN_IN_BIND_EXPR_P (v) = 1;
+ DECL_CHAIN (v) = ctx->block_vars;
+ ctx->block_vars = v;
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ ctx->lastprivate_conditional_map->put (o, v);
+ }
+}
+
/* Generate code to implement the LASTPRIVATE clauses. This is used for
both parallel and workshare constructs. PREDICATE may be NULL if it's
- always true. */
+ always true. BODY_P is the sequence to insert early initialization
+ if needed, STMT_LIST is where the non-conditional lastprivate handling
+ goes into and CSTMT_LIST is a sequence that needs to be run in a critical
+ section. */
static void
-lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
+lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *body_p,
+ gimple_seq *stmt_list, gimple_seq *cstmt_list,
omp_context *ctx)
{
tree x, c, label = NULL, orig_clauses = clauses;
bool par_clauses = false;
tree simduid = NULL, lastlane = NULL, simtcond = NULL, simtlast = NULL;
+ unsigned HOST_WIDE_INT conditional_off = 0;
/* Early exit if there are no lastprivate or linear clauses. */
for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
@@ -5448,10 +5508,43 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
}
+ tree cond_ptr = NULL_TREE;
for (c = clauses; c ;)
{
tree var, new_var;
location_t clause_loc = OMP_CLAUSE_LOCATION (c);
+ gimple_seq *this_stmt_list = stmt_list;
+ tree lab2 = NULL_TREE;
+
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c))
+ {
+ gcc_assert (body_p && ctx->lastprivate_conditional_map);
+ if (cond_ptr == NULL_TREE)
+ {
+ cond_ptr = omp_find_clause (orig_clauses, OMP_CLAUSE__CONDTEMP_);
+ cond_ptr = OMP_CLAUSE_DECL (cond_ptr);
+ }
+ tree type = TREE_TYPE (TREE_TYPE (cond_ptr));
+ tree o = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
+ tree v = *ctx->lastprivate_conditional_map->get (o);
+ gimplify_assign (v, build_zero_cst (type), body_p);
+ this_stmt_list = cstmt_list;
+ tree mem = build2 (MEM_REF, type, cond_ptr,
+ build_int_cst (TREE_TYPE (cond_ptr),
+ conditional_off));
+ tree mem2 = copy_node (mem);
+ conditional_off += tree_to_uhwi (TYPE_SIZE_UNIT (type));
+ gimple_seq seq = NULL;
+ mem = force_gimple_operand (mem, &seq, true, NULL_TREE);
+ gimple_seq_add_seq (this_stmt_list, seq);
+ tree lab1 = create_artificial_label (UNKNOWN_LOCATION);
+ lab2 = create_artificial_label (UNKNOWN_LOCATION);
+ gimple *g = gimple_build_cond (GT_EXPR, v, mem, lab1, lab2);
+ gimple_seq_add_stmt (this_stmt_list, g);
+ gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab1));
+ gimplify_assign (mem2, v, this_stmt_list);
+ }
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
|| (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
@@ -5493,7 +5586,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
2, simduid,
TREE_OPERAND (val, 1));
gimple_call_set_lhs (g, lastlane);
- gimple_seq_add_stmt (stmt_list, g);
+ gimple_seq_add_stmt (this_stmt_list, g);
}
new_var = build4 (ARRAY_REF, TREE_TYPE (val),
TREE_OPERAND (val, 0), lastlane,
@@ -5511,13 +5604,13 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
gcall *g = gimple_build_call_internal
(IFN_GOMP_SIMT_LAST_LANE, 1, simtcond);
gimple_call_set_lhs (g, simtlast);
- gimple_seq_add_stmt (stmt_list, g);
+ gimple_seq_add_stmt (this_stmt_list, g);
}
x = build_call_expr_internal_loc
(UNKNOWN_LOCATION, IFN_GOMP_SIMT_XCHG_IDX,
TREE_TYPE (val), 2, val, simtlast);
new_var = unshare_expr (new_var);
- gimplify_assign (new_var, x, stmt_list);
+ gimplify_assign (new_var, x, this_stmt_list);
new_var = unshare_expr (new_var);
}
@@ -5525,7 +5618,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
&& OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
{
lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
- gimple_seq_add_seq (stmt_list,
+ gimple_seq_add_seq (this_stmt_list,
OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
}
@@ -5533,7 +5626,7 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
&& OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
{
lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
- gimple_seq_add_seq (stmt_list,
+ gimple_seq_add_seq (this_stmt_list,
OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
}
@@ -5553,8 +5646,12 @@ lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
if (omp_is_reference (var))
new_var = build_simple_mem_ref_loc (clause_loc, new_var);
x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
- gimplify_and_add (x, stmt_list);
+ gimplify_and_add (x, this_stmt_list);
+
+ if (lab2)
+ gimple_seq_add_stmt (this_stmt_list, gimple_build_label (lab2));
}
+
c = OMP_CLAUSE_CHAIN (c);
if (c == NULL && !par_clauses)
{
@@ -5802,10 +5899,15 @@ lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
gimple_seq_add_seq (join_seq, after_join);
}
-/* Generate code to implement the REDUCTION clauses. */
+/* Generate code to implement the REDUCTION clauses, append it
+ to STMT_SEQP. CLIST if non-NULL is a pointer to a sequence
+ that should be emitted also inside of the critical section,
+ in that case clear *CLIST afterwards, otherwise leave it as is
+ and let the caller emit it itself. */
static void
-lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
+lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp,
+ gimple_seq *clist, omp_context *ctx)
{
gimple_seq sub_seq = NULL;
gimple *stmt;
@@ -6047,6 +6149,12 @@ lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
gimple_seq_add_seq (stmt_seqp, sub_seq);
+ if (clist)
+ {
+ gimple_seq_add_seq (stmt_seqp, *clist);
+ *clist = NULL;
+ }
+
stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
0);
gimple_seq_add_stmt (stmt_seqp, stmt);
@@ -6684,7 +6792,7 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
{
gimple_seq l = NULL;
lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
- &l, ctx);
+ NULL, &l, NULL, ctx);
gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
gimple_omp_section_set_last (sec_start);
}
@@ -6697,7 +6805,8 @@ lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bind = gimple_build_bind (NULL, new_body, block);
olist = NULL;
- lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
+ lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist,
+ NULL, ctx);
block = make_node (BLOCK);
new_stmt = gimple_build_bind (NULL, NULL, block);
@@ -8074,11 +8183,13 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
for a lastprivate clause. Given a loop control predicate of (V
cond N2), we gate the clause on (!(V cond N2)). The lowered form
is appended to *DLIST, iterator initialization is appended to
- *BODY_P. */
+ *BODY_P. *CLIST is for lastprivate(conditional:) code that needs
+ to be emitted in a critical section. */
static void
lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
- gimple_seq *dlist, struct omp_context *ctx)
+ gimple_seq *dlist, gimple_seq *clist,
+ struct omp_context *ctx)
{
tree clauses, cond, vinit;
enum tree_code cond_code;
@@ -8158,7 +8269,7 @@ lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
clauses = gimple_omp_for_clauses (fd->for_stmt);
stmts = NULL;
- lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
+ lower_lastprivate_clauses (clauses, cond, body_p, &stmts, clist, ctx);
if (!gimple_seq_empty_p (stmts))
{
gimple_seq_add_seq (&stmts, *dlist);
@@ -8190,7 +8301,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
gbind *new_stmt;
gimple_seq omp_for_body, body, dlist, tred_ilist = NULL, tred_dlist = NULL;
- gimple_seq cnt_list = NULL;
+ gimple_seq cnt_list = NULL, clist = NULL;
gimple_seq oacc_head = NULL, oacc_tail = NULL;
size_t i;
@@ -8308,6 +8419,9 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gimple_seq_add_seq (rclauses ? &tred_ilist : &body,
gimple_omp_for_pre_body (stmt));
+ lower_lastprivate_conditional_clauses (gimple_omp_for_clauses_ptr (stmt),
+ ctx);
+
lower_omp (gimple_omp_body_ptr (stmt), ctx);
/* Lower the header expressions. At this point, we can assume that
@@ -8353,7 +8467,7 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
if (oacc_head)
gimple_seq_add_seq (&body, oacc_head);
- lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
+ lower_omp_for_lastprivate (&fd, &body, &dlist, &clist, ctx);
if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
@@ -8378,7 +8492,18 @@ lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
fd.loop.v));
/* After the loop, add exit clauses. */
- lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
+ lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, &clist, ctx);
+
+ if (clist)
+ {
+ tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
+ gcall *g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&body, g);
+ gimple_seq_add_seq (&body, clist);
+ fndecl = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
+ g = gimple_build_call (fndecl, 0);
+ gimple_seq_add_stmt (&body, g);
+ }
if (ctx->cancellable)
gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
@@ -9000,7 +9125,7 @@ lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
lower_omp (&par_body, ctx);
if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
- lower_reduction_clauses (clauses, &par_rlist, ctx);
+ lower_reduction_clauses (clauses, &par_rlist, NULL, ctx);
/* Declare all the variables created by mapping and the variables
declared in the scope of the parallel body. */
@@ -10189,7 +10314,8 @@ lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
&bind_body, &dlist, ctx, NULL);
lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
- lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
+ lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist,
+ NULL, ctx);
if (!gimple_omp_teams_grid_phony (teams_stmt))
{
gimple_seq_add_stmt (&bind_body, teams_stmt);
@@ -10498,8 +10624,28 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
default:
break;
}
+ goto regimplify;
+
+ case GIMPLE_ASSIGN:
+ if (ctx && ctx->lastprivate_conditional_map)
+ {
+ tree lhs = get_base_address (gimple_assign_lhs (stmt));
+ if (DECL_P (lhs))
+ if (tree *v = ctx->lastprivate_conditional_map->get (lhs))
+ {
+ tree clauses
+ = gimple_omp_for_clauses (as_a <gomp_for *> (ctx->stmt));
+ tree c = omp_find_clause (clauses, OMP_CLAUSE__CONDTEMP_);
+ c = omp_find_clause (OMP_CLAUSE_CHAIN (c),
+ OMP_CLAUSE__CONDTEMP_);
+ gimple *g = gimple_build_assign (*v, OMP_CLAUSE_DECL (c));
+ gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
+ }
+ }
/* FALLTHRU */
+
default:
+ regimplify:
if ((ctx || task_shared_vars)
&& walk_gimple_op (stmt, lower_omp_regimplify_p,
ctx ? NULL : &wi))