aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/c-common.h4
-rw-r--r--gcc/c-family/c-omp.c52
-rw-r--r--gcc/c-family/c-pragma.c1
-rw-r--r--gcc/c-family/c-pragma.h2
-rw-r--r--gcc/c/c-parser.c139
-rw-r--r--gcc/c/c-typeck.c1
-rw-r--r--gcc/cp/parser.c142
-rw-r--r--gcc/cp/pt.c2
-rw-r--r--gcc/cp/semantics.c23
-rw-r--r--gcc/gimple-low.c1
-rw-r--r--gcc/gimple-pretty-print.c33
-rw-r--r--gcc/gimple-walk.c1
-rw-r--r--gcc/gimple.c20
-rw-r--r--gcc/gimple.def4
-rw-r--r--gcc/gimple.h37
-rw-r--r--gcc/gimplify.c31
-rw-r--r--gcc/omp-expand.c3
-rw-r--r--gcc/omp-low.c41
-rw-r--r--gcc/testsuite/c-c++-common/goacc/uninit-if-clause.c9
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clause-dups-1.c3
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clauses-1.c52
-rw-r--r--gcc/testsuite/c-c++-common/gomp/clauses-5.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/masked-1.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/masked-2.c11
-rw-r--r--gcc/testsuite/c-c++-common/gomp/masked-combined-1.c37
-rw-r--r--gcc/testsuite/c-c++-common/gomp/masked-combined-2.c13
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-1.C54
-rw-r--r--gcc/testsuite/g++.dg/gomp/attrs-2.C54
-rw-r--r--gcc/testsuite/g++.dg/gomp/block-11.C18
-rw-r--r--gcc/testsuite/g++.dg/gomp/tpl-masked-1.C21
-rw-r--r--gcc/testsuite/gcc.dg/gomp/nesting-1.c39
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/host_data-tree.f954
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/kernels-tree.f954
-rw-r--r--gcc/tree-core.h3
-rw-r--r--gcc/tree-inline.c7
-rw-r--r--gcc/tree-nested.c5
-rw-r--r--gcc/tree-pretty-print.c12
-rw-r--r--gcc/tree.c3
-rw-r--r--gcc/tree.def5
-rw-r--r--gcc/tree.h10
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/masked-1.c83
41 files changed, 969 insertions, 40 deletions
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 65d8c1c..025123a 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1201,7 +1201,8 @@ enum c_omp_clause_split
C_OMP_CLAUSE_SPLIT_COUNT,
C_OMP_CLAUSE_SPLIT_SECTIONS = C_OMP_CLAUSE_SPLIT_FOR,
C_OMP_CLAUSE_SPLIT_TASKLOOP = C_OMP_CLAUSE_SPLIT_FOR,
- C_OMP_CLAUSE_SPLIT_LOOP = C_OMP_CLAUSE_SPLIT_FOR
+ C_OMP_CLAUSE_SPLIT_LOOP = C_OMP_CLAUSE_SPLIT_FOR,
+ C_OMP_CLAUSE_SPLIT_MASKED = C_OMP_CLAUSE_SPLIT_DISTRIBUTE
};
enum c_omp_region_type
@@ -1215,6 +1216,7 @@ enum c_omp_region_type
};
extern tree c_finish_omp_master (location_t, tree);
+extern tree c_finish_omp_masked (location_t, tree, tree);
extern tree c_finish_omp_taskgroup (location_t, tree, tree);
extern tree c_finish_omp_critical (location_t, tree, tree, tree);
extern tree c_finish_omp_ordered (location_t, tree, tree);
diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c
index e70974d..54eba61 100644
--- a/gcc/c-family/c-omp.c
+++ b/gcc/c-family/c-omp.c
@@ -86,6 +86,20 @@ c_finish_omp_master (location_t loc, tree stmt)
return t;
}
+/* Complete a #pragma omp masked construct. BODY is the structured-block
+ that follows the pragma. LOC is the location of the #pragma. */
+
+tree
+c_finish_omp_masked (location_t loc, tree body, tree clauses)
+{
+ tree stmt = make_node (OMP_MASKED);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_MASKED_BODY (stmt) = body;
+ OMP_MASKED_CLAUSES (stmt) = clauses;
+ SET_EXPR_LOCATION (stmt, loc);
+ return add_stmt (stmt);
+}
+
/* Complete a #pragma omp taskgroup construct. BODY is the structured-block
that follows the pragma. LOC is the location of the #pragma. */
@@ -1542,11 +1556,16 @@ c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses,
#pragma omp distribute parallel for simd
#pragma omp distribute simd
#pragma omp for simd
+ #pragma omp masked taskloop
+ #pragma omp masked taskloop simd
#pragma omp master taskloop
#pragma omp master taskloop simd
#pragma omp parallel for
#pragma omp parallel for simd
#pragma omp parallel loop
+ #pragma omp parallel masked
+ #pragma omp parallel masked taskloop
+ #pragma omp parallel masked taskloop simd
#pragma omp parallel master
#pragma omp parallel master taskloop
#pragma omp parallel master taskloop simd
@@ -1651,6 +1670,9 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
case OMP_CLAUSE_BIND:
s = C_OMP_CLAUSE_SPLIT_LOOP;
break;
+ case OMP_CLAUSE_FILTER:
+ s = C_OMP_CLAUSE_SPLIT_MASKED;
+ break;
/* Duplicate this to all of taskloop, distribute, for, simd and
loop. */
case OMP_CLAUSE_COLLAPSE:
@@ -1700,10 +1722,10 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
else
s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE;
break;
- /* 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. */
+ /* Private clause is supported on all constructs but master/masked,
+ it is enough to put it on the innermost one other than
+ master/masked. For #pragma omp {for,sections} put it on parallel
+ though, as that's what we did for OpenMP 3.1. */
case OMP_CLAUSE_PRIVATE:
switch (code)
{
@@ -1713,14 +1735,15 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
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_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break;
case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break;
case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break;
default: gcc_unreachable ();
}
break;
/* Firstprivate clause is supported on all constructs but
- simd, master and loop. Put it on the outermost of those and
- duplicate on teams and parallel. */
+ simd, master, masked and loop. 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)
@@ -1773,7 +1796,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
else if ((mask & (OMP_CLAUSE_MASK_1
<< PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
/* This must be
- #pragma omp parallel master taskloop{, simd}. */
+ #pragma omp parallel mas{ked,ter} taskloop{, simd}. */
s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
else
/* This must be
@@ -1805,9 +1828,10 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
else if ((mask & (OMP_CLAUSE_MASK_1
<< PRAGMA_OMP_CLAUSE_NOGROUP)) != 0)
{
- /* This must be #pragma omp {,{,parallel }master }taskloop simd
+ /* This must be
+ #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd
or
- #pragma omp {,parallel }master taskloop. */
+ #pragma omp {,parallel }mas{ked,ter} taskloop. */
gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP);
s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
}
@@ -2044,7 +2068,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
}
else if (code == OMP_SECTIONS
|| code == OMP_PARALLEL
- || code == OMP_MASTER)
+ || code == OMP_MASTER
+ || code == OMP_MASKED)
s = C_OMP_CLAUSE_SPLIT_PARALLEL;
else if (code == OMP_TASKLOOP)
s = C_OMP_CLAUSE_SPLIT_TASKLOOP;
@@ -2455,7 +2480,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE);
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0)
gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE);
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
+ if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0
+ && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0)
gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE);
if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0)
gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE);
@@ -2975,8 +3001,8 @@ static const struct c_omp_directive omp_directives[] = {
C_OMP_DIR_STANDALONE, false }, */
{ "loop", nullptr, nullptr, PRAGMA_OMP_LOOP,
C_OMP_DIR_CONSTRUCT, true },
- /* { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
- C_OMP_DIR_CONSTRUCT, true }, */
+ { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED,
+ C_OMP_DIR_CONSTRUCT, true },
{ "master", nullptr, nullptr, PRAGMA_OMP_MASTER,
C_OMP_DIR_CONSTRUCT, true },
/* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE,
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index f46b5b9..b466a27 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1343,6 +1343,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = {
{ "distribute", PRAGMA_OMP_DISTRIBUTE },
{ "for", PRAGMA_OMP_FOR },
{ "loop", PRAGMA_OMP_LOOP },
+ { "masked", PRAGMA_OMP_MASKED },
{ "master", PRAGMA_OMP_MASTER },
{ "ordered", PRAGMA_OMP_ORDERED },
{ "parallel", PRAGMA_OMP_PARALLEL },
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index abd6667..b7ec6e5 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -57,6 +57,7 @@ enum pragma_kind {
PRAGMA_OMP_FLUSH,
PRAGMA_OMP_FOR,
PRAGMA_OMP_LOOP,
+ PRAGMA_OMP_MASKED,
PRAGMA_OMP_MASTER,
PRAGMA_OMP_ORDERED,
PRAGMA_OMP_PARALLEL,
@@ -104,6 +105,7 @@ enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_DEVICE,
PRAGMA_OMP_CLAUSE_DEVICE_TYPE,
PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
+ PRAGMA_OMP_CLAUSE_FILTER,
PRAGMA_OMP_CLAUSE_FINAL,
PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
PRAGMA_OMP_CLAUSE_FOR,
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 195c137..ca6e56a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12696,7 +12696,9 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
break;
case 'f':
- if (!strcmp ("final", p))
+ if (!strcmp ("filter", p))
+ result = PRAGMA_OMP_CLAUSE_FILTER;
+ else if (!strcmp ("final", p))
result = PRAGMA_OMP_CLAUSE_FINAL;
else if (!strcmp ("finalize", p))
result = PRAGMA_OACC_CLAUSE_FINALIZE;
@@ -13948,6 +13950,38 @@ c_parser_omp_clause_hint (c_parser *parser, tree list)
return list;
}
+/* OpenMP 5.1:
+ filter ( integer-expression ) */
+
+static tree
+c_parser_omp_clause_filter (c_parser *parser, tree list)
+{
+ location_t hint_loc = c_parser_peek_token (parser)->location;
+ matching_parens parens;
+ if (parens.require_open (parser))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ tree c, t = expr.value;
+ t = c_fully_fold (t, false, NULL);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ c_parser_error (parser, "expected integer expression");
+ return list;
+ }
+ parens.skip_until_found_close (parser);
+ check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter");
+
+ c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
+ OMP_CLAUSE_FILTER_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+ }
+
+ return list;
+}
+
/* OpenMP 4.5:
defaultmap ( tofrom : scalar )
@@ -16410,6 +16444,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_detach (parser, clauses);
c_name = "detach";
break;
+ case PRAGMA_OMP_CLAUSE_FILTER:
+ clauses = c_parser_omp_clause_filter (parser, clauses);
+ c_name = "filter";
+ break;
case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
clauses = c_parser_omp_clause_firstprivate (parser, clauses);
c_name = "firstprivate";
@@ -18975,6 +19013,70 @@ c_parser_omp_master (location_t loc, c_parser *parser,
if_p));
}
+/* OpenMP 5.1:
+ # pragma omp masked masked-clauses new-line
+ structured-block
+
+ LOC is the location of the #pragma token.
+*/
+
+#define OMP_MASKED_CLAUSE_MASK \
+ (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
+
+static tree
+c_parser_omp_masked (location_t loc, c_parser *parser,
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
+{
+ tree block, clauses, ret;
+
+ strcat (p_name, " masked");
+ mask |= OMP_MASKED_CLAUSE_MASK;
+
+ 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_masked (loc, block,
+ cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
+ OMP_MASKED_COMBINED (ret) = 1;
+ return ret;
+ }
+ }
+ 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)
+ {
+ omp_split_clauses (loc, OMP_MASKED, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
+ }
+
+ return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
+ if_p),
+ clauses);
+}
+
/* OpenMP 2.5:
# pragma omp ordered new-line
structured-block
@@ -19237,7 +19339,36 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
else if (c_parser_next_token_is (parser, CPP_NAME))
{
const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (cclauses == NULL && strcmp (p, "master") == 0)
+ if (cclauses == NULL && strcmp (p, "masked") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ cclauses = cclauses_buf;
+
+ c_parser_consume_token (parser);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
+ if_p);
+ block = c_begin_omp_parallel ();
+ tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
+ if_p);
+ stmt = c_finish_omp_parallel (loc,
+ cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
+ block);
+ if (ret == NULL)
+ return ret;
+ /* masked does have just filter clause, but during gimplification
+ isn't represented by a gimplification omp context, so for
+ #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
+ so that
+ #pragma omp parallel masked
+ #pragma omp taskloop simd lastprivate (x)
+ isn't confused with
+ #pragma omp parallel masked taskloop simd lastprivate (x) */
+ if (OMP_MASKED_COMBINED (ret))
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
+ }
+ else if (cclauses == NULL && strcmp (p, "master") == 0)
{
tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
cclauses = cclauses_buf;
@@ -21815,6 +21946,10 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
break;
+ case PRAGMA_OMP_MASKED:
+ strcpy (p_name, "#pragma omp");
+ stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
+ break;
case PRAGMA_OMP_MASTER:
strcpy (p_name, "#pragma omp");
stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index eb5c87d..0c07af61 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -15158,6 +15158,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_THREADS:
case OMP_CLAUSE_SIMD:
case OMP_CLAUSE_HINT:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_DEFAULTMAP:
case OMP_CLAUSE_BIND:
case OMP_CLAUSE_NUM_GANGS:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b7fe4b4..edb69ae 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -36004,7 +36004,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
break;
case 'f':
- if (!strcmp ("final", p))
+ if (!strcmp ("filter", p))
+ result = PRAGMA_OMP_CLAUSE_FILTER;
+ else if (!strcmp ("final", p))
result = PRAGMA_OMP_CLAUSE_FINAL;
else if (!strcmp ("finalize", p))
result = PRAGMA_OACC_CLAUSE_FINALIZE;
@@ -37340,6 +37342,34 @@ cp_parser_omp_clause_hint (cp_parser *parser, tree list, location_t location)
return c;
}
+/* OpenMP 5.1:
+ filter ( integer-expression ) */
+
+static tree
+cp_parser_omp_clause_filter (cp_parser *parser, tree list, location_t location)
+{
+ tree t, c;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ t = cp_parser_assignment_expression (parser);
+
+ if (t == error_mark_node
+ || !parens.require_close (parser))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter", location);
+
+ c = build_omp_clause (location, OMP_CLAUSE_FILTER);
+ OMP_CLAUSE_FILTER_EXPR (c) = t;
+ OMP_CLAUSE_CHAIN (c) = list;
+
+ return c;
+}
+
/* OpenMP 4.5:
defaultmap ( tofrom : scalar )
@@ -39449,6 +39479,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
token->location, false);
c_name = "default";
break;
+ case PRAGMA_OMP_CLAUSE_FILTER:
+ clauses = cp_parser_omp_clause_filter (parser, clauses,
+ token->location);
+ c_name = "filter";
+ break;
case PRAGMA_OMP_CLAUSE_FINAL:
clauses = cp_parser_omp_clause_final (parser, clauses, token->location);
c_name = "final";
@@ -41985,6 +42020,73 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok,
cp_parser_omp_structured_block (parser, if_p));
}
+/* OpenMP 5.1:
+ # pragma omp masked masked-clauses new-line
+ structured-block */
+
+#define OMP_MASKED_CLAUSE_MASK \
+ (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
+
+static tree
+cp_parser_omp_masked (cp_parser *parser, cp_token *pragma_tok,
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
+{
+ tree clauses, sb, ret;
+ unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+ strcat (p_name, " masked");
+ mask |= OMP_MASKED_CLAUSE_MASK;
+
+ 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;
+ ret = c_finish_omp_masked (loc, body,
+ cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
+ OMP_MASKED_COMBINED (ret) = 1;
+ return ret;
+ }
+ }
+ 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);
+ if (cclauses)
+ {
+ cp_omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
+ clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
+ }
+
+ return c_finish_omp_masked (loc,
+ cp_parser_omp_structured_block (parser, if_p),
+ clauses);
+}
+
/* OpenMP 2.5:
# pragma omp ordered new-line
structured-block
@@ -42238,7 +42340,37 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
{
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
- if (cclauses == NULL && strcmp (p, "master") == 0)
+ if (cclauses == NULL && strcmp (p, "masked") == 0)
+ {
+ tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
+ cclauses = cclauses_buf;
+
+ cp_lexer_consume_token (parser->lexer);
+ if (!flag_openmp) /* flag_openmp_simd */
+ return cp_parser_omp_masked (parser, pragma_tok, p_name, mask,
+ cclauses, if_p);
+ block = begin_omp_parallel ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ tree ret = cp_parser_omp_masked (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);
+ if (ret == NULL_TREE)
+ return ret;
+ /* masked does have just filter clause, but during gimplification
+ isn't represented by a gimplification omp context, so for
+ #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
+ so that
+ #pragma omp parallel masked
+ #pragma omp taskloop simd lastprivate (x)
+ isn't confused with
+ #pragma omp parallel masked taskloop simd lastprivate (x) */
+ if (OMP_MASKED_COMBINED (ret))
+ OMP_PARALLEL_COMBINED (stmt) = 1;
+ return stmt;
+ }
+ else if (cclauses == NULL && strcmp (p, "master") == 0)
{
tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
cclauses = cclauses_buf;
@@ -45824,6 +45956,11 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
stmt = cp_parser_omp_loop (parser, pragma_tok, p_name, mask, NULL,
if_p);
break;
+ case PRAGMA_OMP_MASKED:
+ strcpy (p_name, "#pragma omp");
+ stmt = cp_parser_omp_masked (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
+ break;
case PRAGMA_OMP_MASTER:
strcpy (p_name, "#pragma omp");
stmt = cp_parser_omp_master (parser, pragma_tok, p_name, mask, NULL,
@@ -46464,6 +46601,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
case PRAGMA_OMP_DISTRIBUTE:
case PRAGMA_OMP_FOR:
case PRAGMA_OMP_LOOP:
+ case PRAGMA_OMP_MASKED:
case PRAGMA_OMP_MASTER:
case PRAGMA_OMP_PARALLEL:
case PRAGMA_OMP_SECTIONS:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 42ea51c..0870ccd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -17394,6 +17394,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_HINT:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_NUM_GANGS:
case OMP_CLAUSE_NUM_WORKERS:
case OMP_CLAUSE_VECTOR_LENGTH:
@@ -18786,6 +18787,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
break;
case OMP_SECTIONS:
+ case OMP_MASKED:
omp_parallel_combined_clauses = NULL;
/* FALLTHRU */
case OMP_SINGLE:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2e23818..0198d2d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8204,6 +8204,29 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
break;
+ case OMP_CLAUSE_FILTER:
+ t = OMP_CLAUSE_FILTER_EXPR (c);
+ if (t == error_mark_node)
+ remove = true;
+ else if (!type_dependent_expression_p (t)
+ && !INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<filter%> expression must be integral");
+ remove = true;
+ }
+ else
+ {
+ t = mark_rvalue_use (t);
+ if (!processing_template_decl)
+ {
+ t = maybe_constant_value (t);
+ t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
+ }
+ OMP_CLAUSE_FILTER_EXPR (c) = t;
+ }
+ break;
+
case OMP_CLAUSE_IS_DEVICE_PTR:
case OMP_CLAUSE_USE_DEVICE_PTR:
field_ok = (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP;
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index fa7d4de..832d5c3 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -334,6 +334,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index d6e63d6..1bccad1 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1658,6 +1658,35 @@ dump_gimple_omp_taskgroup (pretty_printer *buffer, const gimple *gs,
}
}
+/* Dump a GIMPLE_OMP_MASKED tuple on the pretty_printer BUFFER. */
+
+static void
+dump_gimple_omp_masked (pretty_printer *buffer, const gimple *gs,
+ int spc, dump_flags_t flags)
+{
+ if (flags & TDF_RAW)
+ {
+ dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S>%nCLAUSES <", gs,
+ gimple_omp_body (gs));
+ dump_omp_clauses (buffer, gimple_omp_masked_clauses (gs), spc, flags);
+ dump_gimple_fmt (buffer, spc, flags, " >");
+ }
+ else
+ {
+ pp_string (buffer, "#pragma omp masked");
+ dump_omp_clauses (buffer, gimple_omp_masked_clauses (gs), spc, flags);
+ if (!gimple_seq_empty_p (gimple_omp_body (gs)))
+ {
+ newline_and_indent (buffer, spc + 2);
+ pp_left_brace (buffer);
+ pp_newline (buffer);
+ dump_gimple_seq (buffer, gimple_omp_body (gs), spc + 4, flags);
+ newline_and_indent (buffer, spc + 2);
+ pp_right_brace (buffer);
+ }
+ }
+}
+
/* Dump a GIMPLE_OMP_TARGET tuple on the pretty_printer BUFFER. */
static void
@@ -2722,6 +2751,10 @@ pp_gimple_stmt_1 (pretty_printer *buffer, const gimple *gs, int spc,
dump_gimple_omp_taskgroup (buffer, gs, spc, flags);
break;
+ case GIMPLE_OMP_MASKED:
+ dump_gimple_omp_masked (buffer, gs, spc, flags);
+ break;
+
case GIMPLE_OMP_MASTER:
case GIMPLE_OMP_SECTION:
dump_gimple_omp_block (buffer, gs, spc, flags);
diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c
index 18884c4..9dd2e86 100644
--- a/gcc/gimple-walk.c
+++ b/gcc/gimple-walk.c
@@ -682,6 +682,7 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt,
/* FALL THROUGH. */
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 383da98..23bfc7f 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -1038,6 +1038,21 @@ gimple_build_omp_master (gimple_seq body)
return p;
}
+/* Build a GIMPLE_OMP_MASKED statement.
+
+ BODY is the sequence of statements to be executed by the selected thread(s). */
+
+gimple *
+gimple_build_omp_masked (gimple_seq body, tree clauses)
+{
+ gimple *p = gimple_alloc (GIMPLE_OMP_MASKED, 0);
+ gimple_omp_masked_set_clauses (p, clauses);
+ if (body)
+ gimple_omp_set_body (p, body);
+
+ return p;
+}
+
/* Build a GIMPLE_OMP_TASKGROUP statement.
BODY is the sequence of statements to be executed by the taskgroup
@@ -2031,6 +2046,11 @@ gimple_copy (gimple *stmt)
gimple_omp_set_body (copy, new_seq);
break;
+ case GIMPLE_OMP_MASKED:
+ t = unshare_expr (gimple_omp_masked_clauses (stmt));
+ gimple_omp_masked_set_clauses (copy, t);
+ goto copy_omp_body;
+
case GIMPLE_TRANSACTION:
new_seq = gimple_seq_copy (gimple_transaction_body (
as_a <gtransaction *> (stmt)));
diff --git a/gcc/gimple.def b/gcc/gimple.def
index 0ac0cf7..e66546c 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -279,6 +279,10 @@ DEFGSCODE(GIMPLE_OMP_FOR, "gimple_omp_for", GSS_OMP_FOR)
BODY is the sequence of statements to execute in the master section. */
DEFGSCODE(GIMPLE_OMP_MASTER, "gimple_omp_master", GSS_OMP)
+/* GIMPLE_OMP_MASKED <BODY, CLAUSES> represents #pragma omp masked.
+ BODY is the sequence of statements to execute in the masked section. */
+DEFGSCODE(GIMPLE_OMP_MASKED, "gimple_omp_masked", GSS_OMP_SINGLE_LAYOUT)
+
/* GIMPLE_OMP_TASKGROUP <BODY, CLAUSES> represents #pragma omp taskgroup.
BODY is the sequence of statements inside the taskgroup section.
CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */
diff --git a/gcc/gimple.h b/gcc/gimple.h
index 31d7dd0..7fd483d 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -1560,6 +1560,7 @@ gomp_task *gimple_build_omp_task (gimple_seq, tree, tree, tree, tree,
tree, tree);
gimple *gimple_build_omp_section (gimple_seq);
gimple *gimple_build_omp_master (gimple_seq);
+gimple *gimple_build_omp_masked (gimple_seq, tree);
gimple *gimple_build_omp_taskgroup (gimple_seq, tree);
gomp_continue *gimple_build_omp_continue (tree, tree);
gomp_ordered *gimple_build_omp_ordered (gimple_seq, tree);
@@ -1836,6 +1837,7 @@ gimple_has_substatements (gimple *g)
case GIMPLE_TRY:
case GIMPLE_OMP_FOR:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SECTION:
@@ -5205,6 +5207,40 @@ gimple_omp_taskgroup_set_clauses (gimple *gs, tree clauses)
}
+/* Return the clauses associated with OMP_MASTER statement GS. */
+
+static inline tree
+gimple_omp_masked_clauses (const gimple *gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_MASKED);
+ return
+ static_cast <const gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+
+/* Return a pointer to the clauses associated with OMP masked statement
+ GS. */
+
+static inline tree *
+gimple_omp_masked_clauses_ptr (gimple *gs)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_MASKED);
+ return &static_cast <gimple_statement_omp_single_layout *> (gs)->clauses;
+}
+
+
+/* Set CLAUSES to be the clauses associated with OMP masked statement
+ GS. */
+
+static inline void
+gimple_omp_masked_set_clauses (gimple *gs, tree clauses)
+{
+ GIMPLE_CHECK (gs, GIMPLE_OMP_MASKED);
+ static_cast <gimple_statement_omp_single_layout *> (gs)->clauses
+ = clauses;
+}
+
+
/* Return the kind of the OMP_FOR statemement G. */
static inline int
@@ -6493,6 +6529,7 @@ gimple_return_set_retval (greturn *gs, tree retval)
case GIMPLE_OMP_TEAMS: \
case GIMPLE_OMP_SECTION: \
case GIMPLE_OMP_MASTER: \
+ case GIMPLE_OMP_MASKED: \
case GIMPLE_OMP_TASKGROUP: \
case GIMPLE_OMP_ORDERED: \
case GIMPLE_OMP_CRITICAL: \
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 21ff32e..eadbf83 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -5632,6 +5632,7 @@ is_gimple_stmt (tree t)
case OMP_SECTION:
case OMP_SINGLE:
case OMP_MASTER:
+ case OMP_MASKED:
case OMP_TASKGROUP:
case OMP_ORDERED:
case OMP_CRITICAL:
@@ -10102,6 +10103,7 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_PRIORITY:
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_HINT:
case OMP_CLAUSE_ASYNC:
case OMP_CLAUSE_WAIT:
@@ -10110,9 +10112,20 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_VECTOR_LENGTH:
case OMP_CLAUSE_WORKER:
case OMP_CLAUSE_VECTOR:
- if (gimplify_expr (&OMP_CLAUSE_OPERAND (c, 0), pre_p, NULL,
- is_gimple_val, fb_rvalue) == GS_ERROR)
- remove = true;
+ if (OMP_CLAUSE_OPERAND (c, 0)
+ && !is_gimple_min_invariant (OMP_CLAUSE_OPERAND (c, 0)))
+ {
+ if (error_operand_p (OMP_CLAUSE_OPERAND (c, 0)))
+ {
+ remove = true;
+ break;
+ }
+ /* All these clauses care about value, not a particular decl,
+ so try to force it into a SSA_NAME or fresh temporary. */
+ OMP_CLAUSE_OPERAND (c, 0)
+ = get_initialized_tmp_var (OMP_CLAUSE_OPERAND (c, 0),
+ pre_p, NULL, true);
+ }
break;
case OMP_CLAUSE_GANG:
@@ -11222,6 +11235,7 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p,
case OMP_CLAUSE_NOGROUP:
case OMP_CLAUSE_THREADS:
case OMP_CLAUSE_SIMD:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_HINT:
case OMP_CLAUSE_DEFAULTMAP:
case OMP_CLAUSE_ORDER:
@@ -14766,6 +14780,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_SECTION:
case OMP_MASTER:
+ case OMP_MASKED:
case OMP_ORDERED:
case OMP_CRITICAL:
case OMP_SCAN:
@@ -14788,6 +14803,15 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case OMP_ORDERED:
g = gimplify_omp_ordered (*expr_p, body);
break;
+ case OMP_MASKED:
+ gimplify_scan_omp_clauses (&OMP_MASKED_CLAUSES (*expr_p),
+ pre_p, ORT_WORKSHARE, OMP_MASKED);
+ gimplify_adjust_omp_clauses (pre_p, body,
+ &OMP_MASKED_CLAUSES (*expr_p),
+ OMP_MASKED);
+ g = gimple_build_omp_masked (body,
+ OMP_MASKED_CLAUSES (*expr_p));
+ break;
case OMP_CRITICAL:
gimplify_scan_omp_clauses (&OMP_CRITICAL_CLAUSES (*expr_p),
pre_p, ORT_WORKSHARE, OMP_CRITICAL);
@@ -15161,6 +15185,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
&& code != OMP_FOR
&& code != OACC_LOOP
&& code != OMP_MASTER
+ && code != OMP_MASKED
&& code != OMP_TASKGROUP
&& code != OMP_ORDERED
&& code != OMP_PARALLEL
diff --git a/gcc/omp-expand.c b/gcc/omp-expand.c
index 9fd1c65..1d4b39e 100644
--- a/gcc/omp-expand.c
+++ b/gcc/omp-expand.c
@@ -8460,6 +8460,7 @@ expand_omp_synch (struct omp_region *region)
si = gsi_last_nondebug_bb (entry_bb);
gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
|| gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
+ || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASKED
|| gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
|| gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
|| gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
@@ -9947,6 +9948,7 @@ expand_omp (struct omp_region *region)
}
/* FALLTHRU */
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_TEAMS:
@@ -10266,6 +10268,7 @@ omp_make_gimple_edges (basic_block bb, struct omp_region **region,
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_TEAMS:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_SECTION:
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 926087d..22ba579 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1466,6 +1466,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE_NUM_WORKERS:
case OMP_CLAUSE_VECTOR_LENGTH:
case OMP_CLAUSE_DETACH:
+ case OMP_CLAUSE_FILTER:
if (ctx->outer)
scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
break;
@@ -1868,6 +1869,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
case OMP_CLAUSE__SIMT_:
case OMP_CLAUSE_IF_PRESENT:
case OMP_CLAUSE_FINALIZE:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE__CONDTEMP_:
break;
@@ -3426,6 +3428,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_CRITICAL:
if (is_gimple_call (stmt))
@@ -3436,14 +3439,15 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
error_at (gimple_location (stmt),
"barrier region may not be closely nested inside "
"of work-sharing, %<loop%>, %<critical%>, "
- "%<ordered%>, %<master%>, explicit %<task%> or "
- "%<taskloop%> region");
+ "%<ordered%>, %<master%>, %<masked%>, explicit "
+ "%<task%> or %<taskloop%> region");
return false;
}
error_at (gimple_location (stmt),
"work-sharing region may not be closely nested inside "
"of work-sharing, %<loop%>, %<critical%>, %<ordered%>, "
- "%<master%>, explicit %<task%> or %<taskloop%> region");
+ "%<master%>, %<masked%>, explicit %<task%> or "
+ "%<taskloop%> region");
return false;
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TEAMS:
@@ -3458,6 +3462,7 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
}
break;
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
for (; ctx != NULL; ctx = ctx->outer)
switch (gimple_code (ctx->stmt))
{
@@ -3470,9 +3475,11 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_TASK:
error_at (gimple_location (stmt),
- "%<master%> region may not be closely nested inside "
+ "%qs region may not be closely nested inside "
"of work-sharing, %<loop%>, explicit %<task%> or "
- "%<taskloop%> region");
+ "%<taskloop%> region",
+ gimple_code (stmt) == GIMPLE_OMP_MASTER
+ ? "master" : "masked");
return false;
case GIMPLE_OMP_PARALLEL:
case GIMPLE_OMP_TEAMS:
@@ -4079,6 +4086,12 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
scan_omp (gimple_omp_body_ptr (stmt), ctx);
break;
+ case GIMPLE_OMP_MASKED:
+ ctx = new_omp_context (stmt, ctx);
+ scan_sharing_clauses (gimple_omp_masked_clauses (stmt), ctx);
+ scan_omp (gimple_omp_body_ptr (stmt), ctx);
+ break;
+
case GIMPLE_OMP_TASKGROUP:
ctx = new_omp_context (stmt, ctx);
scan_sharing_clauses (gimple_omp_taskgroup_clauses (stmt), ctx);
@@ -8675,7 +8688,7 @@ lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
}
-/* Expand code for an OpenMP master directive. */
+/* Expand code for an OpenMP master or masked directive. */
static void
lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
@@ -8685,9 +8698,20 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
gbind *bind;
location_t loc = gimple_location (stmt);
gimple_seq tseq;
+ tree filter = integer_zero_node;
push_gimplify_context ();
+ if (gimple_code (stmt) == GIMPLE_OMP_MASKED)
+ {
+ filter = omp_find_clause (gimple_omp_masked_clauses (stmt),
+ OMP_CLAUSE_FILTER);
+ if (filter)
+ filter = fold_convert (integer_type_node,
+ OMP_CLAUSE_FILTER_EXPR (filter));
+ else
+ filter = integer_zero_node;
+ }
block = make_node (BLOCK);
bind = gimple_build_bind (NULL, NULL, block);
gsi_replace (gsi_p, bind, true);
@@ -8695,7 +8719,7 @@ lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
x = build_call_expr_loc (loc, bfn_decl, 0);
- x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
+ x = build2 (EQ_EXPR, boolean_type_node, x, filter);
x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
tseq = NULL;
gimplify_and_add (x, &tseq);
@@ -13869,6 +13893,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
lower_omp_single (gsi_p, ctx);
break;
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
ctx = maybe_lookup_ctx (stmt);
gcc_assert (ctx);
lower_omp_master (gsi_p, ctx);
@@ -14246,6 +14271,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
@@ -14307,6 +14333,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
case GIMPLE_OMP_CRITICAL:
diff --git a/gcc/testsuite/c-c++-common/goacc/uninit-if-clause.c b/gcc/testsuite/c-c++-common/goacc/uninit-if-clause.c
index 7f78d72..683ac1b 100644
--- a/gcc/testsuite/c-c++-common/goacc/uninit-if-clause.c
+++ b/gcc/testsuite/c-c++-common/goacc/uninit-if-clause.c
@@ -1,6 +1,5 @@
/* { dg-do compile } */
/* { dg-additional-options "-Wuninitialized" } */
-/* { dg-excess-errors "PR70392" { xfail c++ } } */
#include <stdbool.h>
@@ -14,25 +13,25 @@ main (void)
#pragma acc parallel if(l) /* { dg-warning "is used uninitialized" } */
;
- #pragma acc parallel if(b) /* { dg-warning "is used uninitialized" "" { xfail c++ } } */
+ #pragma acc parallel if(b) /* { dg-warning "is used uninitialized" } */
;
#pragma acc kernels if(l2) /* { dg-warning "is used uninitialized" } */
;
- #pragma acc kernels if(b2) /* { dg-warning "is used uninitialized" "" { xfail c++ } } */
+ #pragma acc kernels if(b2) /* { dg-warning "is used uninitialized" } */
;
#pragma acc data if(l3) /* { dg-warning "is used uninitialized" } */
;
- #pragma acc data if(b3) /* { dg-warning "is used uninitialized" "" { xfail c++ } } */
+ #pragma acc data if(b3) /* { dg-warning "is used uninitialized" } */
;
#pragma acc update if(l4) self(i) /* { dg-warning "is used uninitialized" } */
;
- #pragma acc update if(b4) self(i2) /* { dg-warning "is used uninitialized" "" { xfail c++ } } */
+ #pragma acc update if(b4) self(i2) /* { dg-warning "is used uninitialized" } */
;
}
diff --git a/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c b/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
index 3dde058..7b71ad3 100644
--- a/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/clause-dups-1.c
@@ -203,7 +203,8 @@ f1 (int *p)
i = p[0]++;
#pragma omp atomic capture hint(0) hint (0) /* { dg-error "too many 'hint' clauses" } */
i = p[0]++;
-
+ #pragma omp masked filter (0) filter (0) /* { dg-error "too many 'filter' clauses" } */
+ f0 ();
}
#pragma omp declare simd simdlen (4) simdlen (4) /* { dg-error "too many 'simdlen' clauses" } */
diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-1.c b/gcc/testsuite/c-c++-common/gomp/clauses-1.c
index 682442af..378c7bf 100644
--- a/gcc/testsuite/c-c++-common/gomp/clauses-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/clauses-1.c
@@ -273,6 +273,10 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) \
num_threads (nth) proc_bind(spread) copyin(t) allocate (f)
;
+ #pragma omp parallel masked \
+ private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r) \
+ num_threads (nth) proc_bind(spread) copyin(t) allocate (f) filter (d)
+ ;
#pragma omp taskgroup task_reduction (+:r2) allocate (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) \
@@ -280,23 +284,47 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
for (int i = 0; i < 64; i++)
ll++;
#pragma omp taskgroup task_reduction (+:r2) allocate (r2)
+ #pragma omp masked 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) allocate (f) filter (d)
+ for (int i = 0; i < 64; i++)
+ ll++;
+ #pragma omp taskgroup task_reduction (+:r2) allocate (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) \
order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
+ #pragma omp taskgroup task_reduction (+:r2) allocate (r2)
+ #pragma omp masked 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) \
+ order(concurrent) allocate (f) filter (d)
+ 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) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
+ #pragma omp parallel masked 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) allocate (f) filter (d)
+ 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) \
order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
+ #pragma omp parallel masked 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) \
+ order(concurrent) allocate (f) filter (d)
+ for (int i = 0; i < 64; i++)
+ ll++;
#pragma omp taskgroup task_reduction (+:r2) allocate (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) \
@@ -304,23 +332,47 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
for (int i = 0; i < 64; i++)
ll++;
#pragma omp taskgroup task_reduction (+:r2) allocate (r2)
+ #pragma omp mastked 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) filter (d)
+ for (int i = 0; i < 64; i++)
+ ll++;
+ #pragma omp taskgroup task_reduction (+:r2) allocate (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) \
order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
+ #pragma omp taskgroup task_reduction (+:r2) allocate (r2)
+ #pragma omp masked 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) \
+ order(concurrent) allocate (f) filter (d)
+ 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) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
+ #pragma omp parallel masked 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) allocate (f) filter (d)
+ 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) \
order(concurrent) allocate (f)
for (int i = 0; i < 64; i++)
ll++;
+ #pragma omp parallel masked 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) \
+ order(concurrent) allocate (f) filter (d)
+ for (int i = 0; i < 64; i++)
+ ll++;
#pragma omp loop bind(thread) order(concurrent) \
private (p) lastprivate (l) collapse(1) reduction(+:r)
for (l = 0; l < 64; ++l)
diff --git a/gcc/testsuite/c-c++-common/gomp/clauses-5.c b/gcc/testsuite/c-c++-common/gomp/clauses-5.c
index 35e16f0..87e53a9 100644
--- a/gcc/testsuite/c-c++-common/gomp/clauses-5.c
+++ b/gcc/testsuite/c-c++-common/gomp/clauses-5.c
@@ -49,4 +49,6 @@ foo (int *p)
;
#pragma omp critical (baz) hint (2, 3) /* { dg-error "expected" } */
;
+ #pragma omp masked filter (3, 4) /* { dg-error "expected" } */
+ ;
}
diff --git a/gcc/testsuite/c-c++-common/gomp/masked-1.c b/gcc/testsuite/c-c++-common/gomp/masked-1.c
new file mode 100644
index 0000000..36c2e49
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/masked-1.c
@@ -0,0 +1,23 @@
+void bar (void);
+
+void
+foo (int x, int *a)
+{
+ #pragma omp masked
+ bar ();
+ #pragma omp masked filter (0)
+ bar ();
+ #pragma omp masked filter (7)
+ bar ();
+ #pragma omp masked filter (x)
+ bar ();
+ #pragma omp masked taskloop simd filter (x) grainsize (12) simdlen (4)
+ for (int i = 0; i < 128; i++)
+ a[i] = i;
+ #pragma omp parallel masked filter (x) firstprivate (x)
+ bar ();
+ #pragma omp masked
+ #pragma omp masked filter (0)
+ #pragma omp masked filter (x)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/masked-2.c b/gcc/testsuite/c-c++-common/gomp/masked-2.c
new file mode 100644
index 0000000..7230c82
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/masked-2.c
@@ -0,0 +1,11 @@
+void bar (void);
+struct S { int s; };
+
+void
+foo (float f, struct S s)
+{
+ #pragma omp masked filter (0.0) /* { dg-error "integral|integer" } */
+ bar ();
+ #pragma omp masked filter (s) /* { dg-error "integral|integer" } */
+ bar ();
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/masked-combined-1.c b/gcc/testsuite/c-c++-common/gomp/masked-combined-1.c
new file mode 100644
index 0000000..0b3ff58
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/masked-combined-1.c
@@ -0,0 +1,37 @@
+void bar (int *);
+
+void
+foo (int *a, int f)
+{
+ int i, j, k, u = 0, v = 0, w = 0, x = 0, y = 0, z = 0;
+ #pragma omp parallel masked default(none) private (k) filter (f) firstprivate (f)
+ bar (&k);
+ #pragma omp parallel masked default(none) private (k)
+ bar (&k);
+ #pragma omp parallel default(none) firstprivate(a, f) shared(x, y, z)
+ {
+ #pragma omp masked taskloop reduction (+:x) default(none) firstprivate(a) filter (f)
+ for (i = 0; i < 64; i++)
+ x += a[i];
+ #pragma omp masked taskloop simd reduction (+:y) default(none) firstprivate(a) private (i) filter (f)
+ for (i = 0; i < 64; i++)
+ y += a[i];
+ #pragma omp masked taskloop simd reduction (+:y) default(none) firstprivate(a) private (i)
+ for (i = 0; i < 64; i++)
+ y += a[i];
+ #pragma omp masked taskloop simd collapse(2) reduction (+:z) default(none) firstprivate(a) private (i, j) filter (f)
+ for (j = 0; j < 1; j++)
+ for (i = 0; i < 64; ++i)
+ z += a[i];
+ }
+ #pragma omp parallel masked taskloop reduction (+:u) default(none) firstprivate(a, f) filter (f)
+ for (i = 0; i < 64; i++)
+ u += a[i];
+ #pragma omp parallel masked taskloop simd reduction (+:v) default(none) firstprivate(a, f) filter (f)
+ for (i = 0; i < 64; i++)
+ v += a[i];
+ #pragma omp parallel masked taskloop simd collapse(2) reduction (+:w) default(none) firstprivate(a, f) filter (f)
+ for (j = 0; j < 1; j++)
+ for (i = 0; i < 64; ++i)
+ w += a[i];
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/masked-combined-2.c b/gcc/testsuite/c-c++-common/gomp/masked-combined-2.c
new file mode 100644
index 0000000..1d63969
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/masked-combined-2.c
@@ -0,0 +1,13 @@
+void
+foo (int *a)
+{
+ int i, r = 0, s = 0;
+ #pragma omp taskgroup task_reduction(+:r)
+ #pragma omp parallel masked taskloop in_reduction(+:r) /* { dg-error "'in_reduction' is not valid for '#pragma omp parallel masked taskloop'" } */
+ for (i = 0; i < 64; i++)
+ r += a[i];
+ #pragma omp taskgroup task_reduction(+:s)
+ #pragma omp parallel masked taskloop simd in_reduction(+:s) /* { dg-error "'in_reduction' is not valid for '#pragma omp parallel masked taskloop simd'" } */
+ for (i = 0; i < 64; i++)
+ s += a[i];
+}
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-1.C b/gcc/testsuite/g++.dg/gomp/attrs-1.C
index 5c7007b..c348375 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-1.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-1.C
@@ -348,6 +348,10 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r)
num_threads (nth) proc_bind(spread) copyin(t) allocate (f))]]
;
+ [[omp::directive (parallel masked
+ private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r)
+ num_threads (nth) proc_bind(spread) copyin(t) allocate (f) filter (d))]]
+ ;
[[omp::directive (parallel
private (p) firstprivate (f) if (parallel: i2) default(shared) shared(s) reduction(+:r)
num_threads (nth) proc_bind(spread) copyin(t) allocate (f))]]
@@ -358,7 +362,15 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
reduction(default, +:r) in_reduction(+:r2) allocate (f)))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::sequence (directive (taskgroup task_reduction (+:r2) allocate (r2)),
+ omp::directive (masked 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) allocate (f) filter (d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (master)]];
+ [[omp::directive (masked)]];
+ [[omp::directive (masked filter (d))]];
[[omp::sequence (omp::directive (taskgroup task_reduction (+:r2) allocate (r2)),
directive (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)
@@ -366,23 +378,47 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
order(concurrent) allocate (f)))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::sequence (omp::directive (taskgroup task_reduction (+:r2) allocate (r2)),
+ directive (masked 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)
+ order(concurrent) allocate (f) filter (d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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) allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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) allocate (f) filter (d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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)
order(concurrent) allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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)
+ order(concurrent) allocate (f) filter (d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::sequence (directive (taskgroup task_reduction (+:r2) allocate (r2)),
directive (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++;
+ [[omp::sequence (directive (taskgroup task_reduction (+:r2) allocate (r2)),
+ directive (masked 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) filter (d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::sequence (omp::directive (taskgroup task_reduction (+:r2) allocate (r2)),
omp::directive (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)
@@ -390,17 +426,35 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
order(concurrent) allocate (f)))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::sequence (omp::directive (taskgroup task_reduction (+:r2) allocate (r2)),
+ omp::directive (masked 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)
+ order(concurrent) allocate (f) filter (d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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) allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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) allocate (f) filter (d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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)
order(concurrent) allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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)
+ order(concurrent) allocate (f) filter (d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (loop bind(thread) order(concurrent)
private (p) lastprivate (l) collapse(1) reduction(+:r))]]
for (l = 0; l < 64; ++l)
diff --git a/gcc/testsuite/g++.dg/gomp/attrs-2.C b/gcc/testsuite/g++.dg/gomp/attrs-2.C
index 1b59abd..b2fba21 100644
--- a/gcc/testsuite/g++.dg/gomp/attrs-2.C
+++ b/gcc/testsuite/g++.dg/gomp/attrs-2.C
@@ -348,6 +348,10 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),reduction(+:r),
num_threads (nth),proc_bind(spread),copyin(t),allocate (f))]]
;
+ [[omp::directive (parallel masked,
+ private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),reduction(+:r),
+ num_threads (nth),proc_bind(spread),copyin(t),allocate (f),filter(d))]]
+ ;
[[omp::directive (parallel,
private (p),firstprivate (f),if (parallel: i2),default(shared),shared(s),reduction(+:r),
num_threads (nth),proc_bind(spread),copyin(t),allocate (f))]]
@@ -358,7 +362,15 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
reduction(default, +:r),in_reduction(+:r2),allocate (f)))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[using omp:sequence (directive (taskgroup, task_reduction (+:r2),allocate (r2)),
+ omp::directive (masked 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),allocate (f),filter(d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[using omp:directive (master)]];
+ [[using omp:directive (masked)]];
+ [[using omp:directive (masked,filter(d))]];
[[omp::sequence (omp::directive (taskgroup task_reduction (+:r2),allocate (r2)),
directive (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),
@@ -366,23 +378,47 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
order(concurrent),allocate (f)))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::sequence (omp::directive (taskgroup task_reduction (+:r2),allocate (r2)),
+ directive (masked 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),
+ order(concurrent),allocate (f),filter(d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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),allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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),allocate (f),filter(d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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),
order(concurrent),allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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),
+ order(concurrent),allocate (f),filter(d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::sequence (directive (taskgroup,task_reduction (+:r2),allocate (r2)),
directive (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++;
+ [[omp::sequence (directive (taskgroup,task_reduction (+:r2),allocate (r2)),
+ directive (masked 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),filter(d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::sequence (omp::directive (taskgroup,task_reduction (+:r2),allocate (r2)),
omp::directive (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),
@@ -390,17 +426,35 @@ bar (int d, int m, int i1, int i2, int i3, int p, int *idp, int s,
order(concurrent),allocate (f)))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::sequence (omp::directive (taskgroup,task_reduction (+:r2),allocate (r2)),
+ omp::directive (masked 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),
+ order(concurrent),allocate (f),filter(d)))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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),allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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),allocate (f),filter(d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (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),
order(concurrent),allocate (f))]]
for (int i = 0; i < 64; i++)
ll++;
+ [[omp::directive (parallel masked 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),
+ order(concurrent),allocate (f),filter(d))]]
+ for (int i = 0; i < 64; i++)
+ ll++;
[[omp::directive (loop, bind(thread),order(concurrent),
private (p),lastprivate (l),collapse(1),reduction(+:r))]]
for (l = 0; l < 64; ++l)
diff --git a/gcc/testsuite/g++.dg/gomp/block-11.C b/gcc/testsuite/g++.dg/gomp/block-11.C
index c280006..cf4b0d3 100644
--- a/gcc/testsuite/g++.dg/gomp/block-11.C
+++ b/gcc/testsuite/g++.dg/gomp/block-11.C
@@ -1,3 +1,21 @@
+// { dg-do compile }
+
+void foo()
+{
+ #pragma omp masked
+ {
+ goto bad1; // { dg-message "from here" }
+ }
+
+ #pragma omp masked filter(1)
+ {
+ bad1: // { dg-error "jump" }
+ // { dg-message "exits OpenMP" "" { target *-*-* } .-1 }
+ return; // { dg-error "invalid exit" }
+ }
+}
+
+// { dg-message "error: invalid branch to/from OpenMP structured block" "" { target *-*-* } 7 }
/* PR c++/24516 */
/* { dg-do compile } */
diff --git a/gcc/testsuite/g++.dg/gomp/tpl-masked-1.C b/gcc/testsuite/g++.dg/gomp/tpl-masked-1.C
new file mode 100644
index 0000000..8574861
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/tpl-masked-1.C
@@ -0,0 +1,21 @@
+// { dg-do compile }
+// { dg-options "-fopenmp -fdump-tree-gimple" }
+
+int i;
+
+template <typename T> void f1 (bool p, T t)
+{
+ if (p)
+ {
+ #pragma omp masked filter (t)
+ i++;
+ }
+}
+
+void f2 ()
+{
+ f1<int> (true, 0);
+ f1<long> (true, 0L);
+}
+
+// { dg-final { scan-tree-dump-times "#pragma omp masked" 2 "gimple" } }
diff --git a/gcc/testsuite/gcc.dg/gomp/nesting-1.c b/gcc/testsuite/gcc.dg/gomp/nesting-1.c
index 52fcda7..4a471c8 100644
--- a/gcc/testsuite/gcc.dg/gomp/nesting-1.c
+++ b/gcc/testsuite/gcc.dg/gomp/nesting-1.c
@@ -19,8 +19,10 @@ f1 (void)
}
#pragma omp single /* { dg-error "may not be closely nested" } */
;
- #pragma omp master /* { dg-error "may not be closely nested" } */
- ;
+ #pragma omp master /* { dg-error "may not be closely nested" } */
+ ;
+ #pragma omp masked /* { dg-error "may not be closely nested" } */
+ ;
#pragma omp barrier /* { dg-error "may not be closely nested" } */
}
#pragma omp sections
@@ -50,6 +52,11 @@ f1 (void)
}
#pragma omp sections
{
+ #pragma omp masked /* { dg-error "may not be closely nested" } */
+ ;
+ }
+ #pragma omp sections
+ {
#pragma omp section
;
}
@@ -81,6 +88,9 @@ f1 (void)
#pragma omp section
#pragma omp master /* { dg-error "may not be closely nested" } */
;
+ #pragma omp section
+ #pragma omp masked /* { dg-error "may not be closely nested" } */
+ ;
}
#pragma omp single
{
@@ -97,6 +107,8 @@ f1 (void)
;
#pragma omp master /* { dg-error "may not be closely nested" } */
;
+ #pragma omp masked /* { dg-error "may not be closely nested" } */
+ ;
#pragma omp barrier /* { dg-error "may not be closely nested" } */
}
#pragma omp master
@@ -116,6 +128,23 @@ f1 (void)
;
#pragma omp barrier /* { dg-error "may not be closely nested" } */
}
+ #pragma omp masked filter (1)
+ {
+ #pragma omp for /* { dg-error "may not be closely nested" } */
+ for (j = 0; j < 3; j++)
+ ;
+ #pragma omp sections /* { dg-error "may not be closely nested" } */
+ {
+ ;
+ #pragma omp section
+ ;
+ }
+ #pragma omp single /* { dg-error "may not be closely nested" } */
+ ;
+ #pragma omp master
+ ;
+ #pragma omp barrier /* { dg-error "may not be closely nested" } */
+ }
#pragma omp task
{
#pragma omp for /* { dg-error "may not be closely nested" } */
@@ -131,6 +160,8 @@ f1 (void)
;
#pragma omp master /* { dg-error "may not be closely nested" } */
;
+ #pragma omp masked /* { dg-error "may not be closely nested" } */
+ ;
#pragma omp barrier /* { dg-error "may not be closely nested" } */
}
#pragma omp parallel
@@ -148,6 +179,8 @@ f1 (void)
;
#pragma omp master
;
+ #pragma omp masked
+ ;
#pragma omp barrier
}
}
@@ -171,6 +204,8 @@ f2 (void)
;
#pragma omp master
;
+ #pragma omp masked
+ ;
#pragma omp barrier /* { dg-error "may not be closely nested" } */
}
}
diff --git a/gcc/testsuite/gfortran.dg/goacc/host_data-tree.f95 b/gcc/testsuite/gfortran.dg/goacc/host_data-tree.f95
index 558e800..e575890 100644
--- a/gcc/testsuite/gfortran.dg/goacc/host_data-tree.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/host_data-tree.f95
@@ -12,12 +12,12 @@ program test
!$acc host_data use_device(p) if (p == 42)
! { dg-final { scan-tree-dump-times "(?n)D\\.\[0-9\]+ = \\*p == 42;$" 1 "original" } }
! { dg-final { scan-tree-dump-times "(?n)#pragma acc host_data use_device_ptr\\(p\\) if\\(D\\.\[0-9\]+\\)$" 1 "original" } }
- ! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_host_data use_device_ptr\\(p\\) if\\(D\\.\[0-9\]+\\)$" 1 "gimple" } }
+ ! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_host_data use_device_ptr\\(p\\) if\\((?:D\\.|_)\[0-9\]+\\)$" 1 "gimple" } }
!$acc end host_data
!$acc host_data use_device(p) if_present if (p == 43)
! { dg-final { scan-tree-dump-times "(?n)D\\.\[0-9\]+ = \\*p == 43;$" 1 "original" } }
! { dg-final { scan-tree-dump-times "(?n)#pragma acc host_data use_device_ptr\\(p\\) if\\(D\\.\[0-9\]+\\) if_present$" 1 "original" } }
- ! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_host_data use_device_ptr\\(if_present:p\\) if\\(D\\.\[0-9\]+\\) if_present$" 1 "gimple" } }
+ ! { dg-final { scan-tree-dump-times "(?n)#pragma omp target oacc_host_data use_device_ptr\\(if_present:p\\) if\\((?:D\\.|_)\[0-9\]+\\) if_present$" 1 "gimple" } }
!$acc end host_data
end program test
diff --git a/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95 b/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
index 63ef7e1..688ed0a 100644
--- a/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/kernels-tree.f95
@@ -37,5 +37,5 @@ end program test
! { dg-final { scan-tree-dump-times "map\\(force_deviceptr:u\\)" 1 "original" } }
-! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_data_kernels if\(D\.[0-9]+\)$} 1 "omp_oacc_kernels_decompose" } }
-! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_gang_single num_gangs\(1\) if\(D\.[0-9]+\) async\(-1\)$} 1 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_data_kernels if\((?:D\.|_)[0-9]+\)$} 1 "omp_oacc_kernels_decompose" } }
+! { dg-final { scan-tree-dump-times {(?n)#pragma omp target oacc_parallel_kernels_gang_single num_gangs\(1\) if\((?:D\.|_)[0-9]+\) async\(-1\)$} 1 "omp_oacc_kernels_decompose" } }
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 9a1aa9a..9e901ce 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -476,6 +476,9 @@ enum omp_clause_code {
/* OpenMP clause: bind (binding). */
OMP_CLAUSE_BIND,
+ /* OpenMP clause: filter (integer-expression). */
+ OMP_CLAUSE_FILTER,
+
/* Internally used only clause, holding SIMD uid. */
OMP_CLAUSE__SIMDUID_,
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 8e6cdd3..4ba48e0 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1658,6 +1658,12 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
copy = gimple_build_omp_master (s1);
break;
+ case GIMPLE_OMP_MASKED:
+ s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
+ copy = gimple_build_omp_masked
+ (s1, gimple_omp_masked_clauses (stmt));
+ break;
+
case GIMPLE_OMP_TASKGROUP:
s1 = remap_gimple_seq (gimple_omp_body (stmt), id);
copy = gimple_build_omp_taskgroup
@@ -4544,6 +4550,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights)
case GIMPLE_OMP_TASK:
case GIMPLE_OMP_CRITICAL:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c
index cc59526..d2b3969 100644
--- a/gcc/tree-nested.c
+++ b/gcc/tree-nested.c
@@ -1376,6 +1376,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
case OMP_CLAUSE_HINT:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_NUM_GANGS:
case OMP_CLAUSE_NUM_WORKERS:
case OMP_CLAUSE_VECTOR_LENGTH:
@@ -1785,6 +1786,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op,
@@ -2154,6 +2156,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
case OMP_CLAUSE_HINT:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_NUM_GANGS:
case OMP_CLAUSE_NUM_WORKERS:
case OMP_CLAUSE_VECTOR_LENGTH:
@@ -2518,6 +2521,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
walk_body (convert_local_reference_stmt, convert_local_reference_op,
@@ -3028,6 +3032,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p,
case GIMPLE_OMP_SECTION:
case GIMPLE_OMP_SINGLE:
case GIMPLE_OMP_MASTER:
+ case GIMPLE_OMP_MASKED:
case GIMPLE_OMP_TASKGROUP:
case GIMPLE_OMP_ORDERED:
case GIMPLE_OMP_SCAN:
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 31f886f..5ac4034 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1085,6 +1085,13 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_right_paren (pp);
break;
+ case OMP_CLAUSE_FILTER:
+ pp_string (pp, "filter(");
+ dump_generic_node (pp, OMP_CLAUSE_FILTER_EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
+
case OMP_CLAUSE_DEFAULTMAP:
pp_string (pp, "defaultmap(");
switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (clause))
@@ -3586,6 +3593,11 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
pp_string (pp, "#pragma omp master");
goto dump_omp_body;
+ case OMP_MASKED:
+ pp_string (pp, "#pragma omp masked");
+ dump_omp_clauses (pp, OMP_MASKED_CLAUSES (node), spc, flags);
+ goto dump_omp_body;
+
case OMP_TASKGROUP:
pp_string (pp, "#pragma omp taskgroup");
dump_omp_clauses (pp, OMP_TASKGROUP_CLAUSES (node), spc, flags);
diff --git a/gcc/tree.c b/gcc/tree.c
index e923e67..a0ff794 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -350,6 +350,7 @@ unsigned const char omp_clause_num_ops[] =
0, /* OMP_CLAUSE_DEFAULTMAP */
0, /* OMP_CLAUSE_ORDER */
0, /* OMP_CLAUSE_BIND */
+ 1, /* OMP_CLAUSE_FILTER */
1, /* OMP_CLAUSE__SIMDUID_ */
0, /* OMP_CLAUSE__SIMT_ */
0, /* OMP_CLAUSE_INDEPENDENT */
@@ -438,6 +439,7 @@ const char * const omp_clause_code_name[] =
"defaultmap",
"order",
"bind",
+ "filter",
"_simduid_",
"_simt_",
"independent",
@@ -11126,6 +11128,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
case OMP_CLAUSE_GRAINSIZE:
case OMP_CLAUSE_NUM_TASKS:
case OMP_CLAUSE_HINT:
+ case OMP_CLAUSE_FILTER:
case OMP_CLAUSE_TO_DECLARE:
case OMP_CLAUSE_LINK:
case OMP_CLAUSE_DETACH:
diff --git a/gcc/tree.def b/gcc/tree.def
index eda050b..ff8b5e6 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -1218,6 +1218,11 @@ DEFTREECODE (OMP_SINGLE, "omp_single", tcc_statement, 2)
Operand 1: OMP_SINGLE_CLAUSES: List of clauses. */
DEFTREECODE (OMP_TASKGROUP, "omp_taskgroup", tcc_statement, 2)
+/* OpenMP - #pragma omp masked
+ Operand 0: OMP_MASKED_BODY: Masked section body.
+ Operand 1: OMP_MASKED_CLAUSES: List of clauses. */
+DEFTREECODE (OMP_MASKED, "omp_masked", tcc_statement, 2)
+
/* OpenMP - #pragma omp scan
Operand 0: OMP_SCAN_BODY: Scan body.
Operand 1: OMP_SCAN_CLAUSES: List of clauses. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 972ceb3..c3f302a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1429,6 +1429,9 @@ class auto_suppress_location_wrappers
#define OMP_MASTER_BODY(NODE) TREE_OPERAND (OMP_MASTER_CHECK (NODE), 0)
+#define OMP_MASKED_BODY(NODE) TREE_OPERAND (OMP_MASKED_CHECK (NODE), 0)
+#define OMP_MASKED_CLAUSES(NODE) TREE_OPERAND (OMP_MASKED_CHECK (NODE), 1)
+
#define OMP_TASKGROUP_BODY(NODE) TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 0)
#define OMP_TASKGROUP_CLAUSES(NODE) \
TREE_OPERAND (OMP_TASKGROUP_CHECK (NODE), 1)
@@ -1508,6 +1511,11 @@ class auto_suppress_location_wrappers
#define OMP_MASTER_COMBINED(NODE) \
(OMP_MASTER_CHECK (NODE)->base.private_flag)
+/* True on an OMP_MASKED statement if it represents an explicit
+ combined masked constructs. */
+#define OMP_MASKED_COMBINED(NODE) \
+ (OMP_MASKED_CHECK (NODE)->base.private_flag)
+
/* Memory order for OMP_ATOMIC*. */
#define OMP_ATOMIC_MEMORY_ORDER(NODE) \
(TREE_RANGE_CHECK (NODE, OMP_ATOMIC, \
@@ -1592,6 +1600,8 @@ class auto_suppress_location_wrappers
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_NUM_TASKS), 0)
#define OMP_CLAUSE_HINT_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_HINT), 0)
+#define OMP_CLAUSE_FILTER_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_FILTER), 0)
#define OMP_CLAUSE_GRAINSIZE_EXPR(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_GRAINSIZE),0)
diff --git a/libgomp/testsuite/libgomp.c-c++-common/masked-1.c b/libgomp/testsuite/libgomp.c-c++-common/masked-1.c
new file mode 100644
index 0000000..4ba259c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/masked-1.c
@@ -0,0 +1,83 @@
+#include <omp.h>
+#include <stdlib.h>
+
+void
+foo (int x, int *a)
+{
+ #pragma omp masked
+ {
+ if (omp_get_thread_num () != 0)
+ abort ();
+ a[128]++;
+ }
+ #pragma omp masked filter (0)
+ {
+ if (omp_get_thread_num () != 0)
+ abort ();
+ a[129]++;
+ }
+ #pragma omp masked filter (7)
+ {
+ if (omp_get_thread_num () != 7)
+ abort ();
+ a[130]++;
+ }
+ #pragma omp masked filter (x)
+ {
+ if (omp_get_thread_num () != x)
+ abort ();
+ a[131]++;
+ }
+ #pragma omp masked taskloop simd filter (x) grainsize (12) simdlen (4)
+ for (int i = 0; i < 128; i++)
+ a[i] += i;
+}
+
+int
+main ()
+{
+ int a[136] = {};
+ #pragma omp parallel num_threads (4)
+ foo (4, a);
+ for (int i = 0; i < 128; i++)
+ if (a[i])
+ abort ();
+ if (a[128] != 1 || a[129] != 1 || a[130] || a[131])
+ abort ();
+ #pragma omp parallel num_threads (4)
+ foo (3, a);
+ for (int i = 0; i < 128; i++)
+ if (a[i] != i)
+ abort ();
+ if (a[128] != 2 || a[129] != 2 || a[130] || a[131] != 1)
+ abort ();
+ #pragma omp parallel num_threads (8)
+ foo (8, a);
+ for (int i = 0; i < 128; i++)
+ if (a[i] != i)
+ abort ();
+ if (a[128] != 3 || a[129] != 3 || a[130] != 1 || a[131] != 1)
+ abort ();
+ #pragma omp parallel num_threads (8)
+ foo (6, a);
+ for (int i = 0; i < 128; i++)
+ if (a[i] != 2 * i)
+ abort ();
+ if (a[128] != 4 || a[129] != 4 || a[130] != 2 || a[131] != 2)
+ abort ();
+ for (int i = 0; i < 8; i++)
+ a[i] = 0;
+ /* The filter expression can evaluate to different values in different threads. */
+ #pragma omp parallel masked num_threads (8) filter (omp_get_thread_num () + 1)
+ a[omp_get_thread_num ()]++;
+ for (int i = 0; i < 8; i++)
+ if (a[i])
+ abort ();
+ /* And multiple threads can be filtered. */
+ #pragma omp parallel masked num_threads (8) filter (omp_get_thread_num () & ~1)
+ a[omp_get_thread_num ()]++;
+ for (int i = 0; i < 8; i++)
+ if (a[i] != !(i & 1))
+ abort ();
+ return 0;
+}