Hi! OpenMP 5.0 adds a couple of new combined constructs, mainly to save typing when using tasking. In particular #pragma omp parallel master #pragma omp master taskloop #pragma omp master taskloop simd #pragma omp parallel master taskloop #pragma omp parallel master taskloop simd Tested on x86_64-linux, committed to gomp-5_0-branch.
2018-10-18 Jakub Jelinek <ja...@redhat.com> * gimplify.c (enum omp_region_type): Add ORT_TASKLOOP and ORT_UNTIED_TASKLOOP. (omp_default_clause): Print "taskloop" rather than "task" if ORT_*TASKLOOP. (gimplify_scan_omp_clauses): Add shared clause on parallel for combined parallel master taskloop{, simd} if taskloop has firstprivate, lastprivate or reduction clause. (gimplify_omp_for): Likewise. Use ORT_TASKLOOP or ORT_UNTIED_TASKLOOP instead of ORT_TASK or ORT_UNTIED_TASK. gcc/c-family/ * c-omp.c (c_omp_split_clauses): Add support for combined #pragma omp parallel master and #pragma omp {,parallel }master taskloop{, simd} constructs. gcc/c/ * c-parser.c (c_parser_omp_taskloop): Add forward declaration. Disallow in_reduction clause when combined with parallel master. (c_parser_omp_master): Add p_name, mask and cclauses arguments. Allow to be called while parsing combined parallel master. Parse combined master taskloop{, simd}. (c_parser_omp_parallel): Parse combined parallel master{, taskloop{, simd}} constructs. (c_parser_omp_construct) <case PRAGMA_OMP_MASTER>: Adjust c_parser_omp_master caller. gcc/cp/ * parser.c (cp_parser_omp_taskloop): Add forward declaration. Disallow in_reduction clause when combined with parallel master. (cp_parser_omp_master): Add p_name, mask and cclauses arguments. Allow to be called while parsing combined parallel master. Parse combined master taskloop{, simd}. (cp_parser_omp_parallel): Parse combined parallel master{, taskloop{, simd}} constructs. (cp_parser_omp_construct) <case PRAGMA_OMP_MASTER>: Adjust c_parser_omp_master caller. gcc/testsuite/ * c-c++-common/gomp/clauses-1.c (foo): Add ntm argument and test if and nontemporal clauses on constructs with simd. (bar): Add ntm and i3 arguments. Test if and nontemporal clauses on constructs with simd. Change if clauses on some constructs from specific to the particular constituents to one without a modifier. Add new tests for combined host teams and for new parallel master and {,parallel }master taskloop{, simd} combined constructs. (baz): New function with host teams tests. * c-c++-common/gomp/default-1.c: New test. * c-c++-common/gomp/master-combined-1.c: New test. * c-c++-common/gomp/master-combined-2.c: New test. libgomp/ * testsuite/libgomp.c-c++-common/master-combined-1.c: New test. * testsuite/libgomp.c-c++-common/taskloop-reduction-3.c: New test. * testsuite/libgomp.c-c++-common/taskloop-reduction-4.c: New test. --- gcc/gimplify.c.jj 2018-10-16 16:12:25.461419030 +0200 +++ gcc/gimplify.c 2018-10-18 11:09:56.180590210 +0200 @@ -130,6 +130,8 @@ enum omp_region_type ORT_TASK = 0x10, ORT_UNTIED_TASK = ORT_TASK | 1, + ORT_TASKLOOP = ORT_TASK | 2, + ORT_UNTIED_TASKLOOP = ORT_UNTIED_TASK | 2, ORT_TEAMS = 0x20, ORT_COMBINED_TEAMS = ORT_TEAMS | 1, @@ -6992,6 +6994,8 @@ omp_default_clause (struct gimplify_omp_ if (ctx->region_type & ORT_PARALLEL) rtype = "parallel"; + else if ((ctx->region_type & ORT_TASKLOOP) == ORT_TASKLOOP) + rtype = "taskloop"; else if (ctx->region_type & ORT_TASK) rtype = "task"; else if (ctx->region_type & ORT_TEAMS) @@ -8976,6 +8980,31 @@ gimplify_scan_omp_clauses (tree *list_p, " or private in outer context", DECL_NAME (decl)); } do_notice: + if ((region_type & ORT_TASKLOOP) == ORT_TASKLOOP + && outer_ctx + && outer_ctx->region_type == ORT_COMBINED_PARALLEL + && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)) + { + splay_tree_node on + = splay_tree_lookup (outer_ctx->variables, + (splay_tree_key)decl); + if (on == NULL || (on->value & GOVD_DATA_SHARE_CLASS) == 0) + { + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF + && (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + || (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE + && (TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) + == POINTER_TYPE)))) + omp_firstprivatize_variable (outer_ctx, decl); + else + omp_add_variable (outer_ctx, decl, + GOVD_SEEN | GOVD_SHARED); + omp_notice_variable (outer_ctx, decl, true); + } + } if (outer_ctx) omp_notice_variable (outer_ctx, decl, true); if (check_non_private @@ -10421,9 +10450,9 @@ gimplify_omp_for (tree *expr_p, gimple_s break; case OMP_TASKLOOP: if (omp_find_clause (OMP_FOR_CLAUSES (for_stmt), OMP_CLAUSE_UNTIED)) - ort = ORT_UNTIED_TASK; + ort = ORT_UNTIED_TASKLOOP; else - ort = ORT_TASK; + ort = ORT_TASKLOOP; break; case OMP_SIMD: ort = ORT_SIMD; @@ -10731,7 +10760,8 @@ gimplify_omp_for (tree *expr_p, gimple_s else if (omp_check_private (outer, decl, false)) outer = NULL; } - else if (((outer->region_type & ORT_TASK) != 0) + else if (((outer->region_type & ORT_TASKLOOP) + == ORT_TASKLOOP) && outer->combined_loop && !omp_check_private (gimplify_omp_ctxp, decl, false)) @@ -10770,8 +10800,12 @@ gimplify_omp_for (tree *expr_p, gimple_s outer = NULL; } if (outer && outer->outer_context - && (outer->outer_context->region_type - & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS) + && ((outer->outer_context->region_type + & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS + || (((outer->region_type & ORT_TASKLOOP) + == ORT_TASKLOOP) + && (outer->outer_context->region_type + == ORT_COMBINED_PARALLEL)))) { outer = outer->outer_context; n = splay_tree_lookup (outer->variables, @@ -10818,7 +10852,8 @@ gimplify_omp_for (tree *expr_p, gimple_s else if (omp_check_private (outer, decl, false)) outer = NULL; } - else if (((outer->region_type & ORT_TASK) != 0) + else if (((outer->region_type & ORT_TASKLOOP) + == ORT_TASKLOOP) && outer->combined_loop && !omp_check_private (gimplify_omp_ctxp, decl, false)) @@ -10857,8 +10892,12 @@ gimplify_omp_for (tree *expr_p, gimple_s outer = NULL; } if (outer && outer->outer_context - && (outer->outer_context->region_type - & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS) + && ((outer->outer_context->region_type + & ORT_COMBINED_TEAMS) == ORT_COMBINED_TEAMS + || (((outer->region_type & ORT_TASKLOOP) + == ORT_TASKLOOP) + && (outer->outer_context->region_type + == ORT_COMBINED_PARALLEL)))) { outer = outer->outer_context; n = splay_tree_lookup (outer->variables, --- gcc/c-family/c-omp.c.jj 2018-10-16 16:18:55.888890541 +0200 +++ gcc/c-family/c-omp.c 2018-10-18 12:24:18.639752122 +0200 @@ -1260,18 +1260,24 @@ c_oacc_split_loop_clauses (tree clauses, } /* This function attempts to split or duplicate clauses for OpenMP - combined/composite constructs. Right now there are 21 different + combined/composite constructs. Right now there are 26 different constructs. CODE is the innermost construct in the combined construct, and MASK allows to determine which constructs are combined together, as every construct has at least one clause that no other construct - has (except for OMP_SECTIONS, but that can be only combined with parallel). + has (except for OMP_SECTIONS, but that can be only combined with parallel, + and OMP_MASTER, which doesn't have any clauses at all). OpenMP combined/composite constructs are: #pragma omp distribute parallel for #pragma omp distribute parallel for simd #pragma omp distribute simd #pragma omp for simd + #pragma omp master taskloop + #pragma omp master taskloop simd #pragma omp parallel for #pragma omp parallel for simd + #pragma omp parallel master + #pragma omp parallel master taskloop + #pragma omp parallel master taskloop simd #pragma omp parallel sections #pragma omp target parallel #pragma omp target parallel for @@ -1305,8 +1311,9 @@ c_omp_split_clauses (location_t loc, enu { case OMP_FOR: case OMP_SIMD: - cclauses[C_OMP_CLAUSE_SPLIT_FOR] - = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) + cclauses[C_OMP_CLAUSE_SPLIT_FOR] + = build_omp_clause (loc, OMP_CLAUSE_NOWAIT); break; case OMP_SECTIONS: cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS] @@ -1411,8 +1418,8 @@ c_omp_split_clauses (location_t loc, enu else s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; - /* Private clause is supported on all constructs, - it is enough to put it on the innermost one. For + /* Private clause is supported on all constructs but master, + it is enough to put it on the innermost one other than master. For #pragma omp {for,sections} put it on parallel though, as that's what we did for OpenMP 3.1. */ case OMP_CLAUSE_PRIVATE: @@ -1423,12 +1430,14 @@ c_omp_split_clauses (location_t loc, enu case OMP_PARALLEL: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break; + case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; + case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; default: gcc_unreachable (); } break; /* Firstprivate clause is supported on all constructs but - simd. Put it on the outermost of those and duplicate on teams - and parallel. */ + simd and master. Put it on the outermost of those and duplicate on + teams and parallel. */ case OMP_CLAUSE_FIRSTPRIVATE: if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) @@ -1467,6 +1476,11 @@ c_omp_split_clauses (location_t loc, enu else s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; } + else if ((mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) + /* This must be + #pragma omp parallel master taskloop{, simd}. */ + s = C_OMP_CLAUSE_SPLIT_TASKLOOP; else /* This must be #pragma omp parallel{, for{, simd}, sections} @@ -1496,8 +1510,10 @@ c_omp_split_clauses (location_t loc, enu else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) { - /* This must be #pragma omp taskloop simd. */ - gcc_assert (code == OMP_SIMD); + /* This must be #pragma omp {,{,parallel }master }taskloop simd + or + #pragma omp {,parallel }master taskloop. */ + gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP); s = C_OMP_CLAUSE_SPLIT_TASKLOOP; } else @@ -1507,9 +1523,9 @@ c_omp_split_clauses (location_t loc, enu s = C_OMP_CLAUSE_SPLIT_FOR; } break; - /* Lastprivate is allowed on distribute, for, sections and simd. In - parallel {for{, simd},sections} we actually want to put it on - parallel rather than for or sections. */ + /* Lastprivate is allowed on distribute, for, sections, taskloop and + simd. In parallel {for{, simd},sections} we actually want to put + it on parallel rather than for or sections. */ case OMP_CLAUSE_LASTPRIVATE: if (code == OMP_DISTRIBUTE) { @@ -1536,6 +1552,11 @@ c_omp_split_clauses (location_t loc, enu s = C_OMP_CLAUSE_SPLIT_FOR; break; } + if (code == OMP_TASKLOOP) + { + s = C_OMP_CLAUSE_SPLIT_TASKLOOP; + break; + } gcc_assert (code == OMP_SIMD); if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { @@ -1552,6 +1573,16 @@ c_omp_split_clauses (location_t loc, enu OMP_CLAUSE_CHAIN (c) = cclauses[s]; cclauses[s] = c; } + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_LASTPRIVATE); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) + = OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; + cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c; + } s = C_OMP_CLAUSE_SPLIT_SIMD; break; /* Shared and default clauses are allowed on parallel, teams and @@ -1561,6 +1592,19 @@ c_omp_split_clauses (location_t loc, enu if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) { + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_CODE (clauses)); + if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_SHARED) + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + else + OMP_CLAUSE_DEFAULT_KIND (c) + = OMP_CLAUSE_DEFAULT_KIND (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; + cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] = c; + } s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; } @@ -1585,9 +1629,10 @@ c_omp_split_clauses (location_t loc, enu } s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; - /* Reduction is allowed on simd, for, parallel, sections and teams. - Duplicate it on all of them, but omit on for or sections if - parallel is present. */ + /* Reduction is allowed on simd, for, parallel, sections, taskloop + and teams. Duplicate it on all of them, but omit on for or + sections if parallel is present. If taskloop is combined with + parallel, omit it on parallel. */ case OMP_CLAUSE_REDUCTION: if (OMP_CLAUSE_REDUCTION_TASK (clauses)) { @@ -1649,8 +1694,12 @@ c_omp_split_clauses (location_t loc, enu else s = C_OMP_CLAUSE_SPLIT_FOR; } - else if (code == OMP_SECTIONS || code == OMP_PARALLEL) + else if (code == OMP_SECTIONS + || code == OMP_PARALLEL + || code == OMP_MASTER) s = C_OMP_CLAUSE_SPLIT_PARALLEL; + else if (code == OMP_TASKLOOP) + s = C_OMP_CLAUSE_SPLIT_TASKLOOP; else if (code == OMP_SIMD) { if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) @@ -1763,7 +1812,22 @@ c_omp_split_clauses (location_t loc, enu } if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) - s = C_OMP_CLAUSE_SPLIT_TASKLOOP; + { + if ((mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_IF); + OMP_CLAUSE_IF_MODIFIER (c) + = OMP_CLAUSE_IF_MODIFIER (clauses); + OMP_CLAUSE_IF_EXPR (c) = OMP_CLAUSE_IF_EXPR (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; + cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c; + s = C_OMP_CLAUSE_SPLIT_PARALLEL; + } + else + s = C_OMP_CLAUSE_SPLIT_TASKLOOP; + } else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) { --- gcc/c/c-parser.c.jj 2018-10-17 11:49:04.527491213 +0200 +++ gcc/c/c-parser.c 2018-10-17 18:34:27.788735346 +0200 @@ -16804,6 +16804,9 @@ c_parser_omp_for (location_t loc, c_pars return ret; } +static tree c_parser_omp_taskloop (location_t, c_parser *, char *, + omp_clause_mask, tree *, bool *); + /* OpenMP 2.5: # pragma omp master new-line structured-block @@ -16812,9 +16815,52 @@ c_parser_omp_for (location_t loc, c_pars */ static tree -c_parser_omp_master (location_t loc, c_parser *parser, bool *if_p) +c_parser_omp_master (location_t loc, c_parser *parser, + char *p_name, omp_clause_mask mask, tree *cclauses, + bool *if_p) { - c_parser_skip_to_pragma_eol (parser); + tree block, clauses, ret; + + strcat (p_name, " master"); + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + + if (strcmp (p, "taskloop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + c_parser_consume_token (parser); + if (!flag_openmp) /* flag_openmp_simd */ + return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses, + if_p); + block = c_begin_compound_stmt (true); + ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses, + if_p); + block = c_end_compound_stmt (loc, block, true); + if (ret == NULL_TREE) + return ret; + ret = c_finish_omp_master (loc, block); + return ret; + } + } + if (!flag_openmp) /* flag_openmp_simd */ + { + c_parser_skip_to_pragma_eol (parser, false); + return NULL_TREE; + } + + if (cclauses) + { + clauses = c_parser_omp_all_clauses (parser, mask, p_name, false); + omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses); + } + else + c_parser_skip_to_pragma_eol (parser); + return c_finish_omp_master (loc, c_parser_omp_structured_block (parser, if_p)); } @@ -17076,19 +17122,38 @@ c_parser_omp_parallel (location_t loc, c c_parser_skip_to_pragma_eol (parser); return NULL_TREE; } - else if (!flag_openmp) /* flag_openmp_simd */ - { - c_parser_skip_to_pragma_eol (parser, false); - return NULL_TREE; - } else if (cclauses == NULL && c_parser_next_token_is (parser, CPP_NAME)) { const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); - if (strcmp (p, "sections") == 0) + if (strcmp (p, "master") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; - if (cclauses == NULL) - cclauses = cclauses_buf; + cclauses = cclauses_buf; + + c_parser_consume_token (parser); + if (!flag_openmp) /* flag_openmp_simd */ + return c_parser_omp_master (loc, parser, p_name, mask, cclauses, + if_p); + block = c_begin_omp_parallel (); + tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses, + if_p); + stmt = c_finish_omp_parallel (loc, + cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + OMP_PARALLEL_COMBINED (stmt) = 1; + if (ret == NULL) + return ret; + return stmt; + } + else if (!flag_openmp) /* flag_openmp_simd */ + { + c_parser_skip_to_pragma_eol (parser, false); + return NULL_TREE; + } + else if (strcmp (p, "sections") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + cclauses = cclauses_buf; c_parser_consume_token (parser); block = c_begin_omp_parallel (); @@ -17100,6 +17165,11 @@ c_parser_omp_parallel (location_t loc, c return stmt; } } + else if (!flag_openmp) /* flag_openmp_simd */ + { + c_parser_skip_to_pragma_eol (parser, false); + return NULL_TREE; + } clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL); if (cclauses) @@ -18892,6 +18962,10 @@ c_parser_omp_taskloop (location_t loc, c strcat (p_name, " taskloop"); mask |= OMP_TASKLOOP_CLAUSE_MASK; + /* #pragma omp parallel master taskloop{, simd} disallow in_reduction + clause. */ + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) + mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION); if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -19003,7 +19077,8 @@ c_parser_omp_construct (c_parser *parser stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p); break; case PRAGMA_OMP_MASTER: - stmt = c_parser_omp_master (loc, parser, if_p); + strcpy (p_name, "#pragma omp"); + stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p); break; case PRAGMA_OMP_PARALLEL: strcpy (p_name, "#pragma omp"); --- gcc/cp/parser.c.jj 2018-08-02 15:12:57.043831778 +0200 +++ gcc/cp/parser.c 2018-10-18 10:17:14.098009735 +0200 @@ -36569,15 +36569,66 @@ cp_parser_omp_for (cp_parser *parser, cp return ret; } +static tree cp_parser_omp_taskloop (cp_parser *, cp_token *, char *, + omp_clause_mask, tree *, bool *); + /* OpenMP 2.5: # pragma omp master new-line structured-block */ static tree -cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, bool *if_p) +cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, + char *p_name, omp_clause_mask mask, tree *cclauses, + bool *if_p) { - cp_parser_require_pragma_eol (parser, pragma_tok); - return c_finish_omp_master (input_location, + tree clauses, sb, ret; + unsigned int save; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + + strcat (p_name, " master"); + + 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, "taskloop") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + if (cclauses == NULL) + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + if (!flag_openmp) /* flag_openmp_simd */ + return cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + ret = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, + cclauses, if_p); + cp_parser_end_omp_structured_block (parser, save); + tree body = finish_omp_structured_block (sb); + if (ret == NULL) + return ret; + return c_finish_omp_master (loc, body); + } + } + if (!flag_openmp) /* flag_openmp_simd */ + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + + if (cclauses) + { + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, + false); + cp_omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses); + } + else + cp_parser_require_pragma_eol (parser, pragma_tok); + + return c_finish_omp_master (loc, cp_parser_omp_structured_block (parser, if_p)); } @@ -36819,16 +36870,34 @@ cp_parser_omp_parallel (cp_parser *parse cp_parser_skip_to_pragma_eol (parser, pragma_tok); return NULL_TREE; } - else if (!flag_openmp) /* flag_openmp_simd */ - { - cp_parser_skip_to_pragma_eol (parser, pragma_tok); - return NULL_TREE; - } else if (cclauses == NULL && 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, "sections") == 0) + if (strcmp (p, "master") == 0) + { + tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; + cclauses = cclauses_buf; + + cp_lexer_consume_token (parser->lexer); + block = begin_omp_parallel (); + save = cp_parser_begin_omp_structured_block (parser); + tree ret = cp_parser_omp_master (parser, pragma_tok, p_name, mask, + cclauses, if_p); + cp_parser_end_omp_structured_block (parser, save); + stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL], + block); + OMP_PARALLEL_COMBINED (stmt) = 1; + if (ret == NULL_TREE) + return ret; + return stmt; + } + else if (!flag_openmp) /* flag_openmp_simd */ + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } + else if (strcmp (p, "sections") == 0) { tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT]; cclauses = cclauses_buf; @@ -36844,6 +36913,11 @@ cp_parser_omp_parallel (cp_parser *parse return stmt; } } + else if (!flag_openmp) /* flag_openmp_simd */ + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return NULL_TREE; + } clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok, cclauses == NULL); @@ -39089,6 +39163,10 @@ cp_parser_omp_taskloop (cp_parser *parse strcat (p_name, " taskloop"); mask |= OMP_TASKLOOP_CLAUSE_MASK; + /* #pragma omp parallel master taskloop{, simd} disallow in_reduction + clause. */ + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0) + mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION); if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) { @@ -39451,7 +39529,9 @@ cp_parser_omp_construct (cp_parser *pars if_p); break; case PRAGMA_OMP_MASTER: - stmt = cp_parser_omp_master (parser, pragma_tok, if_p); + strcpy (p_name, "#pragma omp"); + stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL, + if_p); break; case PRAGMA_OMP_PARALLEL: strcpy (p_name, "#pragma omp"); --- gcc/testsuite/c-c++-common/gomp/clauses-1.c.jj 2018-10-16 17:00:40.450995193 +0200 +++ gcc/testsuite/c-c++-common/gomp/clauses-1.c 2018-10-18 16:12:32.020017951 +0200 @@ -9,7 +9,7 @@ int f, l, ll, r, r2; void foo (int d, int m, int i1, int i2, int p, int *idp, int s, - int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q) + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) { #pragma omp distribute parallel for \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ @@ -19,26 +19,50 @@ foo (int d, int m, int i1, int i2, int p ll++; #pragma omp distribute parallel for simd \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ - if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ - lastprivate (l) schedule(static, 4) \ + if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) schedule(static, 4) nontemporal(ntm) \ safelen(8) simdlen(4) aligned(q: 32) for (int i = 0; i < 64; i++) ll++; #pragma omp distribute simd \ private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ - safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) + safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; } #pragma omp end declare target void -bar (int d, int m, int i1, int i2, int p, int *idp, int s, - int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd) +baz (int d, int m, int i1, int i2, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int ntm) +{ + #pragma omp distribute parallel for \ + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ + if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) schedule(static, 4) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute parallel for simd \ + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ + if (parallel: i2) if(simd: i1) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ + lastprivate (l) schedule(static, 4) nontemporal(ntm) \ + safelen(8) simdlen(4) aligned(q: 32) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp distribute simd \ + private (p) firstprivate (f) collapse(1) dist_schedule(static, 16) \ + safelen(8) simdlen(4) aligned(q: 32) reduction(+:r) if(i1) nontemporal(ntm) + for (int i = 0; i < 64; i++) + ll++; +} + +void +bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s, + int nte, int tl, int nth, int g, int nta, int fi, int pp, int *q, int *dd, int ntm) { #pragma omp for simd \ private (p) firstprivate (f) lastprivate (l) linear (ll:1) reduction(+:r) schedule(static, 4) collapse(1) nowait \ - safelen(8) simdlen(4) aligned(q: 32) + safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) if(i1) for (int i = 0; i < 64; i++) ll++; #pragma omp parallel for \ @@ -47,9 +71,9 @@ bar (int d, int m, int i1, int i2, int p for (int i = 0; i < 64; i++) ll++; #pragma omp parallel for simd \ - private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \ + private (p) firstprivate (f) if (i2) default(shared) shared(s) copyin(t) reduction(+:r) num_threads (nth) proc_bind(spread) \ lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) \ - safelen(8) simdlen(4) aligned(q: 32) + safelen(8) simdlen(4) aligned(q: 32) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp parallel sections \ @@ -76,7 +100,7 @@ bar (int d, int m, int i1, int i2, int p device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ if (parallel: i2) default(shared) shared(s) reduction(+:r) num_threads (nth) proc_bind(spread) \ lastprivate (l) linear (ll:1) schedule(static, 4) collapse(1) \ - safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) for (int i = 0; i < 64; i++) ll++; #pragma omp target teams \ @@ -103,38 +127,38 @@ bar (int d, int m, int i1, int i2, int p collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ lastprivate (l) schedule(static, 4) \ - safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) if (simd: i3) for (int i = 0; i < 64; i++) ll++; #pragma omp target teams distribute simd \ - device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ + device(d) map (tofrom: m) if (i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ - safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) + safelen(8) simdlen(4) aligned(q: 32) nowait depend(inout: dd[0]) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp target simd \ device(d) map (tofrom: m) if (target: i1) private (p) firstprivate (f) defaultmap(tofrom: scalar) is_device_ptr (idp) \ safelen(8) simdlen(4) lastprivate (l) linear(ll: 1) aligned(q: 32) reduction(+:r) \ - nowait depend(inout: dd[0]) + nowait depend(inout: dd[0]) nontemporal(ntm) if(simd:i3) for (int i = 0; i < 64; i++) ll++; #pragma omp taskgroup task_reduction(+:r2) #pragma omp taskloop simd \ - private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \ + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp taskgroup task_reduction(+:r) #pragma omp taskloop simd \ - private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable nogroup priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(i1) final(fi) mergeable nogroup priority (pp) \ + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) in_reduction(+:r) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp taskwait #pragma omp taskloop simd \ private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) if(taskloop: i1) final(fi) priority (pp) \ - safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(+:r) if (simd: i3) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp target nowait depend(inout: dd[0]) @@ -157,14 +181,83 @@ bar (int d, int m, int i1, int i2, int p collapse(1) dist_schedule(static, 16) \ if (parallel: i2) num_threads (nth) proc_bind(spread) \ lastprivate (l) schedule(static, 4) \ - safelen(8) simdlen(4) aligned(q: 32) + safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) for (int i = 0; i < 64; i++) ll++; #pragma omp target #pragma omp teams distribute simd \ private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ collapse(1) dist_schedule(static, 16) \ - safelen(8) simdlen(4) aligned(q: 32) + safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute parallel for \ + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ + collapse(1) dist_schedule(static, 16) \ + if (parallel: i2) num_threads (nth) proc_bind(spread) \ + lastprivate (l) schedule(static, 4) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute parallel for simd \ + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ + collapse(1) dist_schedule(static, 16) \ + if (parallel: i2) num_threads (nth) proc_bind(spread) \ + lastprivate (l) schedule(static, 4) \ + safelen(8) simdlen(4) aligned(q: 32) if (simd: i3) nontemporal(ntm) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp teams distribute simd \ + private(p) firstprivate (f) shared(s) default(shared) reduction(+:r) num_teams(nte) thread_limit(tl) \ + collapse(1) dist_schedule(static, 16) \ + safelen(8) simdlen(4) aligned(q: 32) if(i3) nontemporal(ntm) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master \ + private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) \ + num_threads (nth) proc_bind(spread) copyin(t) + ; + #pragma omp taskgroup task_reduction (+:r2) + #pragma omp master taskloop \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) \ + reduction(default, +:r) in_reduction(+:r2) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup task_reduction (+:r2) + #pragma omp master taskloop simd \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \ + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) final(fi) mergeable priority (pp) \ + reduction(default, +:r) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop simd \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) grainsize (g) collapse(1) untied if(taskloop: i1) if(simd: i2) final(fi) mergeable priority (pp) \ + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) if (parallel: i2) num_threads (nth) proc_bind(spread) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup task_reduction (+:r2) + #pragma omp master taskloop \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \ + reduction(default, +:r) in_reduction(+:r2) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp taskgroup task_reduction (+:r2) + #pragma omp master taskloop simd \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \ + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) in_reduction(+:r2) nontemporal(ntm) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \ + reduction(default, +:r) num_threads (nth) proc_bind(spread) copyin(t) + for (int i = 0; i < 64; i++) + ll++; + #pragma omp parallel master taskloop simd \ + private (p) firstprivate (f) lastprivate (l) shared (s) default(shared) num_tasks (nta) collapse(1) untied if(i1) final(fi) mergeable priority (pp) \ + safelen(8) simdlen(4) linear(ll: 1) aligned(q: 32) reduction(default, +:r) nontemporal(ntm) num_threads (nth) proc_bind(spread) copyin(t) for (int i = 0; i < 64; i++) ll++; } --- gcc/testsuite/c-c++-common/gomp/default-1.c.jj 2018-10-18 11:29:33.963102983 +0200 +++ gcc/testsuite/c-c++-common/gomp/default-1.c 2018-10-18 11:29:28.030201128 +0200 @@ -0,0 +1,22 @@ +void +foo (void) +{ + int x = 0, i; + #pragma omp task default(none) /* { dg-error "enclosing 'task'" } */ + { + x++; /* { dg-error "'x' not specified in enclosing 'task'" } */ + } + #pragma omp taskloop default(none) /* { dg-error "enclosing 'taskloop'" } */ + for (i = 0; i < 64; i++) + { + x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */ + } + #pragma omp teams default(none) /* { dg-error "enclosing 'teams'" } */ + { + x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */ + } + #pragma omp parallel default(none) /* { dg-error "enclosing 'parallel'" } */ + { + x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */ + } +} --- gcc/testsuite/c-c++-common/gomp/master-combined-1.c.jj 2018-10-18 11:23:24.029222516 +0200 +++ gcc/testsuite/c-c++-common/gomp/master-combined-1.c 2018-10-18 11:24:28.557155079 +0200 @@ -0,0 +1,32 @@ +void bar (int *); + +void +foo (int *a) +{ + int i, j, k, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0; + #pragma omp parallel master default(none) private (k) + bar (&k); + #pragma omp parallel default(none) firstprivate(a) shared(x, y, z) + { + #pragma omp master taskloop reduction (+:x) default(none) firstprivate(a) + for (i = 0; i < 64; i++) + x += a[i]; + #pragma omp master taskloop simd reduction (+:y) default(none) firstprivate(a) private (i) + for (i = 0; i < 64; i++) + y += a[i]; + #pragma omp master taskloop simd collapse(2) reduction (+:z) default(none) firstprivate(a) private (i, j) + for (j = 0; j < 1; j++) + for (i = 0; i < 64; ++i) + z += a[i]; + } + #pragma omp parallel master taskloop reduction (+:u) default(none) firstprivate(a) + for (i = 0; i < 64; i++) + u += a[i]; + #pragma omp parallel master taskloop simd reduction (+:v) default(none) firstprivate(a) + for (i = 0; i < 64; i++) + v += a[i]; + #pragma omp parallel master taskloop simd collapse(2) reduction (+:w) default(none) firstprivate(a) + for (j = 0; j < 1; j++) + for (i = 0; i < 64; ++i) + w += a[i]; +} --- gcc/testsuite/c-c++-common/gomp/master-combined-2.c.jj 2018-10-18 13:21:20.721093348 +0200 +++ gcc/testsuite/c-c++-common/gomp/master-combined-2.c 2018-10-18 13:21:16.101169926 +0200 @@ -0,0 +1,13 @@ +void +foo (int *a) +{ + int i, r = 0, s = 0; + #pragma omp taskgroup task_reduction(+:r) + #pragma omp parallel master taskloop in_reduction(+:r) /* { dg-error "'in_reduction' is not valid for '#pragma omp parallel master taskloop'" } */ + for (i = 0; i < 64; i++) + r += a[i]; + #pragma omp taskgroup task_reduction(+:s) + #pragma omp parallel master taskloop simd in_reduction(+:s) /* { dg-error "'in_reduction' is not valid for '#pragma omp parallel master taskloop simd'" } */ + for (i = 0; i < 64; i++) + s += a[i]; +} --- libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c.jj 2018-10-18 14:12:20.785378818 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/master-combined-1.c 2018-10-18 15:57:08.544298267 +0200 @@ -0,0 +1,66 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-std=c99" { target c } } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include <omp.h> +#include <stdlib.h> + +#define N 64 + +int +main () +{ + int p, *q, i, l; + int a[N]; + q = a; + #pragma omp parallel master num_threads(4) private (p) shared(a) + { + int i; + p = omp_get_thread_num (); + if (p != 0) + abort (); + #pragma omp taskloop nogroup + for (i = 0; i < N; ++i) + { + if (omp_get_thread_num () >= 4) + abort (); + a[i] = i; + } + } + #pragma omp parallel num_threads(4) + { + #pragma omp master taskloop lastprivate (i, l) firstprivate (q) + for (i = 0; i != N; i = i + 1) + l = q[i]; + } + if (i != N || l != N - 1) + abort (); + #pragma omp parallel master taskloop num_threads(4) \ + lastprivate (i, l) firstprivate (q) + for (i = 0; i < N - 5; i += 2) + if (q[i] != i) + abort (); + else + l = q[i]; + if (i != N - 4 || l != N - 6) + abort (); + #pragma omp parallel master taskloop simd num_threads(4) + for (i = 0; i < N; i++) + a[i] = 2 * a[i]; + if (i != N) + abort (); + #pragma omp parallel num_threads(4) + { + int j; + #pragma omp master taskloop simd collapse(2) + for (i = 0; i < 2; i += 2) + for (j = 0; j < N; j++) + a[j] = a[j] + 1; + } + for (i = 0; i < N; i++) + if (a[i] != 2 * i + 1) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c.jj 2018-10-18 13:47:15.947313944 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-3.c 2018-10-18 13:49:18.531282016 +0200 @@ -0,0 +1,46 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-std=c99" { target c } } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#define N 1024 +long int u[N], m, n; + +__attribute__((noipa)) void +foo (void) +{ + int i; + #pragma omp taskloop simd reduction (+:m) grainsize (64) + for (i = 0; i < N; ++i) + m += u[i]; +} + +__attribute__((noipa)) void +bar (int x) +{ + int i; + #pragma omp taskloop simd in_reduction (+:n) grainsize (64) nogroup + for (i = (x & 1) * (N / 2); i < (x & 1) * (N / 2) + (N / 2); i++) + n += 2 * u[i]; +} + +int +main () +{ + int i; + for (i = 0; i < N; ++i) + u[i] = i; + #pragma omp parallel master + { + foo (); + #pragma omp taskgroup task_reduction (+:n) + { + bar (0); + bar (1); + } + } + if (m != (long)(N - 1) * (N / 2) || n != (long)(N - 1) * N) + __builtin_abort (); + return 0; +} --- libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c.jj 2018-10-18 16:04:26.615045556 +0200 +++ libgomp/testsuite/libgomp.c-c++-common/taskloop-reduction-4.c 2018-10-18 17:31:19.462015638 +0200 @@ -0,0 +1,65 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-std=c99" { target c } } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include <omp.h> +#include <stdlib.h> + +#define N 1024 +long int u[N], m, n, o; + +__attribute__((noipa)) void +foo (void) +{ + int i = -1; + #pragma omp master taskloop simd reduction (+:m) grainsize (64) + for (i = 0; i < N; ++i) + m += u[i]; + if (i != (omp_get_thread_num () ? -1 : N)) + abort (); +} + +__attribute__((noipa)) void +bar (int x) +{ + int i = -1; + #pragma omp master taskloop simd in_reduction (+:n) grainsize (64) + for (i = (x & 1) * (N / 2); i < (x & 1) * (N / 2) + (N / 2); i++) + n += 2 * u[i]; + if (i != (omp_get_thread_num () ? -1 : (x & 1) * (N / 2) + (N / 2))) + abort (); +} + +__attribute__((noipa)) void +baz (void) +{ + int i; + #pragma omp parallel master taskloop simd reduction (+:o) grainsize (64) + for (i = 0; i < N; ++i) + o += u[i]; + if (i != N) + abort (); +} + +int +main () +{ + int i; + for (i = 0; i < N; ++i) + u[i] = i; + #pragma omp parallel + { + foo (); + #pragma omp taskgroup task_reduction (+:n) + { + bar (0); + bar (1); + } + } + baz (); + if (m != (long)(N - 1) * (N / 2) || n != (long)(N - 1) * N || o != m) + abort (); + return 0; +} Jakub