diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-05-24 23:31:59 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-05-24 23:31:59 +0200 |
commit | 6c7ae8c56f9341f180e097d5eb7ba05cb8eec413 (patch) | |
tree | 425965042d935027e8cc7045b383f6b7b6f714f9 /gcc/omp-low.c | |
parent | 09b4000c7c5b359ec62b5d621daf6ab95233ce10 (diff) | |
download | gcc-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.c | 188 |
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)) |