From: Jakub Jelinek Date: Mon, 10 Jun 2019 12:20:30 +0000 (+0200) Subject: tree.def (OMP_SCAN): New tree code. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bf38f7e9aa76856a7c8ac57988600ce9de7cafbd;p=gcc.git tree.def (OMP_SCAN): New tree code. * tree.def (OMP_SCAN): New tree code. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and OMP_CLAUSE_EXCLUSIVE. * tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP. (OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define. * tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for OMP_CLAUSE_{IN,EX}CLUSIVE. (walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE. * tree-nested.c (convert_nonlocal_reference_stmt, convert_local_reference_stmt, convert_gimple_call): Handle GIMPLE_OMP_SCAN. * tree-pretty-print.c (dump_omp_clause): Handle OMP_CLAUSE_{IN,EX}CLUSIVE. (dump_generic_node): Handle OMP_SCAN. * gimple.def (GIMPLE_OMP_SCAN): New gimple code. * gimple.h (gomp_scan): New type. (is_a_helper ::test, is_a_helper ::test): New templates. (gimple_build_omp_scan): Declare. (gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr, gimple_omp_scan_set_clauses): New inline functions. (CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:. * gimple.c (gimple_build_omp_scan): New function. (gimple_copy): Handle GIMPLE_OMP_SCAN. * gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise. * gimple-pretty-print.c (dump_gimple_omp_block): Don't handle GIMPLE_OMP_TASKGROUP. (dump_gimple_omp_scan): New function. (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN. * gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN. * tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise. * gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN. (is_gimple_stmt): Handle OMP_SCAN. (gimplify_scan_omp_clauses): Reject inscan reductions on constructs other than OMP_FOR or OMP_SIMD. Handle OMP_CLAUSE_{IN,EX}CLUSIVE. (gimplify_adjust_omp_clauses): Diagnose inscan reductions not mentioned in nested #pragma omp scan. Handle OMP_CLAUSE_{IN,EX}CLUSIVE. (gimplify_expr): Handle OMP_SCAN. * omp-low.c (check_omp_nesting_restrictions): For parent context, look through GIMPLE_OMP_SCAN context. Allow #pragma omp scan in simd constructs. (scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle GIMPLE_OMP_SCAN. c-family/ * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN. * c-pragma.c (omp_pragmas_simd): Add #pragma omp scan. * c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on combined/composite constructs where it is not allowed. Copy over OMP_CLAUSE_REDUCTION_INSCAN. c/ * c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN. (c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions. (c_parser_omp_scan_loop_body): New function. (c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are inscan reduction clauses. * c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with non-inscan reductions on the same construct, or inscan reductions with ordered or schedule clauses, or inscan array reductions. cp/ * parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan reductions. (cp_parser_omp_scan_loop_body): New function. (cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there are inscan reduction clauses. (cp_parser_pragma): Reject PRAGMA_OMP_SCAN. * semantics.c (finish_omp_clauses): Reject mixing inscan with non-inscan reductions on the same construct, or inscan reductions with ordered or schedule clauses, or inscan array reductions. * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE. (tsubst_expr): Handle OMP_SCAN. testsuite/ * c-c++-common/gomp/scan-1.c: New test. * c-c++-common/gomp/scan-2.c: New test. * c-c++-common/gomp/scan-3.c: New test. * c-c++-common/gomp/scan-4.c: New test. From-SVN: r272117 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e93db0a1b7b..d5181995757 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,8 +1,55 @@ +2019-06-10 Jakub Jelinek + + * tree.def (OMP_SCAN): New tree code. + * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_INCLUSIVE and + OMP_CLAUSE_EXCLUSIVE. + * tree.h (OMP_CLAUSES): Use OMP_SCAN instead of OMP_TASKGROUP. + (OMP_SCAN_BODY, OMP_SCAN_CLAUSES): Define. + * tree.c (omp_clause_num_ops, omp_clause_code_name): Add entries for + OMP_CLAUSE_{IN,EX}CLUSIVE. + (walk_tree_1): Handle OMP_CLAUSE_{IN,EX}CLUSIVE. + * tree-nested.c (convert_nonlocal_reference_stmt, + convert_local_reference_stmt, convert_gimple_call): Handle + GIMPLE_OMP_SCAN. + * tree-pretty-print.c (dump_omp_clause): Handle + OMP_CLAUSE_{IN,EX}CLUSIVE. + (dump_generic_node): Handle OMP_SCAN. + * gimple.def (GIMPLE_OMP_SCAN): New gimple code. + * gimple.h (gomp_scan): New type. + (is_a_helper ::test, + is_a_helper ::test): New templates. + (gimple_build_omp_scan): Declare. + (gimple_omp_scan_clauses, gimple_omp_scan_clauses_ptr, + gimple_omp_scan_set_clauses): New inline functions. + (CASE_GIMPLE_OMP): Add case GIMPLE_OMP_SCAN:. + * gimple.c (gimple_build_omp_scan): New function. + (gimple_copy): Handle GIMPLE_OMP_SCAN. + * gimple-walk.c (walk_gimple_op, walk_gimple_stmt): Likewise. + * gimple-pretty-print.c (dump_gimple_omp_block): Don't handle + GIMPLE_OMP_TASKGROUP. + (dump_gimple_omp_scan): New function. + (pp_gimple_stmt_1): Handle GIMPLE_OMP_SCAN. + * gimple-low.c (lower_stmt): Handle GIMPLE_OMP_SCAN. + * tree-inline.c (remap_gimple_stmt, estimate_num_insns): Likewise. + * gimplify.c (enum gimplify_omp_var_data): Add GOVD_REDUCTION_INSCAN. + (is_gimple_stmt): Handle OMP_SCAN. + (gimplify_scan_omp_clauses): Reject inscan reductions on constructs + other than OMP_FOR or OMP_SIMD. Handle OMP_CLAUSE_{IN,EX}CLUSIVE. + (gimplify_adjust_omp_clauses): Diagnose inscan reductions not + mentioned in nested #pragma omp scan. Handle + OMP_CLAUSE_{IN,EX}CLUSIVE. + (gimplify_expr): Handle OMP_SCAN. + * omp-low.c (check_omp_nesting_restrictions): For parent context, + look through GIMPLE_OMP_SCAN context. Allow #pragma omp scan in + simd constructs. + (scan_omp_1_stmt, lower_omp_1, diagnose_sb_1, diagnose_sb_2): Handle + GIMPLE_OMP_SCAN. + 2019-06-10 Martin Liska * ipa-cp.c (ignore_edge_p): New function. (build_toporder_info): Use it. - * ipa-inline.c (ignore_edge_p): New function/ + * ipa-inline.c (ignore_edge_p): New function. (inline_small_functions): Use it. * ipa-pure-const.c (ignore_edge_for_nothrow): Verify opt_for_fn for caller and callee. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 179e376fb91..589e4a12932 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2019-06-10 Jakub Jelinek + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCAN. + * c-pragma.c (omp_pragmas_simd): Add #pragma omp scan. + * c-omp.c (c_omp_split_clauses): Diagnose inscan reductions on + combined/composite constructs where it is not allowed. Copy over + OMP_CLAUSE_REDUCTION_INSCAN. + 2019-06-05 Martin Sebor * c-attribs.c (handle_mode_attribute): Adjust quoting and hyphenation. diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 5645e9d4fda..96b2e45ae7a 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -1659,6 +1659,18 @@ c_omp_split_clauses (location_t loc, enum tree_code code, OMP_CLAUSE_REDUCTION_TASK (clauses) = 0; } } + if (OMP_CLAUSE_REDUCTION_INSCAN (clauses) + && ((mask & ((OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE) + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP))) + != 0)) + { + error_at (OMP_CLAUSE_LOCATION (clauses), + "% % clause on construct other " + "than %, %, %, " + "%, %"); + OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0; + } if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { if (code == OMP_SIMD) @@ -1672,6 +1684,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_INSCAN (c) + = OMP_CLAUSE_REDUCTION_INSCAN (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_SIMD]; cclauses[C_OMP_CLAUSE_SPLIT_SIMD] = c; } @@ -1687,6 +1701,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_INSCAN (c) + = OMP_CLAUSE_REDUCTION_INSCAN (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c; s = C_OMP_CLAUSE_SPLIT_PARALLEL; @@ -1717,6 +1733,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_INSCAN (c) + = OMP_CLAUSE_REDUCTION_INSCAN (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c; } diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 62b71d2e4c4..9af713d1b43 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1320,6 +1320,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = { { "for", PRAGMA_OMP_FOR }, { "ordered", PRAGMA_OMP_ORDERED }, { "parallel", PRAGMA_OMP_PARALLEL }, + { "scan", PRAGMA_OMP_SCAN }, { "simd", PRAGMA_OMP_SIMD }, { "target", PRAGMA_OMP_TARGET }, { "taskloop", PRAGMA_OMP_TASKLOOP }, diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 2bbb2797525..ed650368620 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -56,6 +56,7 @@ enum pragma_kind { PRAGMA_OMP_ORDERED, PRAGMA_OMP_PARALLEL, PRAGMA_OMP_REQUIRES, + PRAGMA_OMP_SCAN, PRAGMA_OMP_SECTION, PRAGMA_OMP_SECTIONS, PRAGMA_OMP_SIMD, diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 5a0dabbd034..103634eff73 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,14 @@ +2019-06-10 Jakub Jelinek + + * c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN. + (c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions. + (c_parser_omp_scan_loop_body): New function. + (c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are + inscan reduction clauses. + * c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with + non-inscan reductions on the same construct, or inscan reductions with + ordered or schedule clauses, or inscan array reductions. + 2019-06-05 Martin Sebor PR c/90737 diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 84ee576866e..df1a3042276 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -11494,6 +11494,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p) c_parser_omp_end_declare_target (parser); return false; + case PRAGMA_OMP_SCAN: + error_at (c_parser_peek_token (parser)->location, + "%<#pragma omp scan%> may only be used in " + "a loop construct with % % clause"); + c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); + return false; + case PRAGMA_OMP_SECTION: error_at (c_parser_peek_token (parser)->location, "%<#pragma omp section%> may only be used in " @@ -13558,11 +13565,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind, if (strcmp (p, "task") == 0) task = true; else if (strcmp (p, "inscan") == 0) - { - inscan = true; - sorry ("% modifier on % clause " - "not supported yet"); - } + inscan = true; if (task || inscan) { c_parser_consume_token (parser); @@ -16738,6 +16741,71 @@ c_parser_omp_flush (c_parser *parser) c_finish_omp_flush (loc, mo); } +/* OpenMP 5.0: + + scan-loop-body: + { structured-block scan-directive structured-block } */ + +static void +c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed) +{ + tree substmt; + location_t loc; + tree clauses = NULL_TREE; + + loc = c_parser_peek_token (parser)->location; + if (!open_brace_parsed + && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>")) + { + /* Avoid skipping until the end of the block. */ + parser->error = false; + return; + } + + substmt = c_parser_omp_structured_block (parser, NULL); + substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); + SET_EXPR_LOCATION (substmt, loc); + add_stmt (substmt); + + loc = c_parser_peek_token (parser)->location; + if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN) + { + enum omp_clause_code clause = OMP_CLAUSE_ERROR; + + c_parser_consume_pragma (parser); + + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p + = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "inclusive") == 0) + clause = OMP_CLAUSE_INCLUSIVE; + else if (strcmp (p, "exclusive") == 0) + clause = OMP_CLAUSE_EXCLUSIVE; + } + if (clause != OMP_CLAUSE_ERROR) + { + c_parser_consume_token (parser); + clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE); + } + else + c_parser_error (parser, "expected % or " + "% clause"); + c_parser_skip_to_pragma_eol (parser); + } + else + error ("expected %<#pragma omp scan%>"); + + clauses = c_finish_omp_clauses (clauses, C_ORT_OMP); + substmt = c_parser_omp_structured_block (parser, NULL); + substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses); + SET_EXPR_LOCATION (substmt, loc); + add_stmt (substmt); + + c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, + "expected %<}%>"); +} + /* Parse the restricted form of loop statements allowed by OpenACC and OpenMP. The real trick here is to determine the loop control variable early so that we can push a new decl if necessary to make it private. @@ -16756,6 +16824,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, int i, collapse = 1, ordered = 0, count, nbraces = 0; location_t for_loc; bool tiling = false; + bool inscan = false; vec *for_block = make_tree_vector (); for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) @@ -16772,6 +16841,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, ordered_cl = cl; ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); } + else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_INSCAN (cl) + && (code == OMP_SIMD || code == OMP_FOR)) + inscan = true; if (ordered && ordered < collapse) { @@ -16992,7 +17065,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code, c_cont_label = NULL_TREE; body = push_stmt_list (); - if (open_brace_parsed) + if (inscan) + c_parser_omp_scan_loop_body (parser, open_brace_parsed); + else if (open_brace_parsed) { location_t here = c_parser_peek_token (parser)->location; stmt = c_begin_compound_stmt (true); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 0dd86f074b9..6abfd101f30 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13661,13 +13661,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bool copyprivate_seen = false; bool linear_variable_step_check = false; tree *nowait_clause = NULL; - bool ordered_seen = false; + tree ordered_clause = NULL_TREE; tree schedule_clause = NULL_TREE; bool oacc_async = false; tree last_iterators = NULL_TREE; bool last_iterators_remove = false; tree *nogroup_seen = NULL; - bool reduction_seen = false; + /* 1 if normal/task reduction has been seen, -1 if inscan reduction + has been seen, -2 if mixed inscan/normal reduction diagnosed. */ + int reduction_seen = 0; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -13706,7 +13708,17 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) goto check_dup_generic; case OMP_CLAUSE_REDUCTION: - reduction_seen = true; + if (reduction_seen == 0) + reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1; + else if (reduction_seen != -2 + && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c) + ? -1 : 1)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% and non-% % clauses " + "on the same construct"); + reduction_seen = -2; + } /* FALLTHRU */ case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: @@ -13721,6 +13733,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } t = OMP_CLAUSE_DECL (c); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_INSCAN (c)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause with array " + "section"); + remove = true; + break; + } } t = require_complete_type (OMP_CLAUSE_LOCATION (c), t); if (t == error_mark_node) @@ -14661,7 +14682,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) continue; case OMP_CLAUSE_ORDERED: - ordered_seen = true; + ordered_clause = c; pc = &OMP_CLAUSE_CHAIN (c); continue; @@ -14688,6 +14709,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: + need_complete = true; + need_implicitly_determined = true; + t = OMP_CLAUSE_DECL (c); + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in clause %qs", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + break; + default: gcc_unreachable (); } @@ -14760,7 +14795,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) = OMP_CLAUSE_SAFELEN_EXPR (safelen); } - if (ordered_seen + if (ordered_clause && schedule_clause && (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause) & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) @@ -14774,7 +14809,23 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC); } - if (linear_variable_step_check) + if (reduction_seen < 0 && ordered_clause) + { + error_at (OMP_CLAUSE_LOCATION (ordered_clause), + "%qs clause specified together with % " + "% clause", "ordered"); + reduction_seen = -2; + } + + if (reduction_seen < 0 && schedule_clause) + { + error_at (OMP_CLAUSE_LOCATION (schedule_clause), + "%qs clause specified together with % " + "% clause", "schedule"); + reduction_seen = -2; + } + + if (linear_variable_step_check || reduction_seen == -2) for (pc = &clauses, c = clauses; c ; c = *pc) { bool remove = false; @@ -14789,6 +14840,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) OMP_CLAUSE_LINEAR_STEP (c)); remove = true; } + else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; if (remove) *pc = OMP_CLAUSE_CHAIN (c); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c0720404b75..188752c5ed7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2019-06-10 Jakub Jelinek + + * parser.c (cp_parser_omp_clause_reduction): Don't sorry_at on inscan + reductions. + (cp_parser_omp_scan_loop_body): New function. + (cp_parser_omp_for_loop): Call cp_parser_omp_scan_loop_body if there + are inscan reduction clauses. + (cp_parser_pragma): Reject PRAGMA_OMP_SCAN. + * semantics.c (finish_omp_clauses): Reject mixing inscan with + non-inscan reductions on the same construct, or inscan reductions with + ordered or schedule clauses, or inscan array reductions. + * pt.c (tsubst_omp_clauses): Handle OMP_CLAUSE_{IN,EX}CLUSIVE. + (tsubst_expr): Handle OMP_SCAN. + 2019-06-07 Jason Merrill * constexpr.c (cxx_eval_constant_expression): Call diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 308b2d4ad70..e699fbc6b25 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -33773,11 +33773,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind, if (strcmp (p, "task") == 0) task = true; else if (strcmp (p, "inscan") == 0) - { - inscan = true; - sorry ("% modifier on % clause " - "not supported yet"); - } + inscan = true; if (task || inscan) { cp_lexer_consume_token (parser->lexer); @@ -36820,6 +36816,63 @@ cp_finish_omp_range_for (tree orig, tree begin) cp_finish_decomp (decl, decomp_first_name, decomp_cnt); } +/* OpenMP 5.0: + + scan-loop-body: + { structured-block scan-directive structured-block } */ + +static void +cp_parser_omp_scan_loop_body (cp_parser *parser) +{ + tree substmt, clauses = NULL_TREE; + + matching_braces braces; + if (!braces.require_open (parser)) + return; + + substmt = cp_parser_omp_structured_block (parser, NULL); + substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); + add_stmt (substmt); + + cp_token *tok = cp_lexer_peek_token (parser->lexer); + if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN) + { + enum omp_clause_code clause = OMP_CLAUSE_ERROR; + + cp_lexer_consume_token (parser->lexer); + + 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, "inclusive") == 0) + clause = OMP_CLAUSE_INCLUSIVE; + else if (strcmp (p, "exclusive") == 0) + clause = OMP_CLAUSE_EXCLUSIVE; + } + if (clause != OMP_CLAUSE_ERROR) + { + cp_lexer_consume_token (parser->lexer); + clauses = cp_parser_omp_var_list (parser, clause, NULL_TREE); + } + else + cp_parser_error (parser, "expected % or " + "% clause"); + + cp_parser_require_pragma_eol (parser, tok); + } + else + error ("expected %<#pragma omp scan%>"); + + clauses = finish_omp_clauses (clauses, C_ORT_OMP); + substmt = cp_parser_omp_structured_block (parser, NULL); + substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt, + clauses); + add_stmt (substmt); + + braces.require_close (parser); +} + /* Parse the restricted form of the for statement allowed by OpenMP. */ static tree @@ -36836,6 +36889,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, releasing_vec for_block; auto_vec orig_inits; bool tiling = false; + bool inscan = false; for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl)) if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE) @@ -36851,6 +36905,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, ordered_cl = cl; ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl)); } + else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_INSCAN (cl) + && (code == OMP_SIMD || code == OMP_FOR)) + inscan = true; if (ordered && ordered < collapse) { @@ -37179,7 +37237,10 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses, } else body = push_stmt_list (); - cp_parser_statement (parser, NULL_TREE, false, if_p); + if (inscan) + cp_parser_omp_scan_loop_body (parser); + else + cp_parser_statement (parser, NULL_TREE, false, if_p); if (orig_declv) body = finish_omp_structured_block (body); else @@ -41044,6 +41105,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) cp_parser_omp_end_declare_target (parser, pragma_tok); return false; + case PRAGMA_OMP_SCAN: + error_at (pragma_tok->location, + "%<#pragma omp scan%> may only be used in " + "a loop construct with % % clause"); + break; + case PRAGMA_OMP_SECTION: error_at (pragma_tok->location, "%<#pragma omp section%> may only be used in " diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d2cf3458253..ebaab27f09c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16323,6 +16323,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_NONTEMPORAL: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: OMP_CLAUSE_DECL (nc) = tsubst_omp_clause_decl (OMP_CLAUSE_DECL (oc), args, complain, in_decl, iterator_cache); @@ -16443,6 +16445,8 @@ tsubst_omp_clauses (tree clauses, enum c_omp_region_type ort, case OMP_CLAUSE_TASK_REDUCTION: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: /* tsubst_expr on SCOPE_REF results in returning finish_non_static_data_member result. Undo that here. */ if (TREE_CODE (OMP_CLAUSE_DECL (oc)) == SCOPE_REF @@ -17639,6 +17643,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case OMP_TEAMS: case OMP_CRITICAL: case OMP_TASKGROUP: + case OMP_SCAN: r = push_omp_privatization_clauses (TREE_CODE (t) == OMP_TEAMS && OMP_TEAMS_COMBINED (t)); tmp = tsubst_omp_clauses (OMP_CLAUSES (t), C_ORT_OMP, args, complain, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fc5edde89c3..8e354a2990c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6126,10 +6126,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bool branch_seen = false; bool copyprivate_seen = false; bool ordered_seen = false; + bool schedule_seen = false; bool oacc_async = false; tree last_iterators = NULL_TREE; bool last_iterators_remove = false; - bool reduction_seen = false; + /* 1 if normal/task reduction has been seen, -1 if inscan reduction + has been seen, -2 if mixed inscan/normal reduction diagnosed. */ + int reduction_seen = 0; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -6164,7 +6167,17 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); goto check_dup_generic; case OMP_CLAUSE_REDUCTION: - reduction_seen = true; + if (reduction_seen == 0) + reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1; + else if (reduction_seen != -2 + && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c) + ? -1 : 1)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% and non-% % clauses " + "on the same construct"); + reduction_seen = -2; + } /* FALLTHRU */ case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: @@ -6177,6 +6190,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; break; } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_INSCAN (c)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause with array " + "section"); + remove = true; + break; + } if (TREE_CODE (t) == TREE_LIST) { while (TREE_CODE (t) == TREE_LIST) @@ -6684,6 +6706,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; } + if (!remove) + schedule_seen = true; break; case OMP_CLAUSE_SIMDLEN: @@ -7583,6 +7607,37 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) branch_seen = true; break; + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: + t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); + if (!t) + t = OMP_CLAUSE_DECL (c); + if (t == current_class_ptr) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% allowed in OpenMP only in %" + " clauses"); + remove = true; + break; + } + if (!VAR_P (t) + && TREE_CODE (t) != PARM_DECL + && TREE_CODE (t) != FIELD_DECL) + { + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) + break; + if (DECL_P (t)) + error_at (OMP_CLAUSE_LOCATION (c), + "%qD is not a variable in clause %qs", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + else + error_at (OMP_CLAUSE_LOCATION (c), + "%qE is not a variable in clause %qs", t, + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + break; + default: gcc_unreachable (); } @@ -7593,6 +7648,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); } + if (reduction_seen < 0 && (ordered_seen || schedule_seen)) + reduction_seen = -2; + for (pc = &clauses, c = clauses; c ; c = *pc) { enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c); @@ -7628,8 +7686,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) need_implicitly_determined = true; break; case OMP_CLAUSE_REDUCTION: + if (reduction_seen == -2) + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; + need_implicitly_determined = true; + break; case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: need_implicitly_determined = true; break; case OMP_CLAUSE_LINEAR: @@ -7680,6 +7744,10 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) (OMP_CLAUSE_SCHEDULE_KIND (c) & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC); } + if (reduction_seen == -2) + error_at (OMP_CLAUSE_LOCATION (c), + "%qs clause specified together with % " + "% clause", "schedule"); pc = &OMP_CLAUSE_CHAIN (c); continue; case OMP_CLAUSE_NOGROUP: @@ -7693,6 +7761,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_ORDERED: + if (reduction_seen == -2) + error_at (OMP_CLAUSE_LOCATION (c), + "%qs clause specified together with % " + "% clause", "ordered"); + pc = &OMP_CLAUSE_CHAIN (c); + continue; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) { diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 1ae3db0e596..961b7f42c5b 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -336,6 +336,7 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data) case GIMPLE_OMP_MASTER: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_RETURN: case GIMPLE_OMP_ATOMIC_LOAD: diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 4243eb74d48..0ccbd6c6352 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -1799,9 +1799,6 @@ dump_gimple_omp_block (pretty_printer *buffer, gimple *gs, int spc, case GIMPLE_OMP_MASTER: pp_string (buffer, "#pragma omp master"); break; - case GIMPLE_OMP_TASKGROUP: - pp_string (buffer, "#pragma omp taskgroup"); - break; case GIMPLE_OMP_SECTION: pp_string (buffer, "#pragma omp section"); break; @@ -1880,6 +1877,34 @@ dump_gimple_omp_ordered (pretty_printer *buffer, gomp_ordered *gs, } } +/* Dump a GIMPLE_OMP_SCAN tuple on the pretty_printer BUFFER. */ + +static void +dump_gimple_omp_scan (pretty_printer *buffer, gomp_scan *gs, + int spc, dump_flags_t flags) +{ + if (flags & TDF_RAW) + dump_gimple_fmt (buffer, spc, flags, "%G <%+BODY <%S> >", gs, + gimple_omp_body (gs)); + else + { + if (gimple_omp_scan_clauses (gs)) + { + pp_string (buffer, "#pragma omp scan"); + dump_omp_clauses (buffer, gimple_omp_scan_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_RETURN tuple on the pretty_printer BUFFER. */ static void @@ -2652,6 +2677,11 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple *gs, int spc, flags); break; + case GIMPLE_OMP_SCAN: + dump_gimple_omp_scan (buffer, as_a (gs), spc, + flags); + break; + case GIMPLE_OMP_CRITICAL: dump_gimple_omp_critical (buffer, as_a (gs), spc, flags); diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c index 29f33b005e1..2b8f1e0b5c8 100644 --- a/gcc/gimple-walk.c +++ b/gcc/gimple-walk.c @@ -336,6 +336,16 @@ walk_gimple_op (gimple *stmt, walk_tree_fn callback_op, } break; + case GIMPLE_OMP_SCAN: + { + gomp_scan *scan_stmt = as_a (stmt); + ret = walk_tree (gimple_omp_scan_clauses_ptr (scan_stmt), + callback_op, wi, pset); + if (ret) + return ret; + } + break; + case GIMPLE_OMP_FOR: ret = walk_tree (gimple_omp_for_clauses_ptr (stmt), callback_op, wi, pset); @@ -650,6 +660,7 @@ walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, case GIMPLE_OMP_MASTER: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: diff --git a/gcc/gimple.c b/gcc/gimple.c index 8fae60fb848..63c8d5e85ae 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1108,6 +1108,25 @@ gimple_build_omp_return (bool wait_p) } +/* Build a GIMPLE_OMP_SCAN statement. + + BODY is the sequence of statements to be executed by the scan + construct. + CLAUSES are any of the construct's clauses. */ + +gomp_scan * +gimple_build_omp_scan (gimple_seq body, tree clauses) +{ + gomp_scan *p + = as_a (gimple_alloc (GIMPLE_OMP_SCAN, 0)); + gimple_omp_scan_set_clauses (p, clauses); + if (body) + gimple_omp_set_body (p, body); + + return p; +} + + /* Build a GIMPLE_OMP_SECTIONS statement. BODY is a sequence of section statements. @@ -1943,6 +1962,12 @@ gimple_copy (gimple *stmt) gimple_omp_ordered_set_clauses (as_a (copy), t); goto copy_omp_body; + case GIMPLE_OMP_SCAN: + t = gimple_omp_scan_clauses (as_a (stmt)); + t = unshare_expr (t); + gimple_omp_scan_set_clauses (as_a (copy), t); + goto copy_omp_body; + case GIMPLE_OMP_TASKGROUP: t = unshare_expr (gimple_omp_taskgroup_clauses (stmt)); gimple_omp_taskgroup_set_clauses (copy, t); diff --git a/gcc/gimple.def b/gcc/gimple.def index 78e3467f762..dd64419e8eb 100644 --- a/gcc/gimple.def +++ b/gcc/gimple.def @@ -331,6 +331,11 @@ DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK) /* OMP_RETURN marks the end of an OpenMP directive. */ DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT) +/* GIMPLE_OMP_SCAN represents #pragma omp scan + BODY is the sequence of statements inside the single section. + CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */ +DEFGSCODE(GIMPLE_OMP_SCAN, "gimple_omp_scan", GSS_OMP_SINGLE_LAYOUT) + /* OMP_SECTION represents #pragma omp section. BODY is the sequence of statements in the section body. */ DEFGSCODE(GIMPLE_OMP_SECTION, "gimple_omp_section", GSS_OMP) diff --git a/gcc/gimple.h b/gcc/gimple.h index 8b5c9e2190a..47070e7f409 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -741,7 +741,8 @@ struct GTY((tag("GSS_OMP_CONTINUE"))) tree control_use; }; -/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP. */ +/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_ORDERED, GIMPLE_OMP_TASKGROUP, + GIMPLE_OMP_SCAN. */ struct GTY((tag("GSS_OMP_SINGLE_LAYOUT"))) gimple_statement_omp_single_layout : public gimple_statement_omp @@ -773,6 +774,13 @@ struct GTY((tag("GSS_OMP_SINGLE_LAYOUT"))) stmt->code == GIMPLE_OMP_ORDERED. */ }; +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT"))) + gomp_scan : public gimple_statement_omp_single_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_SCAN. */ +}; + /* GIMPLE_OMP_ATOMIC_LOAD. Note: This is based on gimple, not g_s_omp, because g_s_omp @@ -1112,6 +1120,14 @@ is_a_helper ::test (gimple *gs) return gs->code == GIMPLE_OMP_ORDERED; } +template <> +template <> +inline bool +is_a_helper ::test (gimple *gs) +{ + return gs->code == GIMPLE_OMP_SCAN; +} + template <> template <> inline bool @@ -1330,6 +1346,14 @@ is_a_helper ::test (const gimple *gs) return gs->code == GIMPLE_OMP_ORDERED; } +template <> +template <> +inline bool +is_a_helper ::test (const gimple *gs) +{ + return gs->code == GIMPLE_OMP_SCAN; +} + template <> template <> inline bool @@ -1475,6 +1499,7 @@ 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); gimple *gimple_build_omp_return (bool); +gomp_scan *gimple_build_omp_scan (gimple_seq, tree); gomp_sections *gimple_build_omp_sections (gimple_seq, tree); gimple *gimple_build_omp_sections_switch (void); gomp_single *gimple_build_omp_single (gimple_seq, tree); @@ -4946,6 +4971,35 @@ gimple_omp_ordered_set_clauses (gomp_ordered *ord_stmt, tree clauses) } +/* Return the clauses associated with OMP_SCAN statement SCAN_STMT. */ + +static inline tree +gimple_omp_scan_clauses (const gomp_scan *scan_stmt) +{ + return scan_stmt->clauses; +} + + +/* Return a pointer to the clauses associated with OMP scan statement + ORD_STMT. */ + +static inline tree * +gimple_omp_scan_clauses_ptr (gomp_scan *scan_stmt) +{ + return &scan_stmt->clauses; +} + + +/* Set CLAUSES to be the clauses associated with OMP scan statement + ORD_STMT. */ + +static inline void +gimple_omp_scan_set_clauses (gomp_scan *scan_stmt, tree clauses) +{ + scan_stmt->clauses = clauses; +} + + /* Return the clauses associated with OMP_TASKGROUP statement GS. */ static inline tree @@ -6379,6 +6433,7 @@ gimple_return_set_retval (greturn *gs, tree retval) case GIMPLE_OMP_TASKGROUP: \ case GIMPLE_OMP_ORDERED: \ case GIMPLE_OMP_CRITICAL: \ + case GIMPLE_OMP_SCAN: \ case GIMPLE_OMP_RETURN: \ case GIMPLE_OMP_ATOMIC_LOAD: \ case GIMPLE_OMP_ATOMIC_STORE: \ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 0f3e917bc22..3b4fdc7a509 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -118,6 +118,9 @@ enum gimplify_omp_var_data GOVD_CONDTEMP = 0x1000000, + /* Flag for GOVD_REDUCTION: inscan seen in {in,ex}clusive clause. */ + GOVD_REDUCTION_INSCAN = 0x2000000, + GOVD_DATA_SHARE_CLASS = (GOVD_SHARED | GOVD_PRIVATE | GOVD_FIRSTPRIVATE | GOVD_LASTPRIVATE | GOVD_REDUCTION | GOVD_LINEAR | GOVD_LOCAL) @@ -5492,6 +5495,7 @@ is_gimple_stmt (tree t) case OMP_SIMD: case OMP_DISTRIBUTE: case OACC_LOOP: + case OMP_SCAN: case OMP_SECTIONS: case OMP_SECTION: case OMP_SINGLE: @@ -8119,13 +8123,13 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, case OMP_DISTRIBUTE: error_at (OMP_CLAUSE_LOCATION (c), "conditional % clause on " - "% construct"); + "%qs construct", "distribute"); OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0; break; case OMP_TASKLOOP: error_at (OMP_CLAUSE_LOCATION (c), "conditional % clause on " - "% construct"); + "%qs construct", "taskloop"); OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 0; break; default: @@ -8242,6 +8246,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, OMP_CLAUSE_REDUCTION_TASK (c) = 0; } } + if (OMP_CLAUSE_REDUCTION_INSCAN (c)) + switch (code) + { + case OMP_SECTIONS: + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause on " + "%qs construct", "sections"); + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; + break; + case OMP_PARALLEL: + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause on " + "%qs construct", "parallel"); + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; + break; + case OMP_TEAMS: + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause on " + "%qs construct", "teams"); + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; + break; + case OMP_TASKLOOP: + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause on " + "%qs construct", "taskloop"); + OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; + break; + default: + break; + } /* FALLTHRU */ case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: @@ -9290,6 +9324,36 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p, ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c); break; + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: + decl = OMP_CLAUSE_DECL (c); + { + splay_tree_node n = splay_tree_lookup (outer_ctx->variables, + (splay_tree_key) decl); + if (n == NULL || (n->value & GOVD_REDUCTION) == 0) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qD specified in %qs clause but not in % " + "% clause on the containing construct", + decl, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); + remove = true; + } + else + { + n->value |= GOVD_REDUCTION_INSCAN; + if (outer_ctx->region_type == ORT_SIMD + && outer_ctx->outer_context + && outer_ctx->outer_context->region_type == ORT_WORKSHARE) + { + n = splay_tree_lookup (outer_ctx->outer_context->variables, + (splay_tree_key) decl); + if (n && (n->value & GOVD_REDUCTION) != 0) + n->value |= GOVD_REDUCTION_INSCAN; + } + } + } + break; + default: gcc_unreachable (); } @@ -9683,7 +9747,9 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, enum tree_code code) { struct gimplify_omp_ctx *ctx = gimplify_omp_ctxp; + tree *orig_list_p = list_p; tree c, decl; + bool has_inscan_reductions = false; if (body) { @@ -10024,6 +10090,21 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, break; case OMP_CLAUSE_REDUCTION: + if (OMP_CLAUSE_REDUCTION_INSCAN (c)) + { + decl = OMP_CLAUSE_DECL (c); + n = splay_tree_lookup (ctx->variables, (splay_tree_key) decl); + if ((n->value & GOVD_REDUCTION_INSCAN) == 0) + { + remove = true; + error_at (OMP_CLAUSE_LOCATION (c), + "%qD specified in % % clause " + "but not in % directive clause", decl); + break; + } + has_inscan_reductions = true; + } + /* FALLTHRU */ case OMP_CLAUSE_IN_REDUCTION: case OMP_CLAUSE_TASK_REDUCTION: decl = OMP_CLAUSE_DECL (c); @@ -10105,6 +10186,8 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, case OMP_CLAUSE_TILE: case OMP_CLAUSE_IF_PRESENT: case OMP_CLAUSE_FINALIZE: + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: break; default: @@ -10123,6 +10206,18 @@ gimplify_adjust_omp_clauses (gimple_seq *pre_p, gimple_seq body, tree *list_p, data.pre_p = pre_p; splay_tree_foreach (ctx->variables, gimplify_adjust_omp_clauses_1, &data); + if (has_inscan_reductions) + for (c = *orig_list_p; c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR + && !OMP_CLAUSE_LINEAR_NO_COPYIN (c)) + { + error_at (OMP_CLAUSE_LOCATION (c), + "% % clause used together with " + "% clause for a variable other than loop " + "iterator"); + break; + } + gimplify_omp_ctxp = ctx->outer_context; delete_omp_context (ctx); } @@ -13124,6 +13219,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, case OMP_MASTER: case OMP_ORDERED: case OMP_CRITICAL: + case OMP_SCAN: { gimple_seq body = NULL; gimple *g; @@ -13150,6 +13246,14 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, OMP_CRITICAL_NAME (*expr_p), OMP_CRITICAL_CLAUSES (*expr_p)); break; + case OMP_SCAN: + gimplify_scan_omp_clauses (&OMP_SCAN_CLAUSES (*expr_p), + pre_p, ORT_WORKSHARE, OMP_SCAN); + gimplify_adjust_omp_clauses (pre_p, body, + &OMP_SCAN_CLAUSES (*expr_p), + OMP_SCAN); + g = gimple_build_omp_scan (body, OMP_SCAN_CLAUSES (*expr_p)); + break; default: gcc_unreachable (); } @@ -13514,6 +13618,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, && code != OMP_TASKGROUP && code != OMP_ORDERED && code != OMP_PARALLEL + && code != OMP_SCAN && code != OMP_SECTIONS && code != OMP_SECTION && code != OMP_SINGLE); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index a7f35ffe416..962eadae02f 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -2574,6 +2574,10 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) if (ctx != NULL) { + if (gimple_code (ctx->stmt) == GIMPLE_OMP_SCAN + && ctx->outer + && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR) + ctx = ctx->outer; if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD) { @@ -2600,7 +2604,8 @@ check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx) } } else if (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD - || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE) + || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE + || gimple_code (stmt) == GIMPLE_OMP_SCAN) return true; error_at (gimple_location (stmt), "OpenMP constructs other than %<#pragma omp ordered simd%>" @@ -3328,6 +3333,7 @@ scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, case GIMPLE_OMP_MASTER: case GIMPLE_OMP_ORDERED: case GIMPLE_OMP_CRITICAL: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_GRID_BODY: ctx = new_omp_context (stmt, ctx); scan_omp (gimple_omp_body_ptr (stmt), ctx); @@ -10834,6 +10840,15 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) gcc_assert (ctx); lower_omp_ordered (gsi_p, ctx); break; + case GIMPLE_OMP_SCAN: + ctx = maybe_lookup_ctx (stmt); + gcc_assert (ctx); + gsi_insert_seq_after (gsi_p, gimple_omp_body (stmt), GSI_SAME_STMT); + if (gimple_omp_scan_clauses (as_a (stmt))) + sorry_at (gimple_location (stmt), + "%<#pragma omp scan%> not supported yet"); + gsi_replace (gsi_p, gimple_build_nop (), true); + break; case GIMPLE_OMP_CRITICAL: ctx = maybe_lookup_ctx (stmt); gcc_assert (ctx); @@ -10925,6 +10940,7 @@ lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx) || gimple_code (up->stmt) == GIMPLE_OMP_CRITICAL || gimple_code (up->stmt) == GIMPLE_OMP_TASKGROUP || gimple_code (up->stmt) == GIMPLE_OMP_SECTION + || gimple_code (up->stmt) == GIMPLE_OMP_SCAN || (gimple_code (up->stmt) == GIMPLE_OMP_TARGET && (gimple_omp_target_kind (up->stmt) == GF_OMP_TARGET_KIND_DATA))) @@ -11195,6 +11211,7 @@ diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS: @@ -11255,6 +11272,7 @@ diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p, case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 072884dac2a..191fec2f7b0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-06-10 Jakub Jelinek + + * c-c++-common/gomp/scan-1.c: New test. + * c-c++-common/gomp/scan-2.c: New test. + * c-c++-common/gomp/scan-3.c: New test. + * c-c++-common/gomp/scan-4.c: New test. + 2019-06-10 Martin Liska * gcc.dg/no_profile_instrument_function-attr-1.c: Fix diff --git a/gcc/testsuite/c-c++-common/gomp/scan-1.c b/gcc/testsuite/c-c++-common/gomp/scan-1.c new file mode 100644 index 00000000000..17804e34ba9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-1.c @@ -0,0 +1,209 @@ +int a, b; + +void +f1 (void) +{ + #pragma omp scan inclusive (a) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ + #pragma omp scan exclusive (b) /* { dg-error "'#pragma omp scan' may only be used in a loop construct with 'inscan' 'reduction' clause" } */ +} + +void +f2 (int *c, int *d, int *e, int *f) +{ + int i, l = 1; + #pragma omp for reduction (inscan, +: a) reduction (+: b) /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */ + for (i = 0; i < 64; i++) + { + { b++; a += c[i]; } + #pragma omp scan inclusive (a) /* { dg-error "" } */ + d[i] = a; + } + #pragma omp for reduction (+: a) reduction (inscan, +: b) /* { dg-error "'inscan' and non-'inscan' 'reduction' clauses on the same construct" } */ + for (i = 0; i < 64; i++) + { + { a++; b += c[i]; } + #pragma omp scan inclusive (b) /* { dg-error "" } */ + d[i] = b; + } + #pragma omp for reduction (inscan, +: e[:2]) /* { dg-error "'inscan' 'reduction' clause with array section" } */ + for (i = 0; i < 64; ++i) + { + { e[0] += c[i]; e[1] += c[i]; } + #pragma omp scan inclusive (a, e[:2]) /* { dg-error "" } */ + { d[i] = e[0]; f[i] = e[1]; } + } + #pragma omp for reduction (inscan, +: a) ordered /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */ + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) /* { dg-error "" } */ + d[i] = a; + } + #pragma omp for reduction (inscan, +: a) ordered(1) /* { dg-error "'ordered' clause specified together with 'inscan' 'reduction' clause" } */ + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) /* { dg-error "" } */ + d[i] = a; + } + #pragma omp for reduction (inscan, +: a) schedule(static) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */ + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) /* { dg-error "" } */ + d[i] = a; + } + #pragma omp for reduction (inscan, +: a) schedule(static, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */ + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) /* { dg-error "" } */ + d[i] = a; + } + #pragma omp for reduction (inscan, +: a) schedule(nonmonotonic: dynamic, 2) /* { dg-error "'schedule' clause specified together with 'inscan' 'reduction' clause" } */ + for (i = 0; i < 64; i++) + { + a += c[i]; + #pragma omp scan inclusive (a) /* { dg-error "" } */ + d[i] = a; + } + #pragma omp for reduction (inscan, +: a) linear (l) /* { dg-error "'inscan' 'reduction' clause used together with 'linear' clause for a variable other than loop iterator" } */ + for (i = 0; i < 64; i++) + { + { a += c[i]; ++l; } + #pragma omp scan inclusive (a) + d[i] = a; + } +} + +void +f3 (int *c, int *d) +{ + int i; + #pragma omp teams reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'teams' construct" } */ + ; + #pragma omp parallel reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'parallel' construct" } */ + ; + #pragma omp sections reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'sections' construct" } */ + { + #pragma omp section + ; + } + #pragma omp target parallel for reduction (inscan, +: a) map (c[:64], d[:64]) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */ + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-error "" } */ + a += c[i]; + } + #pragma omp teams + { + #pragma omp distribute parallel for reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */ + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-error "" } */ + a += c[i]; + } + #pragma omp distribute parallel for simd reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on construct other than 'for', 'simd', 'for simd', 'parallel for', 'parallel for simd'" } */ + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-error "" } */ + a += c[i]; + } + } +} + +void +f4 (int *c, int *d) +{ + int i; + #pragma omp taskloop reduction (inscan, +: a) /* { dg-error "'inscan' 'reduction' clause on 'taskloop' construct" } */ + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-error "" } */ + a += c[i]; + } +} + +void +f5 (int *c, int *d) +{ + int i; + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a, b) /* { dg-error "'b' specified in 'exclusive' clause but not in 'inscan' 'reduction' clause on the containing construct" } */ + a += c[i]; + } +} + +void +f6 (int *c, int *d) +{ + int i; + #pragma omp simd reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) + a += c[i]; + } +} + +void +f7 (void) +{ + int i; + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + if (i == 23) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */ + continue; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */ + else if (i == 27) + goto l1; /* { dg-error "invalid branch to/from OpenMP structured block" } */ + #pragma omp scan exclusive (a) + { + l1: a = 0; /* { dg-error "jump to label 'l1'" "" { target c++ } } */ + if (i == 33) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */ + continue; /* { dg-error "invalid branch to/from OpenMP structured block" "" { target c } } */ + } + } +} + +void +f8 (int *c, int *d, int *e, int *f) +{ + int i; + #pragma omp for reduction (inscan, +: a, b) /* { dg-error "'b' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (i = 0; i < 64; i++) + { + { a += c[i]; b += d[i]; } + #pragma omp scan inclusive (a) inclusive (b) /* { dg-error "expected end of line before 'inclusive'" } */ + { e[i] = a; f[i] = b; } + } + #pragma omp for reduction (inscan, +: a, b) /* { dg-error "'.' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } */ + for (i = 0; i < 64; i++) + { + { a += c[i]; b += d[i]; } + #pragma omp scan /* { dg-error "expected 'inclusive' or 'exclusive' clause before end of line" } */ + { e[i] = a; f[i] = b; } + } +} + +void +f9 (void) +{ + int i; + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + if (i == 23) /* { dg-error "invalid exit from OpenMP structured block" "" { target c++ } .+1 } */ + break; /* { dg-error "break statement used with OpenMP for loop" "" { target c } } */ + #pragma omp scan exclusive (a) + a++; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/scan-2.c b/gcc/testsuite/c-c++-common/gomp/scan-2.c new file mode 100644 index 00000000000..14b74a5b87f --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-2.c @@ -0,0 +1,14 @@ +int a, b; + +void +f1 (int *c, int *d) +{ + int i; + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */ + a += c[i]; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/scan-3.c b/gcc/testsuite/c-c++-common/gomp/scan-3.c new file mode 100644 index 00000000000..4865e08ea2c --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-3.c @@ -0,0 +1,14 @@ +int a, b; + +void +f1 (int *c, int *d) +{ + int i; + #pragma omp for reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan inclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */ + a += c[i]; + } +} diff --git a/gcc/testsuite/c-c++-common/gomp/scan-4.c b/gcc/testsuite/c-c++-common/gomp/scan-4.c new file mode 100644 index 00000000000..32d40065786 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/scan-4.c @@ -0,0 +1,14 @@ +int a, b; + +void +f1 (int *c, int *d) +{ + int i; + #pragma omp for simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + d[i] = a; + #pragma omp scan exclusive (a) /* { dg-message "sorry, unimplemented: '#pragma omp scan' not supported yet" } */ + a += c[i]; + } +} diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 26cfa7ea19f..977b768128e 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -306,13 +306,19 @@ enum omp_clause_code { OpenMP clause: map ({alloc:,to:,from:,tofrom:,}variable-list). */ OMP_CLAUSE_MAP, - /* OpenACC clause: use_device (variable_list). + /* OpenACC clause: use_device (variable-list). OpenMP clause: use_device_ptr (variable-list). */ OMP_CLAUSE_USE_DEVICE_PTR, /* OpenMP clause: is_device_ptr (variable-list). */ OMP_CLAUSE_IS_DEVICE_PTR, + /* OpenMP clause: inclusive (variable-list). */ + OMP_CLAUSE_INCLUSIVE, + + /* OpenMP clause: exclusive (variable-list). */ + OMP_CLAUSE_EXCLUSIVE, + /* Internal structure to hold OpenACC cache directive's variable-list. #pragma acc cache (variable-list). */ OMP_CLAUSE__CACHE_, diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 719846ac9a2..52f45a73b1d 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1638,6 +1638,12 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id) gimple_omp_ordered_clauses (as_a (stmt))); break; + case GIMPLE_OMP_SCAN: + s1 = remap_gimple_seq (gimple_omp_body (stmt), id); + copy = gimple_build_omp_scan + (s1, gimple_omp_scan_clauses (as_a (stmt))); + break; + case GIMPLE_OMP_SECTION: s1 = remap_gimple_seq (gimple_omp_body (stmt), id); copy = gimple_build_omp_section (s1); @@ -4365,6 +4371,7 @@ estimate_num_insns (gimple *stmt, eni_weights *weights) case GIMPLE_OMP_MASTER: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 5cf2e3dbdfd..22aa6423756 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1619,6 +1619,7 @@ convert_nonlocal_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: walk_body (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op, info, gimple_omp_body_ptr (stmt)); break; @@ -2322,6 +2323,7 @@ convert_local_reference_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p, case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: walk_body (convert_local_reference_stmt, convert_local_reference_op, info, gimple_omp_body_ptr (stmt)); break; @@ -2831,6 +2833,7 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p, case GIMPLE_OMP_MASTER: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED: + case GIMPLE_OMP_SCAN: case GIMPLE_OMP_CRITICAL: walk_body (convert_gimple_call, NULL, info, gimple_omp_body_ptr (stmt)); break; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 455579c1290..1e6c96813bb 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -467,6 +467,12 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags) case OMP_CLAUSE_IS_DEVICE_PTR: name = "is_device_ptr"; goto print_remap; + case OMP_CLAUSE_INCLUSIVE: + name = "inclusive"; + goto print_remap; + case OMP_CLAUSE_EXCLUSIVE: + name = "exclusive"; + goto print_remap; case OMP_CLAUSE__LOOPTEMP_: name = "_looptemp_"; goto print_remap; @@ -3308,6 +3314,14 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, pp_string (pp, "#pragma omp section"); goto dump_omp_body; + case OMP_SCAN: + if (OMP_SCAN_CLAUSES (node)) + { + pp_string (pp, "#pragma omp scan"); + dump_omp_clauses (pp, OMP_SCAN_CLAUSES (node), spc, flags); + } + goto dump_omp_body; + case OMP_MASTER: pp_string (pp, "#pragma omp master"); goto dump_omp_body; diff --git a/gcc/tree.c b/gcc/tree.c index 43ce44fcee4..5d955535acc 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -300,6 +300,8 @@ unsigned const char omp_clause_num_ops[] = 2, /* OMP_CLAUSE_MAP */ 1, /* OMP_CLAUSE_USE_DEVICE_PTR */ 1, /* OMP_CLAUSE_IS_DEVICE_PTR */ + 1, /* OMP_CLAUSE_INCLUSIVE */ + 1, /* OMP_CLAUSE_EXCLUSIVE */ 2, /* OMP_CLAUSE__CACHE_ */ 2, /* OMP_CLAUSE_GANG */ 1, /* OMP_CLAUSE_ASYNC */ @@ -378,6 +380,8 @@ const char * const omp_clause_code_name[] = "map", "use_device_ptr", "is_device_ptr", + "inclusive", + "exclusive", "_cache_", "gang", "async", @@ -12295,6 +12299,8 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, case OMP_CLAUSE_LINK: case OMP_CLAUSE_USE_DEVICE_PTR: case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_INCLUSIVE: + case OMP_CLAUSE_EXCLUSIVE: case OMP_CLAUSE__LOOPTEMP_: case OMP_CLAUSE__REDUCTEMP_: case OMP_CLAUSE__CONDTEMP_: diff --git a/gcc/tree.def b/gcc/tree.def index 1d6ddedd965..10a14fc23b0 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1191,6 +1191,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 scan + Operand 0: OMP_SCAN_BODY: Scan body. + Operand 1: OMP_SCAN_CLAUSES: List of clauses. */ +DEFTREECODE (OMP_SCAN, "omp_scan", tcc_statement, 2) + /* OpenMP - #pragma omp section Operand 0: OMP_SECTION_BODY: Section body. */ DEFTREECODE (OMP_SECTION, "omp_section", tcc_statement, 1) diff --git a/gcc/tree.h b/gcc/tree.h index 5b50941aa83..d45a391428e 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1344,7 +1344,7 @@ class auto_suppress_location_wrappers #define OMP_BODY(NODE) \ TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_MASTER), 0) #define OMP_CLAUSES(NODE) \ - TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_TASKGROUP), 1) + TREE_OPERAND (TREE_RANGE_CHECK (NODE, OACC_PARALLEL, OMP_SCAN), 1) /* Generic accessors for OMP nodes that keep clauses as operand 0. */ #define OMP_STANDALONE_CLAUSES(NODE) \ @@ -1435,6 +1435,9 @@ class auto_suppress_location_wrappers #define OMP_TARGET_EXIT_DATA_CLAUSES(NODE)\ TREE_OPERAND (OMP_TARGET_EXIT_DATA_CHECK (NODE), 0) +#define OMP_SCAN_BODY(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 0) +#define OMP_SCAN_CLAUSES(NODE) TREE_OPERAND (OMP_SCAN_CHECK (NODE), 1) + #define OMP_CLAUSE_SIZE(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \ OMP_CLAUSE_FROM, \