From bf38f7e9aa76856a7c8ac57988600ce9de7cafbd Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 10 Jun 2019 14:20:30 +0200 Subject: 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 --- gcc/c/ChangeLog | 11 +++++++ gcc/c/c-parser.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- gcc/c/c-typeck.c | 65 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 151 insertions(+), 12 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 5a0dabb..103634e 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 84ee576..df1a304 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 0dd86f0..6abfd10 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); -- cgit v1.1