Hi! This patch adds just the parsing and diagnostics of task reduction modifier. Such reductions behave then differently, like task_reduction clause on taskgroup construct when used on parallel or for/sections.
Tested on x86_64-linux, committed to gomp-5_0-branch. 2018-08-01 Jakub Jelinek <ja...@redhat.com> * tree.h (OMP_CLAUSE_REDUCTION_TASK, OMP_CLAUSE_REDUCTION_INSCAN): Define. * tree-pretty-print.c (dump_omp_clause): Print reduction modifiers. * gimplify.c (gimplify_scan_omp_clauses): Handle OMP_CLAUSE_REDUCTION_TASK diagnostics. gcc/c-family/ * c-omp.c (c_omp_split_clauses): Handle OMP_CLAUSE_REDUCTION_TASK. gcc/c/ * c-parser.c (c_parser_omp_clause_reduction): Add IS_OMP argument, parse reduction modifiers. (c_parser_oacc_all_clauses, c_parser_omp_all_clauses): Adjust c_parser_omp_clause_reduction callers. gcc/cp/ * parser.c (cp_parser_omp_clause_reduction): Add IS_OMP argument, parse reduction modifiers. (cp_parser_oacc_all_clauses, cp_parser_omp_all_clauses): Adjust cp_parser_omp_clause_reduction callers. gcc/testsuite/ * c-c++-common/gomp/reduction-task-1.c: New test. * c-c++-common/gomp/reduction-task-2.c: New test. --- gcc/tree.h.jj 2018-07-17 17:24:39.972318592 +0200 +++ gcc/tree.h 2018-07-30 16:18:35.928699592 +0200 @@ -1614,6 +1614,14 @@ extern tree maybe_wrap_with_location (tr (OMP_CLAUSE_RANGE_CHECK (NODE, OMP_CLAUSE_REDUCTION, \ OMP_CLAUSE_IN_REDUCTION)->base.public_flag) +/* True if a REDUCTION clause has task reduction-modifier. */ +#define OMP_CLAUSE_REDUCTION_TASK(NODE) \ + TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION)) + +/* True if a REDUCTION clause has inscan reduction-modifier. */ +#define OMP_CLAUSE_REDUCTION_INSCAN(NODE) \ + TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_REDUCTION)) + /* True if a LINEAR clause doesn't need copy in. True for iterator vars which are always initialized inside of the loop construct, false otherwise. */ #define OMP_CLAUSE_LINEAR_NO_COPYIN(NODE) \ --- gcc/tree-pretty-print.c.jj 2018-07-10 11:32:22.271156564 +0200 +++ gcc/tree-pretty-print.c 2018-07-30 18:22:56.159264665 +0200 @@ -477,6 +477,13 @@ dump_omp_clause (pretty_printer *pp, tre /* FALLTHRU */ case OMP_CLAUSE_REDUCTION: pp_string (pp, "reduction("); + if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION) + { + if (OMP_CLAUSE_REDUCTION_TASK (clause)) + pp_string (pp, "task,"); + else if (OMP_CLAUSE_REDUCTION_INSCAN (clause)) + pp_string (pp, "inscan,"); + } if (OMP_CLAUSE_REDUCTION_CODE (clause) != ERROR_MARK) { pp_string (pp, --- gcc/gimplify.c.jj 2018-07-25 17:40:05.967970906 +0200 +++ gcc/gimplify.c 2018-08-01 14:34:53.945975952 +0200 @@ -7960,6 +7960,7 @@ gimplify_scan_omp_clauses (tree *list_p, hash_map<tree, tree> *struct_map_to_clause = NULL; tree *prev_list_p = NULL; int handled_depend_iterators = -1; + int nowait = -1; ctx = new_omp_context (region_type); outer_ctx = ctx->outer_context; @@ -8113,6 +8114,32 @@ gimplify_scan_omp_clauses (tree *list_p, } goto do_add; case OMP_CLAUSE_REDUCTION: + if (OMP_CLAUSE_REDUCTION_TASK (c)) + { + if (region_type == ORT_WORKSHARE) + { + if (nowait == -1) + nowait = omp_find_clause (*list_p, + OMP_CLAUSE_NOWAIT) != NULL_TREE; + if (nowait + && (outer_ctx == NULL + || outer_ctx->region_type != ORT_COMBINED_PARALLEL)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<task%> reduction modifier on a construct " + "with a %<nowait%> clause"); + OMP_CLAUSE_REDUCTION_TASK (c) = 0; + } + } + else if ((region_type & ORT_PARALLEL) != ORT_PARALLEL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "invalid %<task%> reduction modifier on construct " + "other than %<parallel%>, %<for%> or %<sections%>"); + OMP_CLAUSE_REDUCTION_TASK (c) = 0; + } + } + /* FALLTHRU */ case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: flags = GOVD_REDUCTION | GOVD_SEEN | GOVD_EXPLICIT; @@ -9016,6 +9043,9 @@ gimplify_scan_omp_clauses (tree *list_p, break; case OMP_CLAUSE_NOWAIT: + nowait = 1; + break; + case OMP_CLAUSE_ORDERED: case OMP_CLAUSE_UNTIED: case OMP_CLAUSE_COLLAPSE: --- gcc/c-family/c-omp.c.jj 2018-07-17 17:24:39.973318593 +0200 +++ gcc/c-family/c-omp.c 2018-08-01 14:04:30.178369000 +0200 @@ -1590,6 +1590,28 @@ c_omp_split_clauses (location_t loc, enu Duplicate it on all of them, but omit on for or sections if parallel is present. */ case OMP_CLAUSE_REDUCTION: + if (OMP_CLAUSE_REDUCTION_TASK (clauses)) + { + if (code == OMP_SIMD /* || code == OMP_LOOP */) + { + error_at (OMP_CLAUSE_LOCATION (clauses), + "invalid %<task%> reduction modifier on construct " + "combined with %<simd%>" /* or %<loop%> */); + OMP_CLAUSE_REDUCTION_TASK (clauses) = 0; + } + else if (code != OMP_SECTIONS + && (mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0 + && (mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_SCHEDULE)) == 0) + { + error_at (OMP_CLAUSE_LOCATION (clauses), + "invalid %<task%> reduction modifier on construct " + "not combined with %<parallel%>, %<for%> or " + "%<sections%>"); + OMP_CLAUSE_REDUCTION_TASK (clauses) = 0; + } + } if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { if (code == OMP_SIMD) @@ -1618,9 +1640,9 @@ c_omp_split_clauses (location_t loc, enu = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); - OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; - cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c; - s = C_OMP_CLAUSE_SPLIT_TEAMS; + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c; + s = C_OMP_CLAUSE_SPLIT_PARALLEL; } else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) --- gcc/c/c-parser.c.jj 2018-07-24 18:19:26.526677938 +0200 +++ gcc/c/c-parser.c 2018-07-31 13:53:31.320112896 +0200 @@ -13076,20 +13076,48 @@ c_parser_omp_clause_private (c_parser *p identifier OpenMP 5.0: + reduction ( reduction-modifier, reduction-operator : variable-list ) in_reduction ( reduction-operator : variable-list ) task_reduction ( reduction-operator : variable-list ) */ static tree c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind, - tree list) + bool is_omp, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; matching_parens parens; if (parens.require_open (parser)) { + bool task = false; + bool inscan = false; enum tree_code code = ERROR_MARK; tree reduc_id = NULL_TREE; + if (kind == OMP_CLAUSE_REDUCTION && is_omp) + { + if (c_parser_next_token_is_keyword (parser, RID_DEFAULT) + && c_parser_peek_2nd_token (parser)->type == CPP_COMMA) + { + c_parser_consume_token (parser); + c_parser_consume_token (parser); + } + else if (c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_COMMA) + { + const char *p + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "task") == 0) + task = true; + else if (strcmp (p, "inscan") == 0) + inscan = true; + if (task || inscan) + { + c_parser_consume_token (parser); + c_parser_consume_token (parser); + } + } + } + switch (c_parser_peek_token (parser)->type) { case CPP_PLUS: @@ -13171,6 +13199,10 @@ c_parser_omp_clause_reduction (c_parser while (TREE_CODE (type) == ARRAY_TYPE) type = TREE_TYPE (type); OMP_CLAUSE_REDUCTION_CODE (c) = code; + if (task) + OMP_CLAUSE_REDUCTION_TASK (c) = 1; + else if (inscan) + OMP_CLAUSE_REDUCTION_INSCAN (c) = 1; if (code == ERROR_MARK || !(INTEGRAL_TYPE_P (type) || TREE_CODE (type) == REAL_TYPE @@ -14452,12 +14484,12 @@ c_parser_oacc_all_clauses (c_parser *par case PRAGMA_OACC_CLAUSE_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - clauses); + false, clauses); c_name = "reduction"; break; case PRAGMA_OACC_CLAUSE_SEQ: clauses = c_parser_oacc_simple_clause (parser, OMP_CLAUSE_SEQ, - clauses); + clauses); c_name = "seq"; break; case PRAGMA_OACC_CLAUSE_TILE: @@ -14581,7 +14613,7 @@ c_parser_omp_all_clauses (c_parser *pars case PRAGMA_OMP_CLAUSE_IN_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION, - clauses); + true, clauses); c_name = "in_reduction"; break; case PRAGMA_OMP_CLAUSE_LASTPRIVATE: @@ -14619,7 +14651,7 @@ c_parser_omp_all_clauses (c_parser *pars case PRAGMA_OMP_CLAUSE_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - clauses); + true, clauses); c_name = "reduction"; break; case PRAGMA_OMP_CLAUSE_SCHEDULE: @@ -14633,7 +14665,7 @@ c_parser_omp_all_clauses (c_parser *pars case PRAGMA_OMP_CLAUSE_TASK_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION, - clauses); + true, clauses); c_name = "task_reduction"; break; case PRAGMA_OMP_CLAUSE_UNTIED: --- gcc/cp/parser.c.jj 2018-07-25 11:42:54.123510698 +0200 +++ gcc/cp/parser.c 2018-07-31 13:56:33.842637416 +0200 @@ -32931,19 +32931,47 @@ cp_parser_omp_clause_ordered (cp_parser id-expression OpenMP 5.0: + reduction ( reduction-modifier, reduction-operator : variable-list ) in_reduction ( reduction-operator : variable-list ) task_reduction ( reduction-operator : variable-list ) */ static tree cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, - tree list) + bool is_omp, tree list) { enum tree_code code = ERROR_MARK; tree nlist, c, id = NULL_TREE; + bool task = false; + bool inscan = false; if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; + if (kind == OMP_CLAUSE_REDUCTION && is_omp) + { + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA)) + { + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + } + else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + if (strcmp (p, "task") == 0) + task = true; + else if (strcmp (p, "inscan") == 0) + inscan = true; + if (task || inscan) + { + cp_lexer_consume_token (parser->lexer); + cp_lexer_consume_token (parser->lexer); + } + } + } + switch (cp_lexer_peek_token (parser->lexer)->type) { case CPP_PLUS: code = PLUS_EXPR; break; @@ -33021,6 +33049,10 @@ cp_parser_omp_clause_reduction (cp_parse for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) { OMP_CLAUSE_REDUCTION_CODE (c) = code; + if (task) + OMP_CLAUSE_REDUCTION_TASK (c) = 1; + else if (inscan) + OMP_CLAUSE_REDUCTION_INSCAN (c) = 1; OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = id; } @@ -34272,7 +34304,7 @@ cp_parser_oacc_all_clauses (cp_parser *p case PRAGMA_OACC_CLAUSE_REDUCTION: clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - clauses); + false, clauses); c_name = "reduction"; break; case PRAGMA_OACC_CLAUSE_SEQ: @@ -34422,7 +34454,7 @@ cp_parser_omp_all_clauses (cp_parser *pa case PRAGMA_OMP_CLAUSE_IN_REDUCTION: clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION, - clauses); + true, clauses); c_name = "in_reduction"; break; case PRAGMA_OMP_CLAUSE_LASTPRIVATE: @@ -34466,7 +34498,7 @@ cp_parser_omp_all_clauses (cp_parser *pa case PRAGMA_OMP_CLAUSE_REDUCTION: clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - clauses); + true, clauses); c_name = "reduction"; break; case PRAGMA_OMP_CLAUSE_SCHEDULE: @@ -34483,7 +34515,7 @@ cp_parser_omp_all_clauses (cp_parser *pa clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION, - clauses); + true, clauses); c_name = "task_reduction"; break; case PRAGMA_OMP_CLAUSE_UNTIED: --- gcc/testsuite/c-c++-common/gomp/reduction-task-1.c.jj 2018-08-01 15:14:14.318166966 +0200 +++ gcc/testsuite/c-c++-common/gomp/reduction-task-1.c 2018-07-31 16:06:16.951634432 +0200 @@ -0,0 +1,86 @@ +int v; +extern void foo (int); + +void +bar (void) +{ + int i; + #pragma omp for reduction (task, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp sections reduction (task, +: v) + { + foo (-2); + #pragma omp section + foo (-3); + } + #pragma omp parallel reduction (task, +: v) + foo (-1); + #pragma omp parallel for reduction (task, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp parallel sections reduction (task, +: v) + { + foo (-2); + #pragma omp section + foo (-3); + } + #pragma omp teams distribute parallel for reduction (task, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp for reduction (default, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp sections reduction (default, +: v) + { + foo (-2); + #pragma omp section + foo (-3); + } + #pragma omp parallel reduction (default, +: v) + foo (-1); + #pragma omp parallel for reduction (default, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp parallel sections reduction (default, +: v) + { + foo (-2); + #pragma omp section + foo (-3); + } + #pragma omp teams distribute parallel for reduction (default, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp for reduction (default, +: v) nowait + for (i = 0; i < 64; i++) + foo (i); + #pragma omp sections nowait reduction (default, +: v) + { + foo (-2); + #pragma omp section + foo (-3); + } + #pragma omp simd reduction (default, +: v) + for (i = 0; i < 64; i++) + v++; + #pragma omp for simd reduction (default, +: v) + for (i = 0; i < 64; i++) + v++; + #pragma omp parallel for simd reduction (default, +: v) + for (i = 0; i < 64; i++) + v++; + #pragma omp teams distribute parallel for simd reduction (default, +: v) + for (i = 0; i < 64; i++) + v++; + #pragma omp taskloop reduction (default, +: v) + for (i = 0; i < 64; i++) + foo (i); + #pragma omp taskloop simd reduction (default, +: v) + for (i = 0; i < 64; i++) + v++; + #pragma omp teams reduction (default, +: v) + foo (i); + #pragma omp teams distribute reduction (default, +: v) + for (i = 0; i < 64; i++) + foo (i); +} --- gcc/testsuite/c-c++-common/gomp/reduction-task-2.c.jj 2018-08-01 15:14:18.040177038 +0200 +++ gcc/testsuite/c-c++-common/gomp/reduction-task-2.c 2018-08-01 14:27:51.320913239 +0200 @@ -0,0 +1,40 @@ +int v; +extern void foo (int); + +void +bar (void) +{ + int i; + #pragma omp for reduction (task, +: v) nowait /* { dg-error "'task' reduction modifier on a construct with a 'nowait' clause" } */ + for (i = 0; i < 64; i++) + foo (i); + #pragma omp sections nowait reduction (task, +: v) /* { dg-error "'task' reduction modifier on a construct with a 'nowait' clause" } */ + { + foo (-2); + #pragma omp section + foo (-3); + } + #pragma omp simd reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */ + for (i = 0; i < 64; i++) + v++; + #pragma omp for simd reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */ + for (i = 0; i < 64; i++) + v++; + #pragma omp parallel for simd reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */ + for (i = 0; i < 64; i++) + v++; + #pragma omp teams distribute parallel for simd reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */ + for (i = 0; i < 64; i++) + v++; + #pragma omp taskloop reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */ + for (i = 0; i < 64; i++) + foo (i); + #pragma omp taskloop simd reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct combined with 'simd'" } */ + for (i = 0; i < 64; i++) + v++; + #pragma omp teams reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct other than 'parallel', 'for' or 'sections'" } */ + foo (i); + #pragma omp teams distribute reduction (task, +: v) /* { dg-error "invalid 'task' reduction modifier on construct not combined with 'parallel', 'for' or 'sections'" } */ + for (i = 0; i < 64; i++) + foo (i); +} Jakub