From patchwork Mon Jun 10 12:23:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1113074 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-502685-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="NY4S9KRw"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45MskQ6HWFz9sBp for ; Mon, 10 Jun 2019 22:23:56 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; q=dns; s=default; b=M0oIiPUYUA6hxVlM1W8+3IqRS9wl8mgC6uLBVzh4XnD rgOoSKh/VKFdElEA733irBMU8KiHxPSwfq3LzZpww2BEnSGANGOlgzCkcDFC1P/9 C5bkD7tkGdzcaMv3Iqnr/ERxMOpX9v6wVjqZE/amglqD5H0YwwiGxgtnoFCmEWGk = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; s=default; bh=ATeaZ5kfkZWj3bXpQLFS1FQWd0I=; b=NY4S9KRwQ3qHSasYm ZyvyPqQstV8L29l6FFndXCUufa71pgxAN8mmjLJpGZhVVK9fbcln9RKRfBFT2Tny TYhmbz+s1dOkMNApivAQpLGRLm9aSET9X7kelt5Dtw0JiYY9cIFbFmX7rJPDVnZJ 3/bidEl2a9zzQSAaeCu/cP0Pao= Received: (qmail 36510 invoked by alias); 10 Jun 2019 12:23:47 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 36501 invoked by uid 89); 10 Jun 2019 12:23:46 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=tre, c-parser.c, cparserc, UD:c-parser.c X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jun 2019 12:23:39 +0000 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B5DE87FDFB for ; Mon, 10 Jun 2019 12:23:29 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-52.ams2.redhat.com [10.36.116.52]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 897D91001B11 for ; Mon, 10 Jun 2019 12:23:26 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id x5ACNOKV006513 for ; Mon, 10 Jun 2019 14:23:24 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id x5ACNLEm006512 for gcc-patches@gcc.gnu.org; Mon, 10 Jun 2019 14:23:21 +0200 Date: Mon, 10 Jun 2019 14:23:21 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [committed] Add parsing and diagnostics for #pragma omp scan and reduction(inscan, ...) Message-ID: <20190610122321.GA19695@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.11.3 (2019-02-01) X-IsSubscribed: yes Hi! The following patch does parsing and diagnostics for C/C++ #pragma omp scan and reduction(inscan, ...) clauses. omp-low.c and further handling is not implemented so far, we just sorry_at on those constructs if we don't diagnose any errors on those. Tested on x86_64-linux, committed to trunk. Trying to handle it in simd constructs will be my next task. 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. 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. Jakub --- gcc/tree.def.jj 2019-06-07 16:55:05.817651838 +0200 +++ gcc/tree.def 2019-06-07 18:20:48.952775949 +0200 @@ -1191,6 +1191,11 @@ DEFTREECODE (OMP_SINGLE, "omp_single", t 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) --- gcc/tree-core.h.jj 2019-06-07 16:55:05.817651838 +0200 +++ gcc/tree-core.h 2019-06-07 18:20:48.965775746 +0200 @@ -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_, --- gcc/tree.h.jj 2019-06-07 16:55:05.582655540 +0200 +++ gcc/tree.h 2019-06-07 18:20:48.956775887 +0200 @@ -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, \ --- gcc/tree.c.jj 2019-06-07 16:55:06.836635784 +0200 +++ gcc/tree.c 2019-06-07 18:20:48.963775777 +0200 @@ -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 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_: --- gcc/tree-nested.c.jj 2019-06-07 16:55:05.786652326 +0200 +++ gcc/tree-nested.c 2019-06-07 18:20:48.951775965 +0200 @@ -1619,6 +1619,7 @@ convert_nonlocal_reference_stmt (gimple_ 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_stm 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_iterato 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; --- gcc/tree-pretty-print.c.jj 2019-06-07 16:55:05.817651838 +0200 +++ gcc/tree-pretty-print.c 2019-06-07 18:20:48.957775871 +0200 @@ -467,6 +467,12 @@ dump_omp_clause (pretty_printer *pp, tre 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, t 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; --- gcc/gimple.def.jj 2019-06-07 16:55:05.555655966 +0200 +++ gcc/gimple.def 2019-06-07 18:20:48.957775871 +0200 @@ -331,6 +331,11 @@ DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_t /* 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) --- gcc/gimple.h.jj 2019-06-07 16:55:05.878650877 +0200 +++ gcc/gimple.h 2019-06-07 18:20:48.954775918 +0200 @@ -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 @@ -1115,6 +1123,14 @@ is_a_helper ::test (gimp template <> template <> inline bool +is_a_helper ::test (gimple *gs) +{ + return gs->code == GIMPLE_OMP_SCAN; +} + +template <> +template <> +inline bool is_a_helper ::test (gimple *gs) { return gs->code == GIMPLE_OMP_FOR; @@ -1333,6 +1349,14 @@ is_a_helper ::test template <> template <> inline bool +is_a_helper ::test (const gimple *gs) +{ + return gs->code == GIMPLE_OMP_SCAN; +} + +template <> +template <> +inline bool is_a_helper ::test (const gimple *gs) { return gs->code == GIMPLE_OMP_FOR; @@ -1475,6 +1499,7 @@ gimple *gimple_build_omp_taskgroup (gimp 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_ord } +/* 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, t 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: \ --- gcc/gimple.c.jj 2019-06-07 16:55:05.856651224 +0200 +++ gcc/gimple.c 2019-06-07 18:20:48.963775777 +0200 @@ -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); --- gcc/gimple-walk.c.jj 2019-06-07 16:55:05.838651507 +0200 +++ gcc/gimple-walk.c 2019-06-07 18:20:48.952775949 +0200 @@ -336,6 +336,16 @@ walk_gimple_op (gimple *stmt, walk_tree_ } 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 * 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: --- gcc/gimple-pretty-print.c.jj 2019-06-07 16:55:05.516656580 +0200 +++ gcc/gimple-pretty-print.c 2019-06-07 18:20:48.953775934 +0200 @@ -1799,9 +1799,6 @@ dump_gimple_omp_block (pretty_printer *b 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 } } +/* 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 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); --- gcc/gimple-low.c.jj 2019-06-07 16:55:05.762652705 +0200 +++ gcc/gimple-low.c 2019-06-07 18:20:48.965775746 +0200 @@ -336,6 +336,7 @@ lower_stmt (gimple_stmt_iterator *gsi, s 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: --- gcc/tree-inline.c.jj 2019-06-07 16:55:05.817651838 +0200 +++ gcc/tree-inline.c 2019-06-07 18:20:48.967775715 +0200 @@ -1638,6 +1638,12 @@ remap_gimple_stmt (gimple *stmt, copy_bo 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_we 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: --- gcc/gimplify.c.jj 2019-06-07 16:55:05.767652626 +0200 +++ gcc/gimplify.c 2019-06-10 10:29:34.524052038 +0200 @@ -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, 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, 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, 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 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 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 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 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 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 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 && code != OMP_TASKGROUP && code != OMP_ORDERED && code != OMP_PARALLEL + && code != OMP_SCAN && code != OMP_SECTIONS && code != OMP_SECTION && code != OMP_SINGLE); --- gcc/omp-low.c.jj 2019-06-07 16:55:05.580655572 +0200 +++ gcc/omp-low.c 2019-06-10 09:56:42.101534802 +0200 @@ -2574,6 +2574,10 @@ check_omp_nesting_restrictions (gimple * 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 * } } 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 *g 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 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 || 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 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 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: --- gcc/c-family/c-pragma.h.jj 2019-06-07 16:55:05.493656943 +0200 +++ gcc/c-family/c-pragma.h 2019-06-07 18:20:48.964775762 +0200 @@ -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, --- gcc/c-family/c-pragma.c.jj 2019-06-07 16:55:05.493656943 +0200 +++ gcc/c-family/c-pragma.c 2019-06-07 18:20:48.964775762 +0200 @@ -1320,6 +1320,7 @@ static const struct omp_pragma_def omp_p { "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 }, --- gcc/c-family/c-omp.c.jj 2019-06-07 16:55:05.494656927 +0200 +++ gcc/c-family/c-omp.c 2019-06-07 20:07:48.015281440 +0200 @@ -1659,6 +1659,18 @@ c_omp_split_clauses (location_t loc, enu 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, enu = 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, enu = 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, enu = 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; } --- gcc/c/c-parser.c.jj 2019-06-07 16:55:05.762652705 +0200 +++ gcc/c/c-parser.c 2019-06-07 18:20:48.961775809 +0200 @@ -11494,6 +11494,13 @@ c_parser_pragma (c_parser *parser, enum 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 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 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 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 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); --- gcc/c/c-typeck.c.jj 2019-06-07 16:55:05.763652689 +0200 +++ gcc/c/c-typeck.c 2019-06-08 14:38:33.508202067 +0200 @@ -13661,13 +13661,15 @@ c_finish_omp_clauses (tree clauses, enum 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 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 } 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 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 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 = 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 & ~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 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); --- gcc/cp/parser.c.jj 2019-06-06 11:06:32.625453254 +0200 +++ gcc/cp/parser.c 2019-06-10 13:13:56.254448877 +0200 @@ -33773,11 +33773,7 @@ cp_parser_omp_clause_reduction (cp_parse 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 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 *parse 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 *parse 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 *parse } 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, enu 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 " --- gcc/cp/semantics.c.jj 2019-05-29 15:30:56.095595833 +0200 +++ gcc/cp/semantics.c 2019-06-10 11:37:04.579601901 +0200 @@ -6126,10 +6126,13 @@ finish_omp_clauses (tree clauses, enum c 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 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 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_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 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 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 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_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 } 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) { --- gcc/cp/pt.c.jj 2019-06-06 11:06:32.623453285 +0200 +++ gcc/cp/pt.c 2019-06-10 12:50:08.657061784 +0200 @@ -16323,6 +16323,8 @@ tsubst_omp_clauses (tree clauses, enum c 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 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_f 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, --- gcc/testsuite/c-c++-common/gomp/scan-1.c.jj 2019-06-08 14:17:19.317840877 +0200 +++ gcc/testsuite/c-c++-common/gomp/scan-1.c 2019-06-10 13:12:43.928577054 +0200 @@ -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++; + } +} --- gcc/testsuite/c-c++-common/gomp/scan-2.c.jj 2019-06-10 10:42:12.194963693 +0200 +++ gcc/testsuite/c-c++-common/gomp/scan-2.c 2019-06-10 10:43:38.807582349 +0200 @@ -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]; + } +} --- gcc/testsuite/c-c++-common/gomp/scan-3.c.jj 2019-06-10 10:43:17.580920885 +0200 +++ gcc/testsuite/c-c++-common/gomp/scan-3.c 2019-06-10 10:43:11.901011471 +0200 @@ -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]; + } +} --- gcc/testsuite/c-c++-common/gomp/scan-4.c.jj 2019-06-10 10:43:24.083817173 +0200 +++ gcc/testsuite/c-c++-common/gomp/scan-4.c 2019-06-10 10:43:30.168720127 +0200 @@ -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]; + } +}