The attached patch adds parser support for the 'dyn_groupprivate'
clause to C/C++. (The Fortran support was added before.) However,
for now, the clause is rejected with a 'sorry' in gimplify.cc.
[To do: Supporting it requires that the clause is forwarded to
libgomp and the memory allocation handled there, including two
routines to make it accessible in the target region.]
(Review) comments, remarks, suggestions before I push the patch?
Tobias
OpenMP: C/C++ parser support for dyn_groupprivate
Follow-up to the Fortran patch r16-5633-g26d41e245dbba3, which (besides
other changes) added parser support for the 'dyn_groupprivate' clause to
the target directive.
This commit adds now the parser support to C/C++ and moves the
not-yet-implemented 'sorry' to the early middle end.
gcc/c-family/ChangeLog:
* c-omp.cc (c_omp_split_clauses): Handle
OMP_CLAUSE_DYN_GROUPPRIVATE, sort target clauses
alphabetically.
* c-pragma.h (enum pragma_omp_clause): Add
PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE.
gcc/c/ChangeLog:
* c-parser.cc (c_parser_omp_clause_dyn_groupprivate): New.
(OMP_TARGET_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
sort clauses alphabetically.
(c_parser_omp_clause_name, c_parser_omp_all_clauses):
Handle 'dyn_groupprivate' clause.
* c-typeck.cc (c_finish_omp_clauses): Likewise.
gcc/cp/ChangeLog:
* pt.cc (tsubst_omp_clauses): Handle OMP_CLAUSE_DYN_GROUPPRIVATE.
* semantics.cc (finish_omp_clauses): Likewise.
* parser.cc (cp_parser_omp_clause_dyn_groupprivate): New.
(cp_parser_omp_clause_name, cp_parser_omp_all_clauses):
Handle 'dyn_groupprivate' clause.
(OMP_TARGET_CLAUSE_MASK): Add PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
sort clauses alphabetically.
gcc/fortran/ChangeLog:
* openmp.cc (resolve_omp_clauses): Permit zero with
DYN_GROUPPRIVATE clause.
* trans-openmp.cc (fallback): Generate TREE code
for DYN_GROUPPRIVATE and remove 'sorry'.
gcc/ChangeLog:
* gimplify.cc (gimplify_scan_omp_clauses): Handle
OMP_CLAUSE_DYN_GROUPPRIVATE by printing 'sorry, unimplemented'.
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_DYN_GROUPPRIVATE.
(enum omp_clause_fallback_kind): New.
(struct tree_omp_clause): Add fallback_kind union member.
* tree-nested.cc (convert_nonlocal_omp_clauses): Handle
(convert_local_omp_clauses):
* tree.cc (omp_clause_num_ops, omp_clause_code_name): Add
OMP_CLAUSE_DYN_GROUPPRIVATE.
* tree-pretty-print.cc (dump_omp_clause): Handle
OMP_CLAUSE_DYN_GROUPPRIVATE.
* tree.h (OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR,
OMP_CLAUSE_DYN_GROUPPRIVATE_KIND): New #define.
gcc/testsuite/ChangeLog:
* gfortran.dg/gomp/dyn_groupprivate-1.f90: Add scan-dump test.
* gfortran.dg/gomp/dyn_groupprivate-2.f90: Extend and update.
* c-c++-common/gomp/dyn_groupprivate-1.c: New test.
* c-c++-common/gomp/dyn_groupprivate-2.c: New test.
gcc/c-family/c-omp.cc | 7 +-
gcc/c-family/c-pragma.h | 1 +
gcc/c/c-parser.cc | 115 +++++++++++++++++++--
gcc/c/c-typeck.cc | 1 +
gcc/cp/parser.cc | 111 ++++++++++++++++++--
gcc/cp/pt.cc | 1 +
gcc/cp/semantics.cc | 13 ++-
gcc/fortran/openmp.cc | 4 +-
gcc/fortran/trans-openmp.cc | 26 +++--
gcc/gimplify.cc | 5 +
.../c-c++-common/gomp/dyn_groupprivate-1.c | 28 +++++
.../c-c++-common/gomp/dyn_groupprivate-2.c | 72 +++++++++++++
.../gfortran.dg/gomp/dyn_groupprivate-1.f90 | 9 ++
.../gfortran.dg/gomp/dyn_groupprivate-2.f90 | 12 ++-
gcc/tree-core.h | 11 ++
gcc/tree-nested.cc | 2 +
gcc/tree-pretty-print.cc | 21 ++++
gcc/tree.cc | 2 +
gcc/tree.h | 5 +
19 files changed, 413 insertions(+), 33 deletions(-)
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index c80d2de6deb..e183c400652 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -2176,11 +2176,12 @@ c_omp_split_clauses (location_t loc, enum tree_code code,
{
/* First the clauses that are unique to some constructs. */
case OMP_CLAUSE_DEVICE:
- case OMP_CLAUSE_MAP:
- case OMP_CLAUSE_IS_DEVICE_PTR:
- case OMP_CLAUSE_HAS_DEVICE_ADDR:
case OMP_CLAUSE_DEFAULTMAP:
case OMP_CLAUSE_DEPEND:
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
+ case OMP_CLAUSE_IS_DEVICE_PTR:
+ case OMP_CLAUSE_HAS_DEVICE_ADDR:
+ case OMP_CLAUSE_MAP:
s = C_OMP_CLAUSE_SPLIT_TARGET;
break;
case OMP_CLAUSE_DOACROSS:
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 13df9ea490e..a61a2c7bec3 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -119,6 +119,7 @@ enum pragma_omp_clause {
PRAGMA_OMP_CLAUSE_DEVICE_TYPE,
PRAGMA_OMP_CLAUSE_DIST_SCHEDULE,
PRAGMA_OMP_CLAUSE_DOACROSS,
+ PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE,
PRAGMA_OMP_CLAUSE_ENTER,
PRAGMA_OMP_CLAUSE_FILTER,
PRAGMA_OMP_CLAUSE_FINAL,
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index b4dc741c6fd..15bfd0dc3f4 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -16411,6 +16411,8 @@ c_parser_omp_clause_name (c_parser *parser)
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
else if (!strcmp ("doacross", p))
result = PRAGMA_OMP_CLAUSE_DOACROSS;
+ else if (!strcmp ("dyn_groupprivate", p))
+ result = PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
break;
case 'e':
if (!strcmp ("enter", p))
@@ -20262,6 +20264,96 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list)
return list;
}
+/* OpenMP 6.1:
+ dyn_groupprivate ( [fallback-modifier : ] integer-expression )
+
+ fallback-modifier
+ fallback( abort | default_mem | null ) */
+
+static tree
+c_parser_omp_clause_dyn_groupprivate (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
+
+ unsigned n = 3;
+ if (c_parser_next_token_is (parser, CPP_NAME)
+ && (c_parser_peek_2nd_token (parser)->type == CPP_COLON
+ || (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN
+ && c_parser_check_balanced_raw_token_sequence (parser, &n)
+ && (c_parser_peek_nth_token_raw (parser, n)->type
+ == CPP_CLOSE_PAREN)
+ && (c_parser_peek_nth_token_raw (parser, n + 1)->type
+ == CPP_COLON))))
+ {
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "fallback") != 0)
+ {
+ c_parser_error (parser, "expected %<fallback%> modifier");
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ return list;
+ p = "";
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ if (strcmp (p, "abort") == 0)
+ kind = OMP_CLAUSE_FALLBACK_ABORT;
+ else if (strcmp (p, "default_mem") == 0)
+ kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
+ else if (strcmp (p, "null") == 0)
+ kind = OMP_CLAUSE_FALLBACK_NULL;
+ else
+ {
+ c_parser_error (parser, "expected %<abort%>, %<default_mem%>, or "
+ "%<null%> as fallback mode");
+ return list;
+ }
+ c_parser_consume_token (parser);
+ if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+ return list;
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ return list;
+ }
+ 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 size = c_fully_fold (expr.value, false, NULL);
+ parens.skip_until_found_close (parser);
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+ {
+ error_at (expr_loc, "expected integer expression");
+ return list;
+ }
+
+ /* Attempt to statically determine when the number is negative. */
+ tree c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, size,
+ build_int_cst (TREE_TYPE (size), 0));
+ protected_set_expr_location (c, expr_loc);
+ if (c == boolean_true_node)
+ {
+ warning_at (expr_loc, OPT_Wopenmp,
+ "%<dyn_groupprivate%> value must be non-negative");
+ size = integer_zero_node;
+ }
+ check_no_duplicate_clause (list, OMP_CLAUSE_DYN_GROUPPRIVATE,
+ "dyn_groupprivate");
+
+ c = build_omp_clause (clause_loc, OMP_CLAUSE_DYN_GROUPPRIVATE);
+ OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
+ OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = size;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+
+ return list;
+}
+
/* OpenMP 4.0:
map ( map-kind: variable-list )
map ( variable-list )
@@ -21982,6 +22074,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_destroy (parser, clauses);
c_name = "destroy";
break;
+ case PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE:
+ clauses = c_parser_omp_clause_dyn_groupprivate (parser, clauses);
+ c_name = "dyn_groupprivate";
+ break;
case PRAGMA_OMP_CLAUSE_INIT:
clauses = c_parser_omp_clause_init (parser, clauses);
c_name = "init";
@@ -26796,19 +26892,20 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
structured-block */
#define OMP_TARGET_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT))
static bool
c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index a34ca2ab97c..d7c9a324d7a 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -17879,6 +17879,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_FINAL:
case OMP_CLAUSE_DEVICE:
case OMP_CLAUSE_DIST_SCHEDULE:
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
case OMP_CLAUSE_PARALLEL:
case OMP_CLAUSE_FOR:
case OMP_CLAUSE_SECTIONS:
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4289f47e1b2..cdfa8f0122d 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -40047,6 +40047,8 @@ cp_parser_omp_clause_name (cp_parser *parser)
result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
else if (!strcmp ("doacross", p))
result = PRAGMA_OMP_CLAUSE_DOACROSS;
+ else if (!strcmp ("dyn_groupprivate", p))
+ result = PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE;
break;
case 'e':
if (!strcmp ("enter", p))
@@ -43743,6 +43745,91 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
return nl;
}
+/* OpenMP 6.1:
+ dyn_groupprivate ( [fallback-modifier : ] integer-expression )
+
+ fallback-modifier
+ fallback( abort | default_mem | null ) */
+
+static tree
+cp_parser_omp_clause_dyn_groupprivate (cp_parser *parser, tree list,
+ location_t location)
+{
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
+
+ size_t n;
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON)
+ || (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN)
+ && (n = cp_parser_skip_balanced_tokens (parser, 2)) != 3
+ && cp_lexer_nth_token_is (parser->lexer, n, CPP_COLON))))
+ {
+ tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+ if (strcmp (IDENTIFIER_POINTER (id), "fallback") != 0)
+ {
+ cp_parser_error (parser, "expected %<fallback%> modifier");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ return list;
+ const char *p = "";
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ id = cp_lexer_peek_token (parser->lexer)->u.value;
+ p = IDENTIFIER_POINTER (id);
+ }
+ if (strcmp (p, "abort") == 0)
+ kind = OMP_CLAUSE_FALLBACK_ABORT;
+ else if (strcmp (p, "default_mem") == 0)
+ kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
+ else if (strcmp (p, "null") == 0)
+ kind = OMP_CLAUSE_FALLBACK_NULL;
+ else
+ {
+ cp_parser_error (parser, "expected %<abort%>, %<default_mem%>, or "
+ "%<null%> as fallback mode");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+ return list;
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ return list;
+ }
+
+ tree size = cp_parser_assignment_expression (parser);
+
+ if (size == 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_DYN_GROUPPRIVATE,
+ "dyn_groupprivate", location);
+
+ tree c = build_omp_clause (location, OMP_CLAUSE_DYN_GROUPPRIVATE);
+ OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
+ OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = size;
+ OMP_CLAUSE_CHAIN (c) = list;
+ list = c;
+
+ return list;
+}
+
/* OpenMP 4.0:
map ( map-kind : variable-list )
map ( variable-list )
@@ -45352,6 +45439,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
clauses);
c_name = "destroy";
break;
+ case PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE:
+ clauses = cp_parser_omp_clause_dyn_groupprivate (parser, clauses,
+ token->location);
+ c_name = "dyn_groupprivate";
+ break;
case PRAGMA_OMP_CLAUSE_INIT:
{
/* prefer_type parsing fails often such that many follow-up errors
@@ -50230,19 +50322,20 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
structured-block */
#define OMP_TARGET_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR)\
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HAS_DEVICE_ADDR))
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT))
static bool
cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index cd66aeafd86..7a019d33bda 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -18214,6 +18214,7 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort,
case OMP_CLAUSE_ASYNC:
case OMP_CLAUSE_WAIT:
case OMP_CLAUSE_DETACH:
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
OMP_CLAUSE_OPERAND (nc, 0)
= tsubst_stmt (OMP_CLAUSE_OPERAND (oc, 0), args, complain, in_decl);
break;
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index f472be21c4b..331db16f76d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -8356,6 +8356,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
case OMP_CLAUSE_NUM_THREADS:
case OMP_CLAUSE_NUM_GANGS:
case OMP_CLAUSE_NUM_WORKERS:
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
case OMP_CLAUSE_VECTOR_LENGTH:
t = OMP_CLAUSE_OPERAND (c, 0);
if (t == error_mark_node)
@@ -8389,7 +8390,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (!processing_template_decl)
{
t = maybe_constant_value (t);
- if (TREE_CODE (t) == INTEGER_CST
+ if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DYN_GROUPPRIVATE
+ && TREE_CODE (t) == INTEGER_CST
&& tree_int_cst_sgn (t) != 1)
{
switch (OMP_CLAUSE_CODE (c))
@@ -8418,6 +8420,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
t = integer_one_node;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DYN_GROUPPRIVATE
+ && TREE_CODE (t) == INTEGER_CST
+ && tree_int_cst_sgn (t) < 0)
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
+ "%<dyn_groupprivate%> value must be "
+ "non-negative");
+ t = integer_zero_node;
+ }
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
}
OMP_CLAUSE_OPERAND (c, 0) = t;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index e847c1c0c08..abc27d59a0c 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -8977,8 +8977,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
if (omp_clauses->num_threads)
resolve_positive_int_expr (omp_clauses->num_threads, "NUM_THREADS");
if (omp_clauses->dyn_groupprivate)
- resolve_positive_int_expr (omp_clauses->dyn_groupprivate,
- "DYN_GROUPPRIVATE");
+ resolve_nonnegative_int_expr (omp_clauses->dyn_groupprivate,
+ "DYN_GROUPPRIVATE");
if (omp_clauses->chunk_size)
{
gfc_expr *expr = omp_clauses->chunk_size;
diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc
index c0a8ed927d9..8eb4fc4bcc6 100644
--- a/gcc/fortran/trans-openmp.cc
+++ b/gcc/fortran/trans-openmp.cc
@@ -5267,21 +5267,33 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (clauses->dyn_groupprivate)
{
- sorry_at (gfc_get_location (&where), "%<dyn_groupprivate%> clause");
-#if 0 /* FIXME: Handle it, including 'fallback(abort/default_mem/null)' */
- tree dyn_groupprivate;
-
gfc_init_se (&se, NULL);
gfc_conv_expr (&se, clauses->dyn_groupprivate);
gfc_add_block_to_block (block, &se.pre);
- dyn_groupprivate = gfc_evaluate_now (se.expr, block);
+ tree expr = (CONSTANT_CLASS_P (se.expr) || DECL_P (se.expr)
+ ? se.expr : gfc_evaluate_now (se.expr, block));
gfc_add_block_to_block (block, &se.post);
+ enum omp_clause_fallback_kind kind = OMP_CLAUSE_FALLBACK_UNSPECIFIED;
+ switch (clauses->fallback)
+ {
+ case OMP_FALLBACK_ABORT:
+ kind = OMP_CLAUSE_FALLBACK_ABORT;
+ break;
+ case OMP_FALLBACK_DEFAULT_MEM:
+ kind = OMP_CLAUSE_FALLBACK_DEFAULT_MEM;
+ break;
+ case OMP_FALLBACK_NULL:
+ kind = OMP_CLAUSE_FALLBACK_NULL;
+ break;
+ case OMP_FALLBACK_NONE:
+ break;
+ }
c = build_omp_clause (gfc_get_location (&where),
OMP_CLAUSE_DYN_GROUPPRIVATE);
- OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
+ OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (c) = kind;
+ OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (c) = expr;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
-#endif
}
chunk_size = NULL_TREE;
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 9371195fa01..0023728ad8e 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -14881,6 +14881,11 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
case OMP_CLAUSE_DESTROY:
break;
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
+ remove = true;
+ sorry_at (OMP_CLAUSE_LOCATION (c),"%<dyn_groupprivate%> clause");
+ break;
+
case OMP_CLAUSE_ORDER:
ctx->order_concurrent = true;
break;
diff --git a/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c b/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c
new file mode 100644
index 00000000000..c49189d6b9a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fdump-tree-original" } */
+
+void f()
+{
+ int N = 1024;
+
+ #pragma omp target dyn_groupprivate(1024) // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ ;
+
+ #pragma omp target dyn_groupprivate (1024 * N) // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback ( abort ) : N) // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback ( null ) : N) // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback ( default_mem ) : N) // { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
+ ;
+}
+
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(1024\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(N \\* 1024\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(abort\\):N\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(null\\):N\\)" 1 "original" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(default_mem\\):N\\)" 1 "original" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c b/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c
new file mode 100644
index 00000000000..f12ff7b2132
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c
@@ -0,0 +1,72 @@
+/* { dg-do compile } */
+
+void f()
+{
+#if !defined(__cplusplus) || __cplusplus >= 201103L
+ constexpr int M = 1024; // C20 + C++11
+#endif
+ int N, A[1];
+ N = 1024;
+
+ #pragma omp target dyn_groupprivate(0)
+ ;
+
+ #pragma omp target dyn_groupprivate(0) dyn_groupprivate(0) // { dg-error "too many 'dyn_groupprivate' clauses" }
+ ;
+
+ #pragma omp target dyn_groupprivate(1,) // { dg-error "expected '\\)' before ',' token" }
+ ;
+
+ #pragma omp target dyn_groupprivate(-123) // { dg-warning "'dyn_groupprivate' value must be non-negative \\\[-Wopenmp\\\]" }
+ ;
+
+#if !defined(__cplusplus) || __cplusplus >= 201103L
+ #pragma omp target dyn_groupprivate (0 * M - 1) // { dg-warning "'dyn_groupprivate' value must be non-negative \\\[-Wopenmp\\\]" "" { target { ! c++98_only } } }
+#endif
+ ;
+
+ #pragma omp target dyn_groupprivate (- 4) // { dg-warning "'dyn_groupprivate' value must be non-negative \\\[-Wopenmp\\\]" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback ( other ) : N) // { dg-error "expected 'abort', 'default_mem', or 'null' as fallback mode before 'other'" }
+ // { dg-error "expected an OpenMP clause before ':' token" "" { target c++ } .-1 }
+ ;
+
+ #pragma omp target dyn_groupprivate ( A )
+ // { dg-error "expected integer expression" "" { target c } .-1 }
+ // { dg-error "'dyn_groupprivate' expression must be integral" "" { target c++ } .-2 }
+ ;
+
+ #pragma omp target dyn_groupprivate ( 1024. )
+ // { dg-error "expected integer expression" "" { target c } .-1 }
+ // { dg-error "'dyn_groupprivate' expression must be integral" "" { target c++ } .-2 }
+ ;
+
+ #pragma omp target dyn_groupprivate ( foo ( 4 ) : 10 ) // { dg-error "expected 'fallback' modifier before 'foo'" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( foo2 ( ) : 10 ) // { dg-error "expected 'fallback' modifier before 'foo2'" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback ( ) : 10 ) // { dg-error "expected 'abort', 'default_mem', or 'null' as fallback mode before '\\)'" }
+ // { dg-error "expected an OpenMP clause before ':' token" "" { target c++ } .-1 }
+ ;
+
+ #pragma omp target dyn_groupprivate ( bar : 10 ) // { dg-error "expected 'fallback' modifier before 'bar'" }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback : 10 ) // { dg-error "expected '\\(' before ':' token" }
+ // { dg-error "expected an OpenMP clause before ':' token" "" { target c++ } .-1 }
+ ;
+
+ #pragma omp target dyn_groupprivate ( fallback ( null,) : 10 ) // { dg-error "expected '\\)' before ',' token" }
+ // { dg-error "expected an OpenMP clause before '\\)' token" "" { target c++ } .-1 }
+ ;
+}
+
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 11 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 14 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 17 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 20 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target { ! c++98_only } } 24 }
+// { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" "" { target *-*-* } 28 }
diff --git a/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-1.f90 b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-1.f90
index 2e09febe18c..3661f142ca5 100644
--- a/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-1.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-1.f90
@@ -1,3 +1,6 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+
implicit none
integer :: N
@@ -18,3 +21,9 @@ N = 1024
!$omp target dyn_groupprivate ( fallback ( default_mem ) : N) ! { dg-message "sorry, unimplemented: 'dyn_groupprivate' clause" }
!$omp end target
end
+
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(1024\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(D.4680\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(abort\\):n\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(null\\):n\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp target dyn_groupprivate\\(fallback\\(default_mem\\):n\\)" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-2.f90 b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-2.f90
index 0a5a644b9f4..8410334f4f5 100644
--- a/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/dyn_groupprivate-2.f90
@@ -1,3 +1,5 @@
+! { dg-do compile }
+
implicit none
integer, parameter :: M = 1024
@@ -5,10 +7,16 @@ integer :: N, A(1)
N = 1024
-!$omp target dyn_groupprivate(-123) ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be positive \\\[-Wopenmp\\\]" }
+!$omp target dyn_groupprivate(0) ! OK, zero is permitted
+block; end block
+
+!$omp target dyn_groupprivate(0) dyn_groupprivate(0) ! { dg-error "Duplicated 'dyn_groupprivate' clause" }
+block; end block
+
+!$omp target dyn_groupprivate(-123) ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be non-negative \\\[-Wopenmp\\\]" }
block; end block
-!$omp target dyn_groupprivate (0 * M) ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be positive \\\[-Wopenmp\\\]" }
+!$omp target dyn_groupprivate (0 * M-1) ! { dg-warning "INTEGER expression of DYN_GROUPPRIVATE clause at .1. must be non-negative \\\[-Wopenmp\\\]" }
block; end block
!$omp target dyn_groupprivate ( fallback ( other ) : N) ! { dg-error "Failed to match clause" }
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 88627ac9381..674d6ec8c7f 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -596,6 +596,8 @@ enum omp_clause_code {
/* OpenMP clause: nocontext (scalar-expression). */
OMP_CLAUSE_NOCONTEXT,
+ /* OpenMP clause: dyn_groupprivate ( [fallback (...)] : integer-expression). */
+ OMP_CLAUSE_DYN_GROUPPRIVATE,
};
#undef DEFTREESTRUCT
@@ -655,6 +657,14 @@ enum omp_clause_bind_kind {
OMP_CLAUSE_BIND_THREAD
};
+enum omp_clause_fallback_kind {
+ OMP_CLAUSE_FALLBACK_UNSPECIFIED,
+ OMP_CLAUSE_FALLBACK_ABORT,
+ OMP_CLAUSE_FALLBACK_DEFAULT_MEM,
+ OMP_CLAUSE_FALLBACK_NULL
+};
+
+
/* memory-order-clause on OpenMP atomic/flush constructs or
argument of atomic_default_mem_order clause. */
enum omp_memory_order {
@@ -1747,6 +1757,7 @@ struct GTY(()) tree_omp_clause {
enum omp_clause_defaultmap_kind defaultmap_kind;
enum omp_clause_bind_kind bind_kind;
enum omp_clause_device_type_kind device_type_kind;
+ enum omp_clause_fallback_kind fallback_kind;
} GTY ((skip)) subcode;
/* The gimplification of OMP_CLAUSE_REDUCTION_{INIT,MERGE} for omp-low's
diff --git a/gcc/tree-nested.cc b/gcc/tree-nested.cc
index 813334b5c92..21a289b0860 100644
--- a/gcc/tree-nested.cc
+++ b/gcc/tree-nested.cc
@@ -1411,6 +1411,7 @@ convert_nonlocal_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_DOACROSS:
case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
case OMP_CLAUSE_NUM_TEAMS:
case OMP_CLAUSE_THREAD_LIMIT:
case OMP_CLAUSE_SAFELEN:
@@ -2192,6 +2193,7 @@ convert_local_omp_clauses (tree *pclauses, struct walk_stmt_info *wi)
case OMP_CLAUSE_DEPEND:
case OMP_CLAUSE_DOACROSS:
case OMP_CLAUSE_DEVICE:
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
case OMP_CLAUSE_NUM_TEAMS:
case OMP_CLAUSE_THREAD_LIMIT:
case OMP_CLAUSE_SAFELEN:
diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc
index c19babadead..ba04911ae90 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -1327,6 +1327,27 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_right_paren (pp);
break;
+ case OMP_CLAUSE_DYN_GROUPPRIVATE:
+ pp_string (pp, "dyn_groupprivate(");
+ switch (OMP_CLAUSE_DYN_GROUPPRIVATE_KIND (clause))
+ {
+ case OMP_CLAUSE_FALLBACK_ABORT:
+ pp_string (pp, "fallback(abort):");
+ break;
+ case OMP_CLAUSE_FALLBACK_DEFAULT_MEM:
+ pp_string (pp, "fallback(default_mem):");
+ break;
+ case OMP_CLAUSE_FALLBACK_NULL:
+ pp_string (pp, "fallback(null):");
+ break;
+ case OMP_CLAUSE_FALLBACK_UNSPECIFIED:
+ break;
+ }
+ dump_generic_node (pp, OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR (clause),
+ spc, flags, false);
+ pp_right_paren (pp);
+ break;
+
case OMP_CLAUSE_SAFELEN:
pp_string (pp, "safelen(");
dump_generic_node (pp, OMP_CLAUSE_SAFELEN_EXPR (clause),
diff --git a/gcc/tree.cc b/gcc/tree.cc
index e8376dd04bd..52fc83e3c07 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -398,6 +398,7 @@ unsigned const char omp_clause_num_ops[] =
0, /* OMP_CLAUSE_NOHOST */
1, /* OMP_CLAUSE_NOVARIANTS */
1, /* OMP_CLAUSE_NOCONTEXT */
+ 1, /* OMP_CLAUSE_DYN_GROUPPRIVATE */
};
const char * const omp_clause_code_name[] =
@@ -501,6 +502,7 @@ const char * const omp_clause_code_name[] =
"nohost",
"novariants",
"nocontext",
+ "dyn_groupprivate",
};
/* Unless specific to OpenACC, we tend to internally maintain OpenMP-centric
diff --git a/gcc/tree.h b/gcc/tree.h
index 762228c336f..56f4fc16dcd 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2116,6 +2116,11 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_BIND_KIND(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_BIND)->omp_clause.subcode.bind_kind)
+#define OMP_CLAUSE_DYN_GROUPPRIVATE_EXPR(NODE) \
+ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DYN_GROUPPRIVATE), 0)
+#define OMP_CLAUSE_DYN_GROUPPRIVATE_KIND(NODE) \
+ (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_DYN_GROUPPRIVATE)->omp_clause.subcode.fallback_kind)
+
/* True if ENTER clause is spelled as TO. */
#define OMP_CLAUSE_ENTER_TO(NODE) \
(OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_ENTER)->base.public_flag)