* tree.def (OMP_SCAN): New tree code.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and
OMP_CLAUSE_EXCLUSIVE.
* tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP.
(OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define.
* tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for
OMP_CLAUSE_{IN,EX}CLUSIVE.
(walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
* tree-nested.c (convert_nonlocal_reference_stmt,
convert_local_reference_stmt, convert_gimple_call): Handle
GIMPLE_OMP_SCAN.
* tree-pretty-print.c (dump_omp_clause): Handle
OMP_CLAUSE_{IN,EX}CLUSIVE.
(dump_generic_node): Handle OMP_SCAN.
* gimple.def (GIMPLE_OMP_SCAN): New gimple code.
* gimple.h (gomp_scan): New type.
(is_a_helper <gomp_scan *>::test,
is_a_helper <const gomp_scan *>::test): New templates.
(gimple_build_omp_scan): Declare.
(gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr,
gimple_omp_scan_set_clauses): New inline functions.
(CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:.
* gimple.c (gimple_build_omp_scan): New function.
(gimple_copy): Handle GIMPLE_OMP_SCAN.
* gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise.
* gimple-pretty-print.c (dump_gimple_omp_block): Don't handle
GIMPLE_OMP_TASKGROUP.
(dump_gimple_omp_scan): New function.
(pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN.
* gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN.
* tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise.
* gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN.
(is_gimple_stmt): Handle OMP_SCAN.
(gimplify_scan_omp_clauses): Reject inscan reductions on constructs
other than OMP_FOR or OMP_SIMD. Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
(gimplify_adjust_omp_clauses): Diagnose inscan reductions not
mentioned in nested #pragma omp scan. Handle
OMP_CLAUSE_{IN,EX}CLUSIVE.
(gimplify_expr): Handle OMP_SCAN.
* omp-low.c (check_omp_nesting_restrictions): For parent context,
look through GIMPLE_OMP_SCAN context. Allow #pragma omp scan in
simd constructs.
(scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle
GIMPLE_OMP_SCAN.
c-family/
* c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN.
* c-pragma.c (omp_pragmas_simd): Add #pragma omp scan.
* c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on
combined/composite constructs where it is not allowed. Copy over
OMP_CLAUSE_REDUCTION_INSCAN.
c/
* c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN.
(c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions.
(c_parser_omp_scan_loop_body): New function.
(c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are
inscan reduction clauses.
* c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with
non-inscan reductions on the same construct, or inscan reductions with
ordered or schedule clauses, or inscan array reductions.
cp/
* parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan
reductions.
(cp_parser_omp_scan_loop_body): New function.
(cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there
are inscan reduction clauses.
(cp_parser_pragma): Reject PRAGMA_OMP_SCAN.
* semantics.c (finish_omp_clauses): Reject mixing inscan with
non-inscan reductions on the same construct, or inscan reductions with
ordered or schedule clauses, or inscan array reductions.
* pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
(tsubst_expr): Handle OMP_SCAN.
testsuite/
* c-c++-common/gomp/scan-1.c: New test.
* c-c++-common/gomp/scan-2.c: New test.
* c-c++-common/gomp/scan-3.c: New test.
* c-c++-common/gomp/scan-4.c: New test.
From-SVN: r272117
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.def (OMP_SCAN): New tree code.
+ * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and
+ OMP_CLAUSE_EXCLUSIVE.
+ * tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP.
+ (OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define.
+ * tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for
+ OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+ * tree-nested.c (convert_nonlocal_reference_stmt,
+ convert_local_reference_stmt, convert_gimple_call): Handle
+ GIMPLE_OMP_SCAN.
+ * tree-pretty-print.c (dump_omp_clause): Handle
+ OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (dump_generic_node): Handle OMP_SCAN.
+ * gimple.def (GIMPLE_OMP_SCAN): New gimple code.
+ * gimple.h (gomp_scan): New type.
+ (is_a_helper <gomp_scan *>::test,
+ is_a_helper <const gomp_scan *>::test): New templates.
+ (gimple_build_omp_scan): Declare.
+ (gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr,
+ gimple_omp_scan_set_clauses): New inline functions.
+ (CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:.
+ * gimple.c (gimple_build_omp_scan): New function.
+ (gimple_copy): Handle GIMPLE_OMP_SCAN.
+ * gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise.
+ * gimple-pretty-print.c (dump_gimple_omp_block): Don't handle
+ GIMPLE_OMP_TASKGROUP.
+ (dump_gimple_omp_scan): New function.
+ (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN.
+ * gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN.
+ * tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise.
+ * gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN.
+ (is_gimple_stmt): Handle OMP_SCAN.
+ (gimplify_scan_omp_clauses): Reject inscan reductions on constructs
+ other than OMP_FOR or OMP_SIMD. Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (gimplify_adjust_omp_clauses): Diagnose inscan reductions not
+ mentioned in nested #pragma omp scan. Handle
+ OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (gimplify_expr): Handle OMP_SCAN.
+ * omp-low.c (check_omp_nesting_restrictions): For parent context,
+ look through GIMPLE_OMP_SCAN context. Allow #pragma omp scan in
+ simd constructs.
+ (scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle
+ GIMPLE_OMP_SCAN.
+
2019-06-10 Martin Liska <mliska@suse.cz>
* ipa-cp.c (ignore_edge_p): New function.
(build_toporder_info): Use it.
- * ipa-inline.c (ignore_edge_p): New function/
+ * ipa-inline.c (ignore_edge_p): New function.
(inline_small_functions): Use it.
* ipa-pure-const.c (ignore_edge_for_nothrow):
Verify opt_for_fn for caller and callee.
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN.
+ * c-pragma.c (omp_pragmas_simd): Add #pragma omp scan.
+ * c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on
+ combined/composite constructs where it is not allowed. Copy over
+ OMP_CLAUSE_REDUCTION_INSCAN.
+
2019-06-05 Martin Sebor <msebor@redhat.com>
* c-attribs.c (handle_mode_attribute): Adjust quoting and hyphenation.
OMP_CLAUSE_REDUCTION_TASK (clauses) = 0;
}
}
+ if (OMP_CLAUSE_REDUCTION_INSCAN (clauses)
+ && ((mask & ((OMP_CLAUSE_MASK_1
+ << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)))
+ != 0))
+ {
+ error_at (OMP_CLAUSE_LOCATION (clauses),
+ "%<inscan%> %<reduction%> clause on construct other "
+ "than %<for%>, %<simd%>, %<for simd%>, "
+ "%<parallel for%>, %<parallel for simd%>");
+ OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0;
+ }
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0)
{
if (code == OMP_SIMD)
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
= OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+ OMP_CLAUSE_REDUCTION_INSCAN (c)
+ = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c;
}
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
= OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+ OMP_CLAUSE_REDUCTION_INSCAN (c)
+ = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c;
s = C_OMP_CLAUSE_SPLIT_PARALLEL;
= OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses);
OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c)
= OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses);
+ OMP_CLAUSE_REDUCTION_INSCAN (c)
+ = OMP_CLAUSE_REDUCTION_INSCAN (clauses);
OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c;
}
{ "for", PRAGMA_OMP_FOR },
{ "ordered", PRAGMA_OMP_ORDERED },
{ "parallel", PRAGMA_OMP_PARALLEL },
+ { "scan", PRAGMA_OMP_SCAN },
{ "simd", PRAGMA_OMP_SIMD },
{ "target", PRAGMA_OMP_TARGET },
{ "taskloop", PRAGMA_OMP_TASKLOOP },
PRAGMA_OMP_ORDERED,
PRAGMA_OMP_PARALLEL,
PRAGMA_OMP_REQUIRES,
+ PRAGMA_OMP_SCAN,
PRAGMA_OMP_SECTION,
PRAGMA_OMP_SECTIONS,
PRAGMA_OMP_SIMD,
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN.
+ (c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions.
+ (c_parser_omp_scan_loop_body): New function.
+ (c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are
+ inscan reduction clauses.
+ * c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with
+ non-inscan reductions on the same construct, or inscan reductions with
+ ordered or schedule clauses, or inscan array reductions.
+
2019-06-05 Martin Sebor <msebor@redhat.com>
PR c/90737
c_parser_omp_end_declare_target (parser);
return false;
+ case PRAGMA_OMP_SCAN:
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma omp scan%> may only be used in "
+ "a loop construct with %<inscan%> %<reduction%> clause");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+
case PRAGMA_OMP_SECTION:
error_at (c_parser_peek_token (parser)->location,
"%<#pragma omp section%> may only be used in "
if (strcmp (p, "task") == 0)
task = true;
else if (strcmp (p, "inscan") == 0)
- {
- inscan = true;
- sorry ("%<inscan%> modifier on %<reduction%> clause "
- "not supported yet");
- }
+ inscan = true;
if (task || inscan)
{
c_parser_consume_token (parser);
c_finish_omp_flush (loc, mo);
}
+/* OpenMP 5.0:
+
+ scan-loop-body:
+ { structured-block scan-directive structured-block } */
+
+static void
+c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
+{
+ tree substmt;
+ location_t loc;
+ tree clauses = NULL_TREE;
+
+ loc = c_parser_peek_token (parser)->location;
+ if (!open_brace_parsed
+ && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ /* Avoid skipping until the end of the block. */
+ parser->error = false;
+ return;
+ }
+
+ substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
+ {
+ enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+ c_parser_consume_pragma (parser);
+
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ const char *p
+ = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "inclusive") == 0)
+ clause = OMP_CLAUSE_INCLUSIVE;
+ else if (strcmp (p, "exclusive") == 0)
+ clause = OMP_CLAUSE_EXCLUSIVE;
+ }
+ if (clause != OMP_CLAUSE_ERROR)
+ {
+ c_parser_consume_token (parser);
+ clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
+ }
+ else
+ c_parser_error (parser, "expected %<inclusive%> or "
+ "%<exclusive%> clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
+ else
+ error ("expected %<#pragma omp scan%>");
+
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
+ substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+ "expected %<}%>");
+}
+
/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
The real trick here is to determine the loop control variable early
so that we can push a new decl if necessary to make it private.
int i, collapse = 1, ordered = 0, count, nbraces = 0;
location_t for_loc;
bool tiling = false;
+ bool inscan = false;
vec<tree, va_gc> *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
ordered_cl = cl;
ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
}
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+ && (code == OMP_SIMD || code == OMP_FOR))
+ inscan = true;
if (ordered && ordered < collapse)
{
c_cont_label = NULL_TREE;
body = push_stmt_list ();
- if (open_brace_parsed)
+ if (inscan)
+ c_parser_omp_scan_loop_body (parser, open_brace_parsed);
+ else if (open_brace_parsed)
{
location_t here = c_parser_peek_token (parser)->location;
stmt = c_begin_compound_stmt (true);
bool copyprivate_seen = false;
bool linear_variable_step_check = false;
tree *nowait_clause = NULL;
- bool ordered_seen = false;
+ tree ordered_clause = NULL_TREE;
tree schedule_clause = NULL_TREE;
bool oacc_async = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
tree *nogroup_seen = NULL;
- bool reduction_seen = false;
+ /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+ has been seen, -2 if mixed inscan/normal reduction diagnosed. */
+ int reduction_seen = 0;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- reduction_seen = true;
+ if (reduction_seen == 0)
+ reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+ else if (reduction_seen != -2
+ && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+ ? -1 : 1))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+ "on the same construct");
+ reduction_seen = -2;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
}
t = OMP_CLAUSE_DECL (c);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause with array "
+ "section");
+ remove = true;
+ break;
+ }
}
t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
if (t == error_mark_node)
continue;
case OMP_CLAUSE_ORDERED:
- ordered_seen = true;
+ ordered_clause = c;
pc = &OMP_CLAUSE_CHAIN (c);
continue;
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ need_complete = true;
+ need_implicitly_determined = true;
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
= OMP_CLAUSE_SAFELEN_EXPR (safelen);
}
- if (ordered_seen
+ if (ordered_clause
&& schedule_clause
&& (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
& OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
& ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
}
- if (linear_variable_step_check)
+ if (reduction_seen < 0 && ordered_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (ordered_clause),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "ordered");
+ reduction_seen = -2;
+ }
+
+ if (reduction_seen < 0 && schedule_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (schedule_clause),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "schedule");
+ reduction_seen = -2;
+ }
+
+ if (linear_variable_step_check || reduction_seen == -2)
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
OMP_CLAUSE_LINEAR_STEP (c));
remove = true;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan
+ reductions.
+ (cp_parser_omp_scan_loop_body): New function.
+ (cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there
+ are inscan reduction clauses.
+ (cp_parser_pragma): Reject PRAGMA_OMP_SCAN.
+ * semantics.c (finish_omp_clauses): Reject mixing inscan with
+ non-inscan reductions on the same construct, or inscan reductions with
+ ordered or schedule clauses, or inscan array reductions.
+ * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE.
+ (tsubst_expr): Handle OMP_SCAN.
+
2019-06-07 Jason Merrill <jason@redhat.com>
* constexpr.c (cxx_eval_constant_expression): Call
if (strcmp (p, "task") == 0)
task = true;
else if (strcmp (p, "inscan") == 0)
- {
- inscan = true;
- sorry ("%<inscan%> modifier on %<reduction%> clause "
- "not supported yet");
- }
+ inscan = true;
if (task || inscan)
{
cp_lexer_consume_token (parser->lexer);
cp_finish_decomp (decl, decomp_first_name, decomp_cnt);
}
+/* OpenMP 5.0:
+
+ scan-loop-body:
+ { structured-block scan-directive structured-block } */
+
+static void
+cp_parser_omp_scan_loop_body (cp_parser *parser)
+{
+ tree substmt, clauses = NULL_TREE;
+
+ matching_braces braces;
+ if (!braces.require_open (parser))
+ return;
+
+ substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+ add_stmt (substmt);
+
+ cp_token *tok = cp_lexer_peek_token (parser->lexer);
+ if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN)
+ {
+ enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ const char *p = IDENTIFIER_POINTER (id);
+ if (strcmp (p, "inclusive") == 0)
+ clause = OMP_CLAUSE_INCLUSIVE;
+ else if (strcmp (p, "exclusive") == 0)
+ clause = OMP_CLAUSE_EXCLUSIVE;
+ }
+ if (clause != OMP_CLAUSE_ERROR)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ clauses = cp_parser_omp_var_list (parser, clause, NULL_TREE);
+ }
+ else
+ cp_parser_error (parser, "expected %<inclusive%> or "
+ "%<exclusive%> clause");
+
+ cp_parser_require_pragma_eol (parser, tok);
+ }
+ else
+ error ("expected %<#pragma omp scan%>");
+
+ clauses = finish_omp_clauses (clauses, C_ORT_OMP);
+ substmt = cp_parser_omp_structured_block (parser, NULL);
+ substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt,
+ clauses);
+ add_stmt (substmt);
+
+ braces.require_close (parser);
+}
+
/* Parse the restricted form of the for statement allowed by OpenMP. */
static tree
releasing_vec for_block;
auto_vec<tree, 4> orig_inits;
bool tiling = false;
+ bool inscan = false;
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
ordered_cl = cl;
ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
}
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+ && (code == OMP_SIMD || code == OMP_FOR))
+ inscan = true;
if (ordered && ordered < collapse)
{
}
else
body = push_stmt_list ();
- cp_parser_statement (parser, NULL_TREE, false, if_p);
+ if (inscan)
+ cp_parser_omp_scan_loop_body (parser);
+ else
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
if (orig_declv)
body = finish_omp_structured_block (body);
else
cp_parser_omp_end_declare_target (parser, pragma_tok);
return false;
+ case PRAGMA_OMP_SCAN:
+ error_at (pragma_tok->location,
+ "%<#pragma omp scan%> may only be used in "
+ "a loop construct with %<inscan%> %<reduction%> clause");
+ break;
+
case PRAGMA_OMP_SECTION:
error_at (pragma_tok->location,
"%<#pragma omp section%> may only be used in "
case OMP_CLAUSE_NONTEMPORAL:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
OMP_CLAUSE_DECL (nc)
= tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain,
in_decl, iterator_cache);
case OMP_CLAUSE_TASK_REDUCTION:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
/* tsubst_expr on SCOPE_REF results in returning
finish_non_static_data_member result. Undo that here. */
if (TREE_CODE (OMP_CLAUSE_DECL (oc)) == SCOPE_REF
case OMP_TEAMS:
case OMP_CRITICAL:
case OMP_TASKGROUP:
+ case OMP_SCAN:
r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS
&& OMP_TEAMS_COMBINED (t));
tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_OMP, args, complain,
bool branch_seen = false;
bool copyprivate_seen = false;
bool ordered_seen = false;
+ bool schedule_seen = false;
bool oacc_async = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
- bool reduction_seen = false;
+ /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+ has been seen, -2 if mixed inscan/normal reduction diagnosed. */
+ int reduction_seen = 0;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- reduction_seen = true;
+ if (reduction_seen == 0)
+ reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+ else if (reduction_seen != -2
+ && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+ ? -1 : 1))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+ "on the same construct");
+ reduction_seen = -2;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
remove = true;
break;
}
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause with array "
+ "section");
+ remove = true;
+ break;
+ }
if (TREE_CODE (t) == TREE_LIST)
{
while (TREE_CODE (t) == TREE_LIST)
}
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
}
+ if (!remove)
+ schedule_seen = true;
break;
case OMP_CLAUSE_SIMDLEN:
branch_seen = true;
break;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (!t)
+ t = OMP_CLAUSE_DECL (c);
+ if (t == current_class_ptr)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<this%> allowed in OpenMP only in %<declare simd%>"
+ " clauses");
+ remove = true;
+ break;
+ }
+ if (!VAR_P (t)
+ && TREE_CODE (t) != PARM_DECL
+ && TREE_CODE (t) != FIELD_DECL)
+ {
+ if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
+ break;
+ if (DECL_P (t))
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ else
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (reduction_seen < 0 && (ordered_seen || schedule_seen))
+ reduction_seen = -2;
+
for (pc = &clauses, c = clauses; c ; c = *pc)
{
enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
need_implicitly_determined = true;
break;
case OMP_CLAUSE_REDUCTION:
+ if (reduction_seen == -2)
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ need_implicitly_determined = true;
+ break;
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LINEAR:
(OMP_CLAUSE_SCHEDULE_KIND (c)
& ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
}
+ if (reduction_seen == -2)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "schedule");
pc = &OMP_CLAUSE_CHAIN (c);
continue;
case OMP_CLAUSE_NOGROUP:
}
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_ORDERED:
+ if (reduction_seen == -2)
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "ordered");
+ pc = &OMP_CLAUSE_CHAIN (c);
+ continue;
case OMP_CLAUSE_NOWAIT:
if (copyprivate_seen)
{
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_RETURN:
case GIMPLE_OMP_ATOMIC_LOAD:
case GIMPLE_OMP_MASTER:
pp_string (buffer, "#pragma omp master");
break;
- case GIMPLE_OMP_TASKGROUP:
- pp_string (buffer, "#pragma omp taskgroup");
- break;
case GIMPLE_OMP_SECTION:
pp_string (buffer, "#pragma omp section");
break;
}
}
+/* Dump a GIMPLE_OMP_SCAN tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_omp_scan (pretty_printer *buffer, gomp_scan *gs,
+ int spc, dump_flags_t flags)
+{
+ if (flags & TDF_RAW)
+ dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs,
+ gimple_omp_body (gs));
+ else
+ {
+ if (gimple_omp_scan_clauses (gs))
+ {
+ pp_string (buffer, "#pragma omp scan");
+ dump_omp_clauses (buffer, gimple_omp_scan_clauses (gs), spc, flags);
+ }
+ if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_left_brace (buffer);
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_right_brace (buffer);
+ }
+ }
+}
+
/* Dump a GIMPLE_OMP_RETURN tuple on the pretty_printer BUFFER. */
static void
flags);
break;
+ case GIMPLE_OMP_SCAN:
+ dump_gimple_omp_scan (buffer, as_a <gomp_scan *> (gs), spc,
+ flags);
+ break;
+
case GIMPLE_OMP_CRITICAL:
dump_gimple_omp_critical (buffer, as_a <gomp_critical *> (gs), spc,
flags);
}
break;
+ case GIMPLE_OMP_SCAN:
+ {
+ gomp_scan *scan_stmt = as_a <gomp_scan *> (stmt);
+ ret = walk_tree (gimple_omp_scan_clauses_ptr (scan_stmt),
+ callback_op, wi, pset);
+ if (ret)
+ return ret;
+ }
+ break;
+
case GIMPLE_OMP_FOR:
ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi,
pset);
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TASK:
}
+/* Build a GIMPLE_OMP_SCAN statement.
+
+ BODY is the sequence of statements to be executed by the scan
+ construct.
+ CLAUSES are any of the construct's clauses. */
+
+gomp_scan *
+gimple_build_omp_scan (gimple_seq body, tree clauses)
+{
+ gomp_scan *p
+ = as_a <gomp_scan *> (gimple_alloc (GIMPLE_OMP_SCAN, 0));
+ gimple_omp_scan_set_clauses (p, clauses);
+ if (body)
+ gimple_omp_set_body (p, body);
+
+ return p;
+}
+
+
/* Build a GIMPLE_OMP_SECTIONS statement.
BODY is a sequence of section statements.
gimple_omp_ordered_set_clauses (as_a <gomp_ordered *> (copy), t);
goto copy_omp_body;
+ case GIMPLE_OMP_SCAN:
+ t = gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt));
+ t = unshare_expr (t);
+ gimple_omp_scan_set_clauses (as_a <gomp_scan *> (copy), t);
+ goto copy_omp_body;
+
case GIMPLE_OMP_TASKGROUP:
t = unshare_expr (gimple_omp_taskgroup_clauses (stmt));
gimple_omp_taskgroup_set_clauses (copy, t);
/* OMP_RETURN marks the end of an OpenMP directive. */
DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT)
+/* GIMPLE_OMP_SCAN <BODY, CLAUSES> represents #pragma omp scan
+ BODY is the sequence of statements inside the single section.
+ CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
+DEFGSCODE(GIMPLE_OMP_SCAN, "gimple_omp_scan", GSS_OMP_SINGLE_LAYOUT)
+
/* OMP_SECTION <BODY> represents #pragma omp section.
BODY is the sequence of statements in the section body. */
DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section", GSS_OMP)
tree control_use;
};
-/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP. */
+/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP,
+ GIMPLE_OMP_SCAN. */
struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
gimple_statement_omp_single_layout : public gimple_statement_omp
stmt->code == GIMPLE_OMP_ORDERED. */
};
+struct GTY((tag("GSS_OMP_SINGLE_LAYOUT")))
+ gomp_scan : public gimple_statement_omp_single_layout
+{
+ /* No extra fields; adds invariant:
+ stmt->code == GIMPLE_OMP_SCAN. */
+};
+
/* GIMPLE_OMP_ATOMIC_LOAD.
Note: This is based on gimple, not g_s_omp, because g_s_omp
return gs->code == GIMPLE_OMP_ORDERED;
}
+template <>
+template <>
+inline bool
+is_a_helper <gomp_scan *>::test (gimple *gs)
+{
+ return gs->code == GIMPLE_OMP_SCAN;
+}
+
template <>
template <>
inline bool
return gs->code == GIMPLE_OMP_ORDERED;
}
+template <>
+template <>
+inline bool
+is_a_helper <const gomp_scan *>::test (const gimple *gs)
+{
+ return gs->code == GIMPLE_OMP_SCAN;
+}
+
template <>
template <>
inline bool
gomp_continue *gimple_build_omp_continue (tree, tree);
gomp_ordered *gimple_build_omp_ordered (gimple_seq, tree);
gimple *gimple_build_omp_return (bool);
+gomp_scan *gimple_build_omp_scan (gimple_seq, tree);
gomp_sections *gimple_build_omp_sections (gimple_seq, tree);
gimple *gimple_build_omp_sections_switch (void);
gomp_single *gimple_build_omp_single (gimple_seq, tree);
}
+/* Return the clauses associated with OMP_SCAN statement SCAN_STMT. */
+
+static inline tree
+gimple_omp_scan_clauses (const gomp_scan *scan_stmt)
+{
+ return scan_stmt->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP scan statement
+ ORD_STMT. */
+
+static inline tree *
+gimple_omp_scan_clauses_ptr (gomp_scan *scan_stmt)
+{
+ return &scan_stmt->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP scan statement
+ ORD_STMT. */
+
+static inline void
+gimple_omp_scan_set_clauses (gomp_scan *scan_stmt, tree clauses)
+{
+ scan_stmt->clauses = clauses;
+}
+
+
/* Return the clauses associated with OMP_TASKGROUP statement GS. */
static inline tree
case GIMPLE_OMP_TASKGROUP: \
case GIMPLE_OMP_ORDERED: \
case GIMPLE_OMP_CRITICAL: \
+ case GIMPLE_OMP_SCAN: \
case GIMPLE_OMP_RETURN: \
case GIMPLE_OMP_ATOMIC_LOAD: \
case GIMPLE_OMP_ATOMIC_STORE: \
GOVD_CONDTEMP = 0x1000000,
+ /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */
+ GOVD_REDUCTION_INSCAN = 0x2000000,
+
GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE
| GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR
| GOVD_LOCAL)
case OMP_SIMD:
case OMP_DISTRIBUTE:
case OACC_LOOP:
+ case OMP_SCAN:
case OMP_SECTIONS:
case OMP_SECTION:
case OMP_SINGLE:
case OMP_DISTRIBUTE:
error_at (OMP_CLAUSE_LOCATION (c),
"conditional %<lastprivate%> clause on "
- "%<distribute%> construct");
+ "%qs construct", "distribute");
OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
break;
case OMP_TASKLOOP:
error_at (OMP_CLAUSE_LOCATION (c),
"conditional %<lastprivate%> clause on "
- "%<taskloop%> construct");
+ "%qs construct", "taskloop");
OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0;
break;
default:
OMP_CLAUSE_REDUCTION_TASK (c) = 0;
}
}
+ if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+ switch (code)
+ {
+ case OMP_SECTIONS:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "sections");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ case OMP_PARALLEL:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "parallel");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ case OMP_TEAMS:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "teams");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ case OMP_TASKLOOP:
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause on "
+ "%qs construct", "taskloop");
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
+ break;
+ default:
+ break;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
break;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ decl = OMP_CLAUSE_DECL (c);
+ {
+ splay_tree_node n = splay_tree_lookup (outer_ctx->variables,
+ (splay_tree_key) decl);
+ if (n == NULL || (n->value & GOVD_REDUCTION) == 0)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %qs clause but not in %<inscan%> "
+ "%<reduction%> clause on the containing construct",
+ decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ else
+ {
+ n->value |= GOVD_REDUCTION_INSCAN;
+ if (outer_ctx->region_type == ORT_SIMD
+ && outer_ctx->outer_context
+ && outer_ctx->outer_context->region_type == ORT_WORKSHARE)
+ {
+ n = splay_tree_lookup (outer_ctx->outer_context->variables,
+ (splay_tree_key) decl);
+ if (n && (n->value & GOVD_REDUCTION) != 0)
+ n->value |= GOVD_REDUCTION_INSCAN;
+ }
+ }
+ }
+ break;
+
default:
gcc_unreachable ();
}
enum tree_code code)
{
struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp;
+ tree *orig_list_p = list_p;
tree c, decl;
+ bool has_inscan_reductions = false;
if (body)
{
break;
case OMP_CLAUSE_REDUCTION:
+ if (OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ decl = OMP_CLAUSE_DECL (c);
+ n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl);
+ if ((n->value & GOVD_REDUCTION_INSCAN) == 0)
+ {
+ remove = true;
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %<inscan%> %<reduction%> clause "
+ "but not in %<scan%> directive clause", decl);
+ break;
+ }
+ has_inscan_reductions = true;
+ }
+ /* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
decl = OMP_CLAUSE_DECL (c);
case OMP_CLAUSE_TILE:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
break;
default:
data.pre_p = pre_p;
splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data);
+ if (has_inscan_reductions)
+ for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c))
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
+ && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause used together with "
+ "%<linear%> clause for a variable other than loop "
+ "iterator");
+ break;
+ }
+
gimplify_omp_ctxp = ctx->outer_context;
delete_omp_context (ctx);
}
case OMP_MASTER:
case OMP_ORDERED:
case OMP_CRITICAL:
+ case OMP_SCAN:
{
gimple_seq body = NULL;
gimple *g;
OMP_CRITICAL_NAME (*expr_p),
OMP_CRITICAL_CLAUSES (*expr_p));
break;
+ case OMP_SCAN:
+ gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p),
+ pre_p, ORT_WORKSHARE, OMP_SCAN);
+ gimplify_adjust_omp_clauses (pre_p, body,
+ &OMP_SCAN_CLAUSES (*expr_p),
+ OMP_SCAN);
+ g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p));
+ break;
default:
gcc_unreachable ();
}
&& code != OMP_TASKGROUP
&& code != OMP_ORDERED
&& code != OMP_PARALLEL
+ && code != OMP_SCAN
&& code != OMP_SECTIONS
&& code != OMP_SECTION
&& code != OMP_SINGLE);
if (ctx != NULL)
{
+ if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN
+ && ctx->outer
+ && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
+ ctx = ctx->outer;
if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
{
}
}
else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
- || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE)
+ || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE
+ || gimple_code (stmt) == GIMPLE_OMP_SCAN)
return true;
error_at (gimple_location (stmt),
"OpenMP constructs other than %<#pragma omp ordered simd%>"
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_CRITICAL:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_GRID_BODY:
ctx = new_omp_context (stmt, ctx);
scan_omp (gimple_omp_body_ptr (stmt), ctx);
gcc_assert (ctx);
lower_omp_ordered (gsi_p, ctx);
break;
+ case GIMPLE_OMP_SCAN:
+ ctx = maybe_lookup_ctx (stmt);
+ gcc_assert (ctx);
+ gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT);
+ if (gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)))
+ sorry_at (gimple_location (stmt),
+ "%<#pragma omp scan%> not supported yet");
+ gsi_replace (gsi_p, gimple_build_nop (), true);
+ break;
case GIMPLE_OMP_CRITICAL:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
|| gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL
|| gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP
|| gimple_code (up->stmt) == GIMPLE_OMP_SECTION
+ || gimple_code (up->stmt) == GIMPLE_OMP_SCAN
|| (gimple_code (up->stmt) == GIMPLE_OMP_TARGET
&& (gimple_omp_target_kind (up->stmt)
== GF_OMP_TARGET_KIND_DATA)))
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_TARGET:
case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_TARGET:
case GIMPLE_OMP_TEAMS:
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-c++-common/gomp/scan-1.c: New test.
+ * c-c++-common/gomp/scan-2.c: New test.
+ * c-c++-common/gomp/scan-3.c: New test.
+ * c-c++-common/gomp/scan-4.c: New test.
+
2019-06-10 Martin Liska <mliska@suse.cz>
* gcc.dg/no_profile_instrument_function-attr-1.c: Fix
--- /dev/null
+int a, b;
+
+void
+f1 (void)
+{
+ #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+ #pragma omp scan exclusive (b) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */
+}
+
+void
+f2 (int *c, int *d, int *e, int *f)
+{
+ int i, l = 1;
+ #pragma omp for reduction (inscan, +: a) reduction (+: b) /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */
+ for (i = 0; i < 64; i++)
+ {
+ { b++; a += c[i]; }
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (+: a) reduction (inscan, +: b) /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a++; b += c[i]; }
+ #pragma omp scan inclusive (b) /* { dg-error "" } */
+ d[i] = b;
+ }
+ #pragma omp for reduction (inscan, +: e[:2]) /* { dg-error "'inscan' 'reduction' clause with array section" } */
+ for (i = 0; i < 64; ++i)
+ {
+ { e[0] += c[i]; e[1] += c[i]; }
+ #pragma omp scan inclusive (a, e[:2]) /* { dg-error "" } */
+ { d[i] = e[0]; f[i] = e[1]; }
+ }
+ #pragma omp for reduction (inscan, +: a) ordered /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) ordered(1) /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) schedule(static) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) schedule(static, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) schedule(nonmonotonic: dynamic, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ a += c[i];
+ #pragma omp scan inclusive (a) /* { dg-error "" } */
+ d[i] = a;
+ }
+ #pragma omp for reduction (inscan, +: a) linear (l) /* { dg-error "'inscan' 'reduction' clause used together with 'linear' clause for a variable other than loop iterator" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a += c[i]; ++l; }
+ #pragma omp scan inclusive (a)
+ d[i] = a;
+ }
+}
+
+void
+f3 (int *c, int *d)
+{
+ int i;
+ #pragma omp teams reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'teams' construct" } */
+ ;
+ #pragma omp parallel reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'parallel' construct" } */
+ ;
+ #pragma omp sections reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'sections' construct" } */
+ {
+ #pragma omp section
+ ;
+ }
+ #pragma omp target parallel for reduction (inscan, +: a) map (c[:64], d[:64]) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+ #pragma omp teams
+ {
+ #pragma omp distribute parallel for reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+ #pragma omp distribute parallel for simd reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+ }
+}
+
+void
+f4 (int *c, int *d)
+{
+ int i;
+ #pragma omp taskloop reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'taskloop' construct" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-error "" } */
+ a += c[i];
+ }
+}
+
+void
+f5 (int *c, int *d)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a, b) /* { dg-error "'b' specified in 'exclusive' clause but not in 'inscan' 'reduction' clause on the containing construct" } */
+ a += c[i];
+ }
+}
+
+void
+f6 (int *c, int *d)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a)
+ a += c[i];
+ }
+}
+
+void
+f7 (void)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ if (i == 23) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+ continue; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */
+ else if (i == 27)
+ goto l1; /* { dg-error "invalid branch to/from OpenMP structured block" } */
+ #pragma omp scan exclusive (a)
+ {
+ l1: a = 0; /* { dg-error "jump to label 'l1'" "" { target c++ } } */
+ if (i == 33) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+ continue; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */
+ }
+ }
+}
+
+void
+f8 (int *c, int *d, int *e, int *f)
+{
+ int i;
+ #pragma omp for reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a += c[i]; b += d[i]; }
+ #pragma omp scan inclusive (a) inclusive (b) /* { dg-error "expected end of line before 'inclusive'" } */
+ { e[i] = a; f[i] = b; }
+ }
+ #pragma omp for reduction (inscan, +: a, b) /* { dg-error "'.' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */
+ for (i = 0; i < 64; i++)
+ {
+ { a += c[i]; b += d[i]; }
+ #pragma omp scan /* { dg-error "expected 'inclusive' or 'exclusive' clause before end of line" } */
+ { e[i] = a; f[i] = b; }
+ }
+}
+
+void
+f9 (void)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ if (i == 23) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */
+ break; /* { dg-error "break statement used with OpenMP for loop" "" { target c } } */
+ #pragma omp scan exclusive (a)
+ a++;
+ }
+}
--- /dev/null
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+ int i;
+ #pragma omp simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+ a += c[i];
+ }
+}
--- /dev/null
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+ int i;
+ #pragma omp for reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan inclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+ a += c[i];
+ }
+}
--- /dev/null
+int a, b;
+
+void
+f1 (int *c, int *d)
+{
+ int i;
+ #pragma omp for simd reduction (inscan, +: a)
+ for (i = 0; i < 64; i++)
+ {
+ d[i] = a;
+ #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */
+ a += c[i];
+ }
+}
OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */
OMP_CLAUSE_MAP,
- /* OpenACC clause: use_device (variable_list).
+ /* OpenACC clause: use_device (variable-list).
OpenMP clause: use_device_ptr (variable-list). */
OMP_CLAUSE_USE_DEVICE_PTR,
/* OpenMP clause: is_device_ptr (variable-list). */
OMP_CLAUSE_IS_DEVICE_PTR,
+ /* OpenMP clause: inclusive (variable-list). */
+ OMP_CLAUSE_INCLUSIVE,
+
+ /* OpenMP clause: exclusive (variable-list). */
+ OMP_CLAUSE_EXCLUSIVE,
+
/* Internal structure to hold OpenACC cache directive's variable-list.
#pragma acc cache (variable-list). */
OMP_CLAUSE__CACHE_,
gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt)));
break;
+ case GIMPLE_OMP_SCAN:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_scan
+ (s1, gimple_omp_scan_clauses (as_a <gomp_scan *> (stmt)));
+ break;
+
case GIMPLE_OMP_SECTION:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy = gimple_build_omp_section (s1);
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
info, gimple_omp_body_ptr (stmt));
break;
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
walk_body (convert_local_reference_stmt, convert_local_reference_op,
info, gimple_omp_body_ptr (stmt));
break;
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
+ case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt));
break;
case OMP_CLAUSE_IS_DEVICE_PTR:
name = "is_device_ptr";
goto print_remap;
+ case OMP_CLAUSE_INCLUSIVE:
+ name = "inclusive";
+ goto print_remap;
+ case OMP_CLAUSE_EXCLUSIVE:
+ name = "exclusive";
+ goto print_remap;
case OMP_CLAUSE__LOOPTEMP_:
name = "_looptemp_";
goto print_remap;
pp_string (pp, "#pragma omp section");
goto dump_omp_body;
+ case OMP_SCAN:
+ if (OMP_SCAN_CLAUSES (node))
+ {
+ pp_string (pp, "#pragma omp scan");
+ dump_omp_clauses (pp, OMP_SCAN_CLAUSES (node), spc, flags);
+ }
+ goto dump_omp_body;
+
case OMP_MASTER:
pp_string (pp, "#pragma omp master");
goto dump_omp_body;
2, /* OMP_CLAUSE_MAP */
1, /* OMP_CLAUSE_USE_DEVICE_PTR */
1, /* OMP_CLAUSE_IS_DEVICE_PTR */
+ 1, /* OMP_CLAUSE_INCLUSIVE */
+ 1, /* OMP_CLAUSE_EXCLUSIVE */
2, /* OMP_CLAUSE__CACHE_ */
2, /* OMP_CLAUSE_GANG */
1, /* OMP_CLAUSE_ASYNC */
"map",
"use_device_ptr",
"is_device_ptr",
+ "inclusive",
+ "exclusive",
"_cache_",
"gang",
"async",
case OMP_CLAUSE_LINK:
case OMP_CLAUSE_USE_DEVICE_PTR:
case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
case OMP_CLAUSE__LOOPTEMP_:
case OMP_CLAUSE__REDUCTEMP_:
case OMP_CLAUSE__CONDTEMP_:
Operand 1: OMP_SINGLE_CLAUSES: List of clauses. */
DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 2)
+/* OpenMP - #pragma omp scan
+ Operand 0: OMP_SCAN_BODY: Scan body.
+ Operand 1: OMP_SCAN_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_SCAN, "omp_scan", tcc_statement, 2)
+
/* OpenMP - #pragma omp section
Operand 0: OMP_SECTION_BODY: Section body. */
DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1)
#define OMP_BODY(NODE) \
TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_MASTER), 0)
#define OMP_CLAUSES(NODE) \
- TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 1)
+ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SCAN), 1)
/* Generic accessors for OMP nodes that keep clauses as operand 0. */
#define OMP_STANDALONE_CLAUSES(NODE) \
#define OMP_TARGET_EXIT_DATA_CLAUSES(NODE)\
TREE_OPERAND (OMP_TARGET_EXIT_DATA_CHECK (NODE), 0)
+#define OMP_SCAN_BODY(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 0)
+#define OMP_SCAN_CLAUSES(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 1)
+
#define OMP_CLAUSE_SIZE(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
OMP_CLAUSE_FROM, \