From patchwork Fri Oct 8 16:14:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 46013 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3837C3857C6A for ; Fri, 8 Oct 2021 16:15:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3837C3857C6A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1633709728; bh=ZS/DQ9XuFAc+RlxzOVZj4I51oAZq/+XzAycvsHfZyhw=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=sqrSkGMH6xdIoqEru/eHsbnFxEW7FtcPNie85pTVB+/nVOXwSykRcRAqDoSfw2SGr jToZVrSx4sga83s0rak3ye6Q/tw44JsZHgWECpOGQ8ijszxu1gbLdvybchA3cBmw6U 9qVFqjtFyoJDOFm7Z+J6cKF7nc1Q1taC/zcEJr8I= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 242B23858D39 for ; Fri, 8 Oct 2021 16:14:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 242B23858D39 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-178-9jbpNemWMxm82G6GZm4TrA-1; Fri, 08 Oct 2021 12:14:56 -0400 X-MC-Unique: 9jbpNemWMxm82G6GZm4TrA-1 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 mimecast-mx01.redhat.com (Postfix) with ESMTPS id 516991927800; Fri, 8 Oct 2021 16:14:55 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.193.109]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5C61D10013C1; Fri, 8 Oct 2021 16:14:53 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 198GEp3f1179234 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 8 Oct 2021 18:14:51 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 198GEo6b1179233; Fri, 8 Oct 2021 18:14:50 +0200 Date: Fri, 8 Oct 2021 18:14:49 +0200 To: Chung-Lin Tang , Tobias Burnus , gcc-patches Subject: [PATCH] openmp: Add support for OpenMP 5.1 structured-block-sequences Message-ID: <20211008161449.GH304296@tucnak> References: <8d20877d-d52e-d90c-8a4e-a38f43921df1@codesourcery.com> <20211007170905.GZ304296@tucnak> MIME-Version: 1.0 In-Reply-To: <20211007170905.GZ304296@tucnak> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.5 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi! Related to this is the addition of structured-block-sequence in OpenMP 5.1, which doesn't change anything for Fortran, but for C/C++ allows multiple statements instead of just one possibly compound around the separating directives (section and scan). The following patch implements that, will commit to trunk if it passes bootstrap/regtest. I've also made some updates to the OpenMP 5.1 support list in libgomp.texi. 2021-10-08 Jakub Jelinek gcc/c/ * c-parser.c (c_parser_omp_structured_block_sequence): New function. (c_parser_omp_scan_loop_body): Use it. (c_parser_omp_sections_scope): Likewise. gcc/cp/ * parser.c (cp_parser_omp_structured_block): Remove disallow_omp_attrs argument. (cp_parser_omp_structured_block_sequence): New function. (cp_parser_omp_scan_loop_body): Use it. (cp_parser_omp_sections_scope): Likewise. gcc/testsuite/ * c-c++-common/gomp/sections1.c (foo): Don't expect errors on multiple statements in between section directive(s). Add testcases for invalid no statements in between section directive(s). * gcc.dg/gomp/sections-2.c (foo): Don't expect errors on multiple statements in between section directive(s). * g++.dg/gomp/sections-2.C (foo): Likewise. * g++.dg/gomp/attrs-6.C (foo): Add testcases for multiple statements in between section directive(s). (bar): Add testcases for multiple statements in between scan directive. * g++.dg/gomp/attrs-7.C (bar): Adjust expected error recovery. libgomp/ * libgomp.texi (OpenMP 5.1): Mention implemented support for structured block sequences in C/C++. Mention support for unconstrained/reproducible modifiers on order clause. Mention partial (C/C++ only) support of extentensions to atomics construct. Mention partial (C/C++ on clause only) support of align/allocator modifiers on allocate clause. Jakub --- gcc/c/c-parser.c.jj 2021-10-07 12:52:34.923913144 +0200 +++ gcc/c/c-parser.c 2021-10-08 13:56:43.989987499 +0200 @@ -18976,6 +18976,31 @@ c_parser_omp_flush (c_parser *parser) c_finish_omp_flush (loc, mo); } +/* Parse an OpenMP structured block sequence. KIND is the corresponding + separating directive. */ + +static tree +c_parser_omp_structured_block_sequence (c_parser *parser, + enum pragma_kind kind) +{ + tree stmt = push_stmt_list (); + c_parser_statement (parser, NULL); + do + { + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + break; + if (c_parser_next_token_is (parser, CPP_EOF)) + break; + + if (kind != PRAGMA_NONE + && c_parser_peek_token (parser)->pragma_kind == kind) + break; + c_parser_statement (parser, NULL); + } + while (1); + return pop_stmt_list (stmt); +} + /* OpenMP 5.0: scan-loop-body: @@ -18997,7 +19022,7 @@ c_parser_omp_scan_loop_body (c_parser *p return; } - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19032,7 +19057,7 @@ c_parser_omp_scan_loop_body (c_parser *p error ("expected %<#pragma omp scan%>"); clauses = c_finish_omp_clauses (clauses, C_ORT_OMP); - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE); substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19860,6 +19885,8 @@ c_parser_omp_ordered (c_parser *parser, section-directive[opt] structured-block section-sequence section-directive structured-block + OpenMP 5.1 allows structured-block-sequence instead of structured-block. + SECTIONS_LOC is the location of the #pragma omp sections. */ static tree @@ -19881,7 +19908,8 @@ c_parser_omp_sections_scope (location_t if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION) { - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); @@ -19907,7 +19935,8 @@ c_parser_omp_sections_scope (location_t error_suppress = true; } - substmt = c_parser_omp_structured_block (parser, NULL); + substmt = c_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); SET_EXPR_LOCATION (substmt, loc); add_stmt (substmt); --- gcc/cp/parser.c.jj 2021-10-08 10:58:48.974436064 +0200 +++ gcc/cp/parser.c 2021-10-08 14:07:21.179102547 +0200 @@ -40136,14 +40136,12 @@ cp_parser_end_omp_structured_block (cp_p } static tree -cp_parser_omp_structured_block (cp_parser *parser, bool *if_p, - bool disallow_omp_attrs = true) +cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) { tree stmt = begin_omp_structured_block (); unsigned int save = cp_parser_begin_omp_structured_block (parser); - if (disallow_omp_attrs) - parser->omp_attrs_forbidden_p = true; + parser->omp_attrs_forbidden_p = true; cp_parser_statement (parser, NULL_TREE, false, if_p); cp_parser_end_omp_structured_block (parser, save); @@ -42001,6 +41999,43 @@ cp_parser_omp_section_scan (cp_parser *p return true; } +/* Parse an OpenMP structured block sequence. KIND is the corresponding + separating directive. */ + +static tree +cp_parser_omp_structured_block_sequence (cp_parser *parser, + enum pragma_kind kind) +{ + tree stmt = begin_omp_structured_block (); + unsigned int save = cp_parser_begin_omp_structured_block (parser); + + cp_parser_statement (parser, NULL_TREE, false, NULL); + while (true) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + + if (token->type == CPP_CLOSE_BRACE + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL + || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END) + || (kind != PRAGMA_NONE + && cp_parser_pragma_kind (token) == kind)) + break; + + if (kind != PRAGMA_NONE + && cp_parser_omp_section_scan (parser, + kind == PRAGMA_OMP_SCAN + ? "scan" : "section", false)) + break; + + cp_parser_statement (parser, NULL_TREE, false, NULL); + } + + cp_parser_end_omp_structured_block (parser, save); + return finish_omp_structured_block (stmt); +} + + /* OpenMP 5.0: scan-loop-body: @@ -42015,11 +42050,10 @@ cp_parser_omp_scan_loop_body (cp_parser if (!braces.require_open (parser)) return; - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN); substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE); add_stmt (substmt); - cp_parser_omp_section_scan (parser, "scan", false); cp_token *tok = cp_lexer_peek_token (parser->lexer); if (cp_parser_pragma_kind (tok) == PRAGMA_OMP_SCAN) { @@ -42055,7 +42089,7 @@ cp_parser_omp_scan_loop_body (cp_parser error ("expected %<#pragma omp scan%>"); clauses = finish_omp_clauses (clauses, C_ORT_OMP); - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, PRAGMA_NONE); substmt = build2_loc (tok->location, OMP_SCAN, void_type_node, substmt, clauses); add_stmt (substmt); @@ -42924,7 +42958,8 @@ cp_parser_omp_sections_scope (cp_parser != PRAGMA_OMP_SECTION && !cp_parser_omp_section_scan (parser, "section", true)) { - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } @@ -42951,7 +42986,8 @@ cp_parser_omp_sections_scope (cp_parser error_suppress = true; } - substmt = cp_parser_omp_structured_block (parser, NULL, false); + substmt = cp_parser_omp_structured_block_sequence (parser, + PRAGMA_OMP_SECTION); substmt = build1 (OMP_SECTION, void_type_node, substmt); add_stmt (substmt); } --- gcc/testsuite/c-c++-common/gomp/sections1.c.jj 2020-01-12 11:54:37.016404311 +0100 +++ gcc/testsuite/c-c++-common/gomp/sections1.c 2021-10-08 16:10:27.711160436 +0200 @@ -50,7 +50,7 @@ foo () #pragma omp sections { bar (12); - bar (13); /* { dg-error "pragma omp section" } */ + bar (13); #pragma omp section bar (14); } @@ -63,11 +63,29 @@ foo () bar (15); #pragma omp section bar (16); - bar (17); /* { dg-error "pragma omp section" } */ + bar (17); } #pragma omp sections { bar (18); #pragma omp section } /* { dg-error "expression before" } */ + #pragma omp sections + { + #pragma omp section + #pragma omp section /* { dg-error "may only be used in" } */ + bar (19); + } + #pragma omp sections + { + bar (20); + #pragma omp section + #pragma omp section /* { dg-error "may only be used in" } */ + bar (21); + } + #pragma omp sections + { + bar (22); + #pragma omp section + } /* { dg-error "expression before" } */ } --- gcc/testsuite/gcc.dg/gomp/sections-2.c.jj 2020-01-11 16:31:55.148291802 +0100 +++ gcc/testsuite/gcc.dg/gomp/sections-2.c 2021-10-08 14:21:41.218108482 +0200 @@ -19,11 +19,11 @@ void foo(void) { #pragma omp section bar(2); - bar(3); // { dg-error "expected" } + bar(3); bar(4); #pragma omp section bar(5); - bar(6); // { dg-error "expected" } + bar(6); bar(7); } } --- gcc/testsuite/g++.dg/gomp/sections-2.C.jj 2020-01-11 16:31:54.712298338 +0100 +++ gcc/testsuite/g++.dg/gomp/sections-2.C 2021-10-08 14:45:36.474085819 +0200 @@ -19,11 +19,11 @@ void foo(void) { #pragma omp section bar(2); - bar(3); // { dg-error "expected" } + bar(3); bar(4); #pragma omp section bar(5); - bar(6); // { dg-error "expected" } + bar(6); bar(7); } } --- gcc/testsuite/g++.dg/gomp/attrs-6.C.jj 2021-07-27 09:47:44.222778645 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-6.C 2021-10-08 16:07:32.030598778 +0200 @@ -26,6 +26,41 @@ foo () #pragma omp section { a[3]++; } } + #pragma omp parallel sections + { + #pragma omp section + a[0]++; + a[4]++; + l1: a[5]++; + if (a[5] == 42) goto l1; + [[omp::directive (section)]] { + a[1]++; + a[6]++; + } [[omp::directive (section)]] + a[2]++; + a[7]++; + #pragma omp section + { a[3]++; } + a[8]++; + } + [[omp::directive (parallel sections)]] + { + #pragma omp section + a[0]++; + a[4]++; + [[omp::directive (section)]] { + a[1]++; + a[5]++; + } [[omp::directive (section)]] + a[2]++; + l2: a[6]++; + if (a[6] == 42) + goto l2; + a[7]++; + #pragma omp section + a[8]++; + { a[3]++; } + } } int @@ -46,5 +81,23 @@ bar (int a, int *c, int *d, int *e, int #pragma omp scan inclusive (a) d[i] = a; } + #pragma omp simd reduction (inscan, +: a) + for (i = 0; i < 64; i++) + { + int t = a; + d[i] = t; + [[omp::directive (scan, exclusive (a))]] + int u = c[i]; + a += u; + } + [[omp::directive (simd reduction (inscan, +: a))]] + for (i = 0; i < 64; i++) + { + int t = c[i]; + a += t; + #pragma omp scan inclusive (a) + int u = a; + d[i] = u; + } return a; } --- gcc/testsuite/g++.dg/gomp/attrs-7.C.jj 2021-08-19 11:42:27.432421468 +0200 +++ gcc/testsuite/g++.dg/gomp/attrs-7.C 2021-10-08 17:31:48.432307745 +0200 @@ -29,29 +29,33 @@ bar (int a, int *c, int *d, int *e, int { d[i] = a; [[omp::sequence (omp::directive (parallel), omp::directive (scan, exclusive (a)))]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { a += c[i]; [[omp::sequence (directive (scan inclusive (a)), directive (critical))]] // { dg-error "must be the only specified attribute on a statement" } - d[i] = a; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + d[i] = a; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { d[i] = a; [[gnu::cold]] [[omp::directive (scan, exclusive (a))]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { d[i] = a; [[omp::directive (scan, exclusive (a)), gnu::cold]] // { dg-error "must be the only specified attribute on a statement" } - a += c[i]; // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } - } + // { dg-error "#pragma omp scan" "" { target *-*-* } .-1 } + a += c[i]; // { dg-error "expected" } + } // { dg-error "expected" } [[omp::directive (parallel for reduction (inscan, +: a))]] // { dg-error "'a' specified in 'inscan' 'reduction' clause but not in 'scan' directive clause" } for (i = 0; i < 64; i++) { --- libgomp/libgomp.texi.jj 2021-09-30 17:12:15.238586878 +0200 +++ libgomp/libgomp.texi 2021-10-08 17:46:36.021964258 +0200 @@ -291,7 +291,7 @@ The OpenMP 4.5 specification is fully su @item @code{strict} modifier in the @code{grainsize} and @code{num_tasks} clauses of the taskloop construct @tab Y @tab @item @code{align} clause/modifier in @code{allocate} directive/clause - and @code{allocator} directive @tab N @tab + and @code{allocator} directive @tab P @tab C/C++ on clause only @item @code{thread_limit} clause to @code{target} construct @tab N @tab @item @code{has_device_addr} clause to @code{target} construct @tab N @tab @item iterators in @code{target update} motion clauses and @code{map} @@ -301,7 +301,7 @@ The OpenMP 4.5 specification is fully su @item @code{interop} directive @tab N @tab @item @code{omp_interop_t} object support in runtime routines @tab N @tab @item @code{nowait} clause in @code{taskwait} directive @tab N @tab -@item Extensions to the @code{atomic} directive @tab N @tab +@item Extensions to the @code{atomic} directive @tab P @tab C/C++ only @item @code{seq_cst} clause on a @code{flush} construct @tab Y @tab @item @code{inoutset} argument to the @code{depend} clause @tab N @tab @item @code{private} and @code{firstprivate} argument to @code{default} @@ -337,7 +337,10 @@ The OpenMP 4.5 specification is fully su @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments -@item Suppport of strictly structured blocks in Fortran @tab N @tab +@item Support of strictly structured blocks in Fortran @tab N @tab +@item Support of structured block sequences in C/C++ @tab Y @tab +@item @code{unconstrained} and @code{reproducible} modifiers on @code{order} + clause @tab Y @tab @end multitable