aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2019-06-10 14:20:30 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2019-06-10 14:20:30 +0200
commitbf38f7e9aa76856a7c8ac57988600ce9de7cafbd (patch)
tree9e298ccc80525cad1ce63b382a393a876b5071aa /gcc/c/c-parser.c
parent07ca30a0d76c970bbf59a4bce04be41fa297d213 (diff)
downloadgcc-bf38f7e9aa76856a7c8ac57988600ce9de7cafbd.zip
gcc-bf38f7e9aa76856a7c8ac57988600ce9de7cafbd.tar.gz
gcc-bf38f7e9aa76856a7c8ac57988600ce9de7cafbd.tar.bz2
tree.def (OMP_SCAN): New tree code.
* 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
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c87
1 files changed, 81 insertions, 6 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 84ee576..df1a304 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11494,6 +11494,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
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 "
@@ -13558,11 +13565,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
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);
@@ -16738,6 +16741,71 @@ c_parser_omp_flush (c_parser *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.
@@ -16756,6 +16824,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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))
@@ -16772,6 +16841,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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)
{
@@ -16992,7 +17065,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
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);