+2018-10-18 Jakub Jelinek <jakub@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.
+
2018-10-16 Jakub Jelinek <jakub@redhat.com>
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE__REDUCTEMP_.
+2018-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * c-omp.c (c_omp_split_clauses): Add support for combined
+ #pragma omp parallel master and
+ #pragma omp {,parallel }master taskloop{, simd} constructs.
+
2018-10-16 Jakub Jelinek <jakub@redhat.com>
* c-omp.c (c_omp_split_clauses) <case OMP_CLAUSE_IN_REDUCTION>: For
}
/* 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
{
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]
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:
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)
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}
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
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)
{
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)
{
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
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;
}
}
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))
{
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))
}
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)
{
+2018-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2018-10-17 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_finish_taskloop_clauses): New function.
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
*/
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));
}
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 ();
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)
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))
{
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");
+2018-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2018-10-17 Jakub Jelinek <jakub@redhat.com>
* semantics.c (finish_omp_reduction_clause): Call save_expr for
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));
}
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;
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);
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))
{
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");
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,
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)
" 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
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;
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))
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,
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))
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,
+2018-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2018-10-17 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/gomp/reduction-2.c: New test.
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) \
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 \
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 \
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 \
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])
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++;
}
--- /dev/null
+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'" } */
+ }
+}
--- /dev/null
+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];
+}
--- /dev/null
+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];
+}
+2018-10-18 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2018-10-16 Jakub Jelinek <jakub@redhat.com>
* task.c (GOMP_taskgroup_reduction_register): Add ialias.
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}