From a553c70e363e75ce02c8e12e3b74b1dd9a965475 Mon Sep 17 00:00:00 2001 From: Tobias Burnus Date: Fri, 5 Dec 2025 09:08:06 +0100 Subject: [PATCH] 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, convert_local_omp_clauses): Handle OMP_CLAUSE_DYN_GROUPPRIVATE. * 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(-) create mode 100644 gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/dyn_groupprivate-2.c 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 % 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 %, %, or " + "% 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, + "% 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 % 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 %, %, or " + "% 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, + "% 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), "% 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),"% 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) -- 2.47.3