https://gcc.gnu.org/g:23251983e020d265e8d40c7a48ba9b383d15e585
commit 23251983e020d265e8d40c7a48ba9b383d15e585 Author: Julian Brown <[email protected]> Date: Fri Apr 3 23:20:36 2026 +0000 Various OpenACC reduction enhancements - FE changes gcc/c/ChangeLog * c-parser.cc (c_parser_omp_variable_list): New c_omp_region_type argument. Use it to specialize handling of OMP_CLAUSE_REDUCTION for OpenACC. (c_parser_omp_var_list_parens): Add region-type argument to call. (c_parser_oacc_data_clause): Likewise. (c_parser_oacc_data_clause_deviceptr): Likewise. (c_parser_omp_clause_reduction): Change is_omp boolean parameter to c_omp_region_type. Update call to c_parser_omp_variable_list. (c_parser_omp_clause_map): Update call to c_parser_omp_variable_list. (c_parser_omp_clause_from_to): Likewise. (c_parser_omp_clause_init): Likewise. (c_parser_oacc_all_clauses): Update calls to c_parser_omp_clause_reduction. (c_parser_omp_all_clauses): Likewise. (c_parser_oacc_cache): Update call to c_parser_omp_variable_list. * c-typeck.cc (c_finish_omp_clauses): Emit an error on orphan OpenACC gang reductions. Suppress user-defined reduction error for OpenACC. gcc/cp/ChangeLog * parser.cc (cp_parser_omp_var_list_no_open): New c_omp_region_type argument. Use it to specialize handling of OMP_CLAUSE_REDUCTION for OpenACC. (cp_parser_omp_var_list): Add c_omp_region_type argument. Update call to cp_parser_omp_var_list_no_open. (cp_parser_oacc_data_clause): Update call to cp_parser_omp_var_list_no_open. (cp_parser_omp_clause_reduction): Change is_omp boolean parameter to c_omp_region_type. Update call to cp_parser_omp_var_list_no_open. (cp_parser_omp_clause_from_to): Update call to cp_parser_omp_clause_var_list_no_open. (cp_parser_omp_clause_map): Likewise. (cp_parser_omp_clause_init): Likewise. (cp_parser_oacc_all_clauses): Update call to cp_parser_omp_clause_reduction. (cp_parser_omp_all_clauses): Likewise. * semantics.cc (finish_omp_reduction_clause): Add c_omp_region_type argument. Suppress user-defined reduction error for OpenACC. (finish_omp_clauses): Update call to finish_omp_reduction_clause. gcc/fortran/ChangeLog * trans-openmp.cc (gfc_omp_clause_copy_ctor): Permit reductions. Co-Authored-By: Cesar Philippidis <[email protected]> Co-Authored-By: Nathan Sidwell <[email protected]> Co-Authored-By: Kwok Cheung Yeung <[email protected]> Diff: --- gcc/c/c-parser.cc | 46 +++++++++++++++++++++++++-------------------- gcc/c/c-typeck.cc | 7 +++++-- gcc/cp/parser.cc | 33 +++++++++++++++++--------------- gcc/cp/semantics.cc | 13 ++++++++----- gcc/fortran/trans-openmp.cc | 3 ++- 5 files changed, 59 insertions(+), 43 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 08a1b1e005c3..d521978c8aa0 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -16714,7 +16714,7 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list) in TREE_PURPOSE and the location in TREE_VALUE (accessible using EXPR_LOCATION); return the list created. - The optional ALLOW_DEREF argument is true if list items can use the deref + The optional MAP_LVALUE argument is true if list items can use the deref (->) operator. */ struct omp_dim @@ -16730,6 +16730,7 @@ static tree c_parser_omp_variable_list (c_parser *parser, location_t clause_loc, enum omp_clause_code kind, tree list, + enum c_omp_region_type ort = C_ORT_OMP, bool map_lvalue = false) { auto_vec<omp_dim> dims; @@ -17002,7 +17003,8 @@ c_parser_omp_variable_list (c_parser *parser, case OMP_CLAUSE_HAS_DEVICE_ADDR: array_section_p = false; dims.truncate (0); - while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) + while ((ort != C_ORT_ACC || kind != OMP_CLAUSE_REDUCTION) + && c_parser_next_token_is (parser, CPP_OPEN_SQUARE)) { location_t loc = UNKNOWN_LOCATION; tree low_bound = NULL_TREE, length = NULL_TREE; @@ -17136,12 +17138,14 @@ c_parser_omp_variable_list (c_parser *parser, } /* Similarly, but expect leading and trailing parenthesis. This is a very - common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF + common case for OpenACC and OpenMP clauses. The optional MAP_LVALUE argument is true if list items can use the deref (->) operator. */ static tree c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, - tree list, bool map_lvalue = false) + tree list, + enum c_omp_region_type ort = C_ORT_OMP, + bool map_lvalue = false) { /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; @@ -17162,7 +17166,8 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, matching_parens parens; if (parens.require_open (parser)) { - list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue); + list = c_parser_omp_variable_list (parser, loc, kind, list, ort, + map_lvalue); parens.skip_until_found_close (parser); } return list; @@ -17257,7 +17262,7 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind, } } nl = c_parser_omp_variable_list (parser, open_loc, OMP_CLAUSE_MAP, list, - false); + C_ORT_ACC, false); parens.skip_until_found_close (parser); } @@ -17282,7 +17287,8 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list) /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR, variable-list must only allow for pointer variables. */ - vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL); + vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL, + C_ORT_ACC); for (t = vars; t && t; t = TREE_CHAIN (t)) { tree v = TREE_PURPOSE (t); @@ -18841,7 +18847,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list) static tree c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind, - bool is_omp, tree list) + enum c_omp_region_type ort, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; matching_parens parens; @@ -18852,7 +18858,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind, enum tree_code code = ERROR_MARK; tree reduc_id = NULL_TREE; - if (kind == OMP_CLAUSE_REDUCTION && is_omp) + if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_OMP) { if (c_parser_next_token_is_keyword (parser, RID_DEFAULT) && c_parser_peek_2nd_token (parser)->type == CPP_COMMA) @@ -18886,7 +18892,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind, code = MULT_EXPR; break; case CPP_MINUS: - if (is_omp) + if (ort == C_ORT_OMP) { location_t loc = c_parser_peek_token (parser)->location; gcc_rich_location richloc (loc); @@ -18942,7 +18948,8 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind, { tree nl, c; - nl = c_parser_omp_variable_list (parser, clause_loc, kind, list); + nl = c_parser_omp_variable_list (parser, clause_loc, kind, list, ort); + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) { tree d = OMP_CLAUSE_DECL (c), type; @@ -20945,7 +20952,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) } nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list, - true); + C_ORT_OMP, true); tree last_new = NULL_TREE; @@ -21375,7 +21382,7 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, if (colon_pos) c_parser_require (parser, CPP_COLON, "expected %<:%>"); - tree nl = c_parser_omp_variable_list (parser, loc, kind, list); + tree nl = c_parser_omp_variable_list (parser, loc, kind, list, C_ORT_OMP); parens.skip_until_found_close (parser); if (present) @@ -21960,8 +21967,7 @@ c_parser_omp_clause_init (c_parser *parser, tree list) error_at (loc, "missing required %<target%> and/or %<targetsync%> modifier"); - tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list, - false); + tree nl = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_INIT, list); parens.skip_until_found_close (parser); for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) @@ -22153,7 +22159,7 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask, case PRAGMA_OACC_CLAUSE_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - false, clauses); + C_ORT_ACC, clauses); c_name = "reduction"; break; case PRAGMA_OACC_CLAUSE_SELF: @@ -22319,7 +22325,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, case PRAGMA_OMP_CLAUSE_IN_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION, - true, clauses); + C_ORT_OMP, clauses); c_name = "in_reduction"; break; case PRAGMA_OMP_CLAUSE_INDIRECT: @@ -22365,7 +22371,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, case PRAGMA_OMP_CLAUSE_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - true, clauses); + C_ORT_OMP, clauses); c_name = "reduction"; break; case PRAGMA_OMP_CLAUSE_SCHEDULE: @@ -22379,7 +22385,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, case PRAGMA_OMP_CLAUSE_TASK_REDUCTION: clauses = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION, - true, clauses); + C_ORT_OMP, clauses); c_name = "task_reduction"; break; case PRAGMA_OMP_CLAUSE_UNTIED: @@ -22685,7 +22691,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser) readonly = true; } clauses = c_parser_omp_variable_list (parser, open_loc, - OMP_CLAUSE__CACHE_, NULL_TREE); + OMP_CLAUSE__CACHE_, NULL_TREE, C_ORT_ACC); parens.skip_until_found_close (parser); } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index f246c6c524f3..15703cf166a5 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -16950,8 +16950,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node) { - error_at (OMP_CLAUSE_LOCATION (c), - "user defined reduction not found for %qE", t); + /* There are no user-defined reductions in OpenACC (as of + 2.6). */ + if (ort & C_ORT_OMP) + error_at (OMP_CLAUSE_LOCATION (c), + "user defined reduction not found for %qE", t); remove = true; break; } diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 9f305723acee..1cd827d47f66 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -41511,6 +41511,7 @@ struct omp_dim static tree cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, tree list, bool *colon, + enum c_omp_region_type ort = C_ORT_OMP, bool map_lvalue = false) { auto_vec<omp_dim> dims; @@ -41727,7 +41728,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, case OMP_CLAUSE_HAS_DEVICE_ADDR: array_section_p = false; dims.truncate (0); - while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) + while ((ort != C_ORT_ACC || kind != OMP_CLAUSE_REDUCTION) + && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) { location_t loc = UNKNOWN_LOCATION; tree low_bound = NULL_TREE, length = NULL_TREE; @@ -41875,6 +41877,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, static tree cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list, + enum c_omp_region_type ort = C_ORT_OMP, bool map_lvalue = false) { if (parser->lexer->in_omp_decl_attribute) @@ -41893,7 +41896,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list, } if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) - return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, + return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, ort, map_lvalue); return list; } @@ -41985,7 +41988,7 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind, } } nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list, NULL, - false); + C_ORT_ACC, false); } for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) @@ -43349,7 +43352,7 @@ cp_parser_omp_clause_ordered (cp_parser *parser, static tree cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, - bool is_omp, tree list) + enum c_omp_region_type ort, tree list) { enum tree_code code = ERROR_MARK; tree nlist, c, id = NULL_TREE; @@ -43359,7 +43362,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return list; - if (kind == OMP_CLAUSE_REDUCTION && is_omp) + if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_OMP) { if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT) && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA)) @@ -43389,7 +43392,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, case CPP_PLUS: code = PLUS_EXPR; break; case CPP_MULT: code = MULT_EXPR; break; case CPP_MINUS: - if (is_omp) + if (ort == C_ORT_OMP) { location_t loc = cp_lexer_peek_token (parser->lexer)->location; gcc_rich_location richloc (loc); @@ -43467,8 +43470,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, if (!cp_parser_require (parser, CPP_COLON, RT_COLON)) goto resync_fail; - nlist = cp_parser_omp_var_list_no_open (parser, kind, list, - NULL); + nlist = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, ort); for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) { OMP_CLAUSE_REDUCTION_CODE (c) = code; @@ -45301,7 +45303,8 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind, if (colon_pos) cp_parser_require (parser, CPP_COLON, RT_COLON); - tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, true); + tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, C_ORT_OMP, + true); if (present) for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_MOTION_PRESENT (c) = 1; @@ -45715,7 +45718,7 @@ cp_parser_omp_clause_map (cp_parser *parser, tree list, bool declare_mapper_p) legally. */ begin_scope (sk_omp, NULL); nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_MAP, list, - NULL, true); + NULL, C_ORT_OMP, true); finish_scope (); tree last_new = NULL_TREE; @@ -46422,7 +46425,7 @@ cp_parser_omp_clause_init (cp_parser *parser, tree list) "missing required %<target%> and/or %<targetsync%> modifier"); tree nl = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_INIT, list, - NULL, false); + NULL); for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) { TREE_ADDRESSABLE (OMP_CLAUSE_DECL (c)) = 1; @@ -46665,7 +46668,7 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask, case PRAGMA_OACC_CLAUSE_REDUCTION: clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - false, clauses); + C_ORT_ACC, clauses); c_name = "reduction"; break; case PRAGMA_OACC_CLAUSE_SELF: @@ -46863,7 +46866,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, case PRAGMA_OMP_CLAUSE_IN_REDUCTION: clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION, - true, clauses); + C_ORT_OMP, clauses); c_name = "in_reduction"; break; case PRAGMA_OMP_CLAUSE_INDIRECT: @@ -46918,7 +46921,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, case PRAGMA_OMP_CLAUSE_REDUCTION: clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION, - true, clauses); + C_ORT_OMP, clauses); c_name = "reduction"; break; case PRAGMA_OMP_CLAUSE_SCHEDULE: @@ -46935,7 +46938,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, clauses = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION, - true, clauses); + C_ORT_OMP, clauses); c_name = "task_reduction"; break; case PRAGMA_OMP_CLAUSE_UNTIED: diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index bafb558b2594..b0bfc5a2a9d3 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -7223,7 +7223,8 @@ find_omp_placeholder_r (tree *tp, int *, void *data) Return true if there is some error and the clause should be removed. */ static bool -finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) +finish_omp_reduction_clause (tree c, enum c_omp_region_type ort, + bool *need_default_ctor, bool *need_dtor) { tree t = OMP_CLAUSE_DECL (c); bool predefined = false; @@ -7469,9 +7470,11 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) *need_dtor = true; else { - error_at (OMP_CLAUSE_LOCATION (c), - "user defined reduction not found for %qE", - omp_clause_printable_decl (t)); + /* There are no user-defined reductions for OpenACC (as of 2.6). */ + if (ort & C_ORT_OMP) + error_at (OMP_CLAUSE_LOCATION (c), + "user defined reduction not found for %qE", + omp_clause_printable_decl (t)); return true; } if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF) @@ -10536,7 +10539,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (processing_template_decl && !VAR_P (t) && TREE_CODE (t) != PARM_DECL) break; - if (finish_omp_reduction_clause (c, &need_default_ctor, + if (finish_omp_reduction_clause (c, ort, &need_default_ctor, &need_dtor)) remove = true; else diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index ab6f751a79e6..782ab7a15d4b 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -954,7 +954,8 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src) stmtblock_t block, cond_block; gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE - || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR); + || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR + || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION); if (DECL_ARTIFICIAL (orig_decl) && DECL_LANG_SPECIFIC (orig_decl)
