From patchwork Tue Nov 28 11:28:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 1869250 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SfgFK0vHBz1yRW for ; Tue, 28 Nov 2023 22:28:36 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 15AE6384A076 for ; Tue, 28 Nov 2023 11:28:34 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id 18FDB385800B; Tue, 28 Nov 2023 11:28:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 18FDB385800B Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 18FDB385800B Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=68.232.137.180 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701170901; cv=none; b=WKBZiM55bPB3yB65Zws64nHjtbxldIKEjl2dkUkww9OnTttoCVS6hFXZPgs2BFWV1DEO8AsaSgu2qKFT7vxORu/Hx5FziSa/IGtNo9f+hEQFDgvR08q6sZJZ4Aqlvd813/zuPjD0evH5VfLfEHh5y10gVq55PS6dugQUwrrSTRw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1701170901; c=relaxed/simple; bh=Gl4Y/TO5BkmbKvYLbmaNMSoLAyB+D+ynPraOu01YIR8=; h=Message-ID:Date:MIME-Version:To:From:Subject; b=Nhrj7lDA/FooP/F62kzIVwZ/NyB3FrS4zj1zIPWRYrcMrkg/5W2iEAgJZwsejAWNI1K1ZEutrvqUTLENBYWQCZV5R3a/eQUyIWv7GWfItXgBNPzFWX8JmpvpY7NXNSTnjt4eCULvnYQzFpU181ju7WhOMfSITZdA3MkGBJFWwMk= ARC-Authentication-Results: i=1; server2.sourceware.org X-CSE-ConnectionGUID: lutlCARpTKW9HIYA+weWLA== X-CSE-MsgGUID: 3eI6l/svS2KqfuCkqM3/bA== X-IronPort-AV: E=Sophos;i="6.04,233,1695715200"; d="diff'?scan'208";a="23891504" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 28 Nov 2023 03:28:17 -0800 IronPort-SDR: tB9pPVvclew61Xvf9Uj5X7dJgPOQfrgwQE1gBBMbqnP00bHlASV6/o+a/+VD2GuYRmeOO+bZf+ Zdjg76mPMxpExSESnDGynTMk0i9OeG1SbiRYfO8+NGqz9I+5bthU3OoK2D75VYWZ8C08MATDQF 7ezBYa/b1lU//byYlZhGmPz3cAv+Wh5mQIqzw8jwadoPwHCTIFFnqFk7mAMCs63pcSOGvxygR7 Y/R/H4Gdlmbo+/JAvjyVsI1pjVPVmlJYoCeWOvWSIGoCJJcIoIncAeApIEqoPRObkkzRN1tLyb Y/A= Message-ID: Date: Tue, 28 Nov 2023 12:28:05 +0100 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: gcc-patches , Jakub Jelinek , fortran From: Tobias Burnus Subject: [Patch] OpenMP: Support acquires/release in 'omp require atomic_default_mem_order' X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-15.mgc.mentorg.com (139.181.222.15) To svr-ies-mbx-12.mgc.mentorg.com (139.181.222.12) X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org I stumbled over this omission when looking at Sandra's patch. It turned out that this is a new OpenMP 5.2 feature - probably added to simplify/unify the syntax. I guess the reason that release/acquire wasn't added before is that it cannot be universally be used - read/write do only accept one of them. However, as a compilation unit might only/mostly use read (and update) or write (and update), that can be fine - especially as overriding the default clause is still possible. It is not quite clear to me why, but the current patch also fixes a bug regarding the diagnostic message for gfortran.dg/gomp/requires-5.f90. (I think I could find out, but as it changed to the better...) Comments, suggestions? Tobias ----------------- Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955 OpenMP: Support acquires/release in 'omp require atomic_default_mem_order' This is an OpenMP 5.2 feature. gcc/c/ChangeLog: * c-parser.cc (c_parser_omp_requires): Handle acquires/release in atomic_default_mem_order clause. (c_parser_omp_atomic): Update. gcc/cp/ChangeLog: * parser.cc (cp_parser_omp_requires): Handle acquires/release in atomic_default_mem_order clause. (cp_parser_omp_atomic): Update. gcc/fortran/ChangeLog: * gfortran.h (enum gfc_omp_requires_kind): Add OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE and OMP_REQ_ATOMIC_MEM_ORDER_RELEASE. (gfc_namespace): Add a 7th bit to omp_requires. * module.cc (enum ab_attribute): Add AB_OMP_REQ_MEM_ORDER_ACQUIRE and AB_OMP_REQ_MEM_ORDER_RELEASE (mio_symbol_attribute): Handle it. * openmp.cc (gfc_omp_requires_add_clause): Update for acquire/release. (gfc_match_omp_requires): Likewise. (gfc_match_omp_atomic): Handle them for atomic_default_mem_order. * parse.cc: Likewise. gcc/testsuite/ChangeLog: * c-c++-common/gomp/requires-3.c: Update for now valid code. * gfortran.dg/gomp/requires-3.f90: Likewise. * gfortran.dg/gomp/requires-2.f90: Update dg-error. * gfortran.dg/gomp/requires-5.f90: Likewise. * c-c++-common/gomp/requires-5.c: New test. * c-c++-common/gomp/requires-6.c: New test. * c-c++-common/gomp/requires-7.c: New test. * c-c++-common/gomp/requires-8.c: New test. * gfortran.dg/gomp/requires-10.f90: New test. * gfortran.dg/gomp/requires-11.f90: New test. gcc/c/c-parser.cc | 32 +++++++++++++++- gcc/cp/parser.cc | 32 +++++++++++++++- gcc/fortran/gfortran.h | 22 ++++++----- gcc/fortran/module.cc | 19 +++++++++ gcc/fortran/openmp.cc | 53 +++++++++++++++++++++----- gcc/fortran/parse.cc | 8 ++++ gcc/testsuite/c-c++-common/gomp/requires-3.c | 8 ++-- gcc/testsuite/c-c++-common/gomp/requires-5.c | 23 +++++++++++ gcc/testsuite/c-c++-common/gomp/requires-6.c | 23 +++++++++++ gcc/testsuite/c-c++-common/gomp/requires-7.c | 11 ++++++ gcc/testsuite/c-c++-common/gomp/requires-8.c | 14 +++++++ gcc/testsuite/gfortran.dg/gomp/requires-10.f90 | 36 +++++++++++++++++ gcc/testsuite/gfortran.dg/gomp/requires-11.f90 | 31 +++++++++++++++ gcc/testsuite/gfortran.dg/gomp/requires-2.f90 | 2 +- gcc/testsuite/gfortran.dg/gomp/requires-3.f90 | 7 ++-- gcc/testsuite/gfortran.dg/gomp/requires-5.f90 | 2 +- 16 files changed, 291 insertions(+), 32 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index df9a07928b5..5700ccccc49 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -20896,6 +20896,28 @@ c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc) case OMP_MEMORY_ORDER_SEQ_CST: memory_order = OMP_MEMORY_ORDER_SEQ_CST; break; + case OMP_MEMORY_ORDER_ACQUIRE: + if (code == NOP_EXPR) /* atomic write */ + { + error_at (loc, "%<#pragma omp atomic write%> incompatible with " + "% clause implicitly provided by a " + "% directive"); + memory_order = OMP_MEMORY_ORDER_SEQ_CST; + } + else + memory_order = OMP_MEMORY_ORDER_ACQUIRE; + break; + case OMP_MEMORY_ORDER_RELEASE: + if (code == OMP_ATOMIC_READ) + { + error_at (loc, "%<#pragma omp atomic read%> incompatible with " + "% clause implicitly provided by a " + "% directive"); + memory_order = OMP_MEMORY_ORDER_SEQ_CST; + } + else + memory_order = OMP_MEMORY_ORDER_RELEASE; + break; case OMP_MEMORY_ORDER_ACQ_REL: switch (code) { @@ -25724,15 +25746,21 @@ c_parser_omp_requires (c_parser *parser) else if (!strcmp (p, "relaxed")) this_req = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED; + else if (!strcmp (p, "release")) + this_req + = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE; else if (!strcmp (p, "acq_rel")) this_req = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL; + else if (!strcmp (p, "acquire")) + this_req + = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE; } if (this_req == 0) { error_at (c_parser_peek_token (parser)->location, - "expected %, % or " - "%"); + "expected %, %, " + "%, % or %"); switch (c_parser_peek_token (parser)->type) { case CPP_EOF: diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 2464d1a0783..93bd7f112a2 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -42436,6 +42436,28 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok, bool openacc) case OMP_MEMORY_ORDER_SEQ_CST: memory_order = OMP_MEMORY_ORDER_SEQ_CST; break; + case OMP_MEMORY_ORDER_ACQUIRE: + if (code == NOP_EXPR) /* atomic write */ + { + error_at (loc, "%<#pragma omp atomic write%> incompatible with " + "% clause implicitly provided by a " + "% directive"); + memory_order = OMP_MEMORY_ORDER_SEQ_CST; + } + else + memory_order = OMP_MEMORY_ORDER_ACQUIRE; + break; + case OMP_MEMORY_ORDER_RELEASE: + if (code == OMP_ATOMIC_READ) + { + error_at (loc, "%<#pragma omp atomic read%> incompatible with " + "% clause implicitly provided by a " + "% directive"); + memory_order = OMP_MEMORY_ORDER_SEQ_CST; + } + else + memory_order = OMP_MEMORY_ORDER_RELEASE; + break; case OMP_MEMORY_ORDER_ACQ_REL: switch (code) { @@ -49126,15 +49148,21 @@ cp_parser_omp_requires (cp_parser *parser, cp_token *pragma_tok) else if (!strcmp (p, "relaxed")) this_req = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED; + else if (!strcmp (p, "release")) + this_req + = (enum omp_requires) OMP_MEMORY_ORDER_RELEASE; else if (!strcmp (p, "acq_rel")) this_req = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL; + else if (!strcmp (p, "acquire")) + this_req + = (enum omp_requires) OMP_MEMORY_ORDER_ACQUIRE; } if (this_req == 0) { error_at (cp_lexer_peek_token (parser->lexer)->location, - "expected %, % or " - "%"); + "expected %, %, " + "%, % or %"); switch (cp_lexer_peek_token (parser->lexer)->type) { case CPP_EOF: diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index aa3f6cb70b4..5477c3d2966 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1496,19 +1496,23 @@ enum gfc_omp_atomic_op enum gfc_omp_requires_kind { /* Keep in sync with gfc_namespace, esp. with omp_req_mem_order. */ - OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST = 1, /* 01 */ - OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL = 2, /* 10 */ - OMP_REQ_ATOMIC_MEM_ORDER_RELAXED = 3, /* 11 */ - OMP_REQ_REVERSE_OFFLOAD = (1 << 2), - OMP_REQ_UNIFIED_ADDRESS = (1 << 3), - OMP_REQ_UNIFIED_SHARED_MEMORY = (1 << 4), - OMP_REQ_DYNAMIC_ALLOCATORS = (1 << 5), + OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST = 1, /* 001 */ + OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL = 2, /* 010 */ + OMP_REQ_ATOMIC_MEM_ORDER_RELAXED = 3, /* 011 */ + OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE = 4, /* 100 */ + OMP_REQ_ATOMIC_MEM_ORDER_RELEASE = 5, /* 101 */ + OMP_REQ_REVERSE_OFFLOAD = (1 << 3), + OMP_REQ_UNIFIED_ADDRESS = (1 << 4), + OMP_REQ_UNIFIED_SHARED_MEMORY = (1 << 5), + OMP_REQ_DYNAMIC_ALLOCATORS = (1 << 6), OMP_REQ_TARGET_MASK = (OMP_REQ_REVERSE_OFFLOAD | OMP_REQ_UNIFIED_ADDRESS | OMP_REQ_UNIFIED_SHARED_MEMORY), OMP_REQ_ATOMIC_MEM_ORDER_MASK = (OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST | OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL - | OMP_REQ_ATOMIC_MEM_ORDER_RELAXED) + | OMP_REQ_ATOMIC_MEM_ORDER_RELAXED + | OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE + | OMP_REQ_ATOMIC_MEM_ORDER_RELEASE) }; enum gfc_omp_memorder @@ -2257,7 +2261,7 @@ typedef struct gfc_namespace unsigned implicit_interface_calls:1; /* OpenMP requires. */ - unsigned omp_requires:6; + unsigned omp_requires:7; unsigned omp_target_seen:1; /* Set to 1 if this is an implicit OMP structured block. */ diff --git a/gcc/fortran/module.cc b/gcc/fortran/module.cc index c07e9dc9ba2..3c07818e2cf 100644 --- a/gcc/fortran/module.cc +++ b/gcc/fortran/module.cc @@ -2093,6 +2093,7 @@ enum ab_attribute AB_OMP_REQ_REVERSE_OFFLOAD, AB_OMP_REQ_UNIFIED_ADDRESS, AB_OMP_REQ_UNIFIED_SHARED_MEMORY, AB_OMP_REQ_DYNAMIC_ALLOCATORS, AB_OMP_REQ_MEM_ORDER_SEQ_CST, AB_OMP_REQ_MEM_ORDER_ACQ_REL, + AB_OMP_REQ_MEM_ORDER_ACQUIRE, AB_OMP_REQ_MEM_ORDER_RELEASE, AB_OMP_REQ_MEM_ORDER_RELAXED, AB_OMP_DEVICE_TYPE_NOHOST, AB_OMP_DEVICE_TYPE_HOST, AB_OMP_DEVICE_TYPE_ANY }; @@ -2175,7 +2176,9 @@ static const mstring attr_bits[] = minit ("OMP_REQ_DYNAMIC_ALLOCATORS", AB_OMP_REQ_DYNAMIC_ALLOCATORS), minit ("OMP_REQ_MEM_ORDER_SEQ_CST", AB_OMP_REQ_MEM_ORDER_SEQ_CST), minit ("OMP_REQ_MEM_ORDER_ACQ_REL", AB_OMP_REQ_MEM_ORDER_ACQ_REL), + minit ("OMP_REQ_MEM_ORDER_ACQUIRE", AB_OMP_REQ_MEM_ORDER_ACQUIRE), minit ("OMP_REQ_MEM_ORDER_RELAXED", AB_OMP_REQ_MEM_ORDER_RELAXED), + minit ("OMP_REQ_MEM_ORDER_RELEASE", AB_OMP_REQ_MEM_ORDER_RELEASE), minit ("OMP_DEVICE_TYPE_HOST", AB_OMP_DEVICE_TYPE_HOST), minit ("OMP_DEVICE_TYPE_NOHOST", AB_OMP_DEVICE_TYPE_NOHOST), minit ("OMP_DEVICE_TYPE_ANYHOST", AB_OMP_DEVICE_TYPE_ANY), @@ -2442,9 +2445,15 @@ mio_symbol_attribute (symbol_attribute *attr) if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) == OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL) MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_ACQ_REL, attr_bits); + if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) + == OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE) + MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_ACQUIRE, attr_bits); if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) == OMP_REQ_ATOMIC_MEM_ORDER_RELAXED) MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_RELAXED, attr_bits); + if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) + == OMP_REQ_ATOMIC_MEM_ORDER_RELEASE) + MIO_NAME (ab_attribute) (AB_OMP_REQ_MEM_ORDER_RELEASE, attr_bits); } switch (attr->omp_device_type) { @@ -2724,11 +2733,21 @@ mio_symbol_attribute (symbol_attribute *attr) "acq_rel", &gfc_current_locus, module_name); break; + case AB_OMP_REQ_MEM_ORDER_ACQUIRE: + gfc_omp_requires_add_clause (OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE, + "acquires", &gfc_current_locus, + module_name); + break; case AB_OMP_REQ_MEM_ORDER_RELAXED: gfc_omp_requires_add_clause (OMP_REQ_ATOMIC_MEM_ORDER_RELAXED, "relaxed", &gfc_current_locus, module_name); break; + case AB_OMP_REQ_MEM_ORDER_RELEASE: + gfc_omp_requires_add_clause (OMP_REQ_ATOMIC_MEM_ORDER_RELEASE, + "release", &gfc_current_locus, + module_name); + break; case AB_OMP_DEVICE_TYPE_HOST: attr->omp_device_type = OMP_DEVICE_TYPE_HOST; break; diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 794df19a4d1..19995708c23 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -6251,14 +6251,15 @@ gfc_omp_requires_add_clause (gfc_omp_requires_kind clause, != (int) clause) { const char *other; - if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST) - other = "seq_cst"; - else if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL) - other = "acq_rel"; - else if (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_RELAXED) - other = "relaxed"; - else - gcc_unreachable (); + switch (prog_unit->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK) + { + case OMP_REQ_ATOMIC_MEM_ORDER_SEQ_CST: other = "seq_cst"; break; + case OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL: other = "acq_rel"; break; + case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: other = "acquire"; break; + case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: other = "relaxed"; break; + case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: other = "release"; break; + default: gcc_unreachable (); + } if (module_name) gfc_error ("!$OMP REQUIRES clause % " @@ -6372,15 +6373,25 @@ gfc_match_omp_requires (void) clause = "acq_rel"; requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQ_REL; } + else if (gfc_match (" acquire )") == MATCH_YES) + { + clause = "acquire"; + requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE; + } else if (gfc_match (" relaxed )") == MATCH_YES) { clause = "relaxed"; requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELAXED; } + else if (gfc_match (" release )") == MATCH_YES) + { + clause = "release"; + requires_clause = OMP_REQ_ATOMIC_MEM_ORDER_RELEASE; + } else { - gfc_error ("Expected SEQ_CST, ACQ_REL or RELAXED for " - "ATOMIC_DEFAULT_MEM_ORDER clause at %C"); + gfc_error ("Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or " + "SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause at %C"); goto error; } } @@ -6827,6 +6838,28 @@ gfc_match_omp_atomic (void) else c->memorder = OMP_MEMORDER_RELEASE; break; + case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: + if (c->atomic_op == GFC_OMP_ATOMIC_WRITE) + { + gfc_error ("!$OMP ATOMIC WRITE at %L incompatible with " + "ACQUIRES clause implicitly provided by a " + "REQUIRES directive", &loc); + c->memorder = OMP_MEMORDER_SEQ_CST; + } + else + c->memorder = OMP_MEMORDER_ACQUIRE; + break; + case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: + if (c->atomic_op == GFC_OMP_ATOMIC_READ) + { + gfc_error ("!$OMP ATOMIC READ at %L incompatible with " + "RELEASE clause implicitly provided by a " + "REQUIRES directive", &loc); + c->memorder = OMP_MEMORDER_SEQ_CST; + } + else + c->memorder = OMP_MEMORDER_RELEASE; + break; default: gcc_unreachable (); } diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index abd3a424f38..c0e80b1a9c3 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -7269,10 +7269,18 @@ done: omp_requires_mask = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_ACQ_REL); break; + case OMP_REQ_ATOMIC_MEM_ORDER_ACQUIRE: + omp_requires_mask + = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_ACQUIRE); + break; case OMP_REQ_ATOMIC_MEM_ORDER_RELAXED: omp_requires_mask = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_RELAXED); break; + case OMP_REQ_ATOMIC_MEM_ORDER_RELEASE: + omp_requires_mask + = (enum omp_requires) (omp_requires_mask | OMP_MEMORY_ORDER_RELEASE); + break; } if (omp_target_seen) diff --git a/gcc/testsuite/c-c++-common/gomp/requires-3.c b/gcc/testsuite/c-c++-common/gomp/requires-3.c index bd2479ba8ff..2fd601acefa 100644 --- a/gcc/testsuite/c-c++-common/gomp/requires-3.c +++ b/gcc/testsuite/c-c++-common/gomp/requires-3.c @@ -1,6 +1,6 @@ -#pragma omp requires atomic_default_mem_order(acquire) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ -#pragma omp requires atomic_default_mem_order(release) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ -#pragma omp requires atomic_default_mem_order(foobar) /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ -#pragma omp requires atomic_default_mem_order ( /* { dg-error "expected 'seq_cst', 'relaxed' or 'acq_rel'" } */ +#pragma omp requires atomic_default_mem_order(foobar) /* { dg-error "expected 'acq_rel', 'acquire', 'relaxed', 'release' or 'seq_cst'" } */ +#pragma omp requires atomic_default_mem_order ( /* { dg-error "expected 'acq_rel', 'acquire', 'relaxed', 'release' or 'seq_cst'" } */ /* { dg-error "expected '\\\)' before end of line" "" { target *-*-* } .-1 } */ #pragma omp requires atomic_default_mem_order(seq_cst), /* { dg-error "expected end of line before ',' token" } */ +/* Valid since since 5.2, but ... */ +#pragma omp requires atomic_default_mem_order(acquire) /* { dg-error "more than one 'atomic_default_mem_order' clause in a single compilation unit" } */ diff --git a/gcc/testsuite/c-c++-common/gomp/requires-5.c b/gcc/testsuite/c-c++-common/gomp/requires-5.c new file mode 100644 index 00000000000..53e0b75f1b7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/requires-5.c @@ -0,0 +1,23 @@ +/* { dg-additional-options "-fdump-tree-original" } */ + +#pragma omp requires atomic_default_mem_order(release) + +int +foo (int x, int y) +{ + int z; + + #pragma omp atomic write + x = y; + + #pragma omp atomic update + x += 1; + + #pragma omp atomic read acquire + z = x; + return z; +} + +/* { dg-final { scan-tree-dump "#pragma omp atomic release" "original" } } */ +/* { dg-final { scan-tree-dump "#pragma omp atomic release" "original" } } */ +/* { dg-final { scan-tree-dump "z = #pragma omp atomic read acquire" "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/requires-6.c b/gcc/testsuite/c-c++-common/gomp/requires-6.c new file mode 100644 index 00000000000..4470c8cae1a --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/requires-6.c @@ -0,0 +1,23 @@ +/* { dg-additional-options "-fdump-tree-original" } */ + +#pragma omp requires atomic_default_mem_order(acquire) + +int +bar (int a, int b) +{ + int c; + + #pragma omp atomic write release + a = b; + + #pragma omp atomic update + a += 1; + + #pragma omp atomic read + c = a; + return c; +} + +/* { dg-final { scan-tree-dump "#pragma omp atomic release" "original" } } */ +/* { dg-final { scan-tree-dump "#pragma omp atomic acquire" "original" } } */ +/* { dg-final { scan-tree-dump "c = #pragma omp atomic read acquire" "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/requires-7.c b/gcc/testsuite/c-c++-common/gomp/requires-7.c new file mode 100644 index 00000000000..4735ef2a6e0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/requires-7.c @@ -0,0 +1,11 @@ +#pragma omp requires atomic_default_mem_order(release) + +int +foo (int x) +{ + int z; + + #pragma omp atomic read /* { dg-error "'#pragma omp atomic read' incompatible with 'release' clause implicitly provided by a 'requires' directive" } */ + z = x; + return z; +} diff --git a/gcc/testsuite/c-c++-common/gomp/requires-8.c b/gcc/testsuite/c-c++-common/gomp/requires-8.c new file mode 100644 index 00000000000..4d56e7d33e9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/requires-8.c @@ -0,0 +1,14 @@ +#pragma omp requires atomic_default_mem_order(acquire) + +int +bar (int a, int b) +{ + int c; + + #pragma omp atomic write /* { dg-error "'#pragma omp atomic write' incompatible with 'acquire' clause implicitly provided by a 'requires' directive" } */ + a = b; + + #pragma omp atomic read + c = a; + return c; +} diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-10.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-10.f90 new file mode 100644 index 00000000000..e912e3e867f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/requires-10.f90 @@ -0,0 +1,36 @@ +! { dg-additional-options "-fdump-tree-original" } + +function foo (x, y) result (z) + !$omp requires atomic_default_mem_order(release) + implicit none + real :: x, y, z + + !$omp atomic write + x = y + + !$omp atomic update + x = x + 1 + + !$omp atomic read acquire + z = x +end + +function bar (a, b) result (c) + !$omp requires atomic_default_mem_order(acquire) + implicit none + real :: a, b, c + + !$omp atomic write release + a = b + + !$omp atomic update + a = a + 1 + + !$omp atomic read + c = a +end + +! { dg-final { scan-tree-dump-times "#pragma omp atomic release" 3 "original" } } */ +! { dg-final { scan-tree-dump-times "#pragma omp atomic acquire" 1 "original" } } */ +! { dg-final { scan-tree-dump-times "z = #pragma omp atomic read acquire" 1 "original" } } */ +! { dg-final { scan-tree-dump-times "c = #pragma omp atomic read acquire" 1 "original" } } */ diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-11.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-11.f90 new file mode 100644 index 00000000000..c55009d5d26 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/requires-11.f90 @@ -0,0 +1,31 @@ +function foo (x, y) result (z) + !$omp requires atomic_default_mem_order(release) + implicit none + real :: x, y, z + + !$omp atomic write + x = y + + !$omp atomic update + x = x + 1 + + !$omp atomic read ! { dg-error "!.OMP ATOMIC READ at .1. incompatible with RELEASE clause implicitly provided by a REQUIRES directive" } + z = x +end + +function bar (a, b) result (c) + !$omp requires atomic_default_mem_order(acquire) + implicit none + real :: a, b, c + + !$omp atomic write ! { dg-error "!.OMP ATOMIC WRITE at .1. incompatible with ACQUIRES clause implicitly provided by a REQUIRES directive" } + a = b + + !$omp atomic update + a = a + 1 + + !$omp atomic read + c = a +end + + diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-2.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-2.f90 index 7b63d4a8b3b..5f11a7bfb2a 100644 --- a/gcc/testsuite/gfortran.dg/gomp/requires-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/requires-2.f90 @@ -8,7 +8,7 @@ !$omp requires atomic_default_mem_order (seq_cst) !$omp requires atomic_default_mem_order (seq_cst) !$omp requires atomic_default_mem_order (acq_rel) ! { dg-error "overrides a previous 'atomic_default_mem_order\\(seq_cst\\)'" } -!$omp requires atomic_default_mem_order (foo) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" } +!$omp requires atomic_default_mem_order (foo) ! { dg-error "Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause" } end ! { dg-prune-output "not yet supported" } diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-3.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-3.f90 index 4429aab2ee6..8c9d6ed3b21 100644 --- a/gcc/testsuite/gfortran.dg/gomp/requires-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/requires-3.f90 @@ -1,4 +1,5 @@ -!$omp requires atomic_default_mem_order(acquire) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" } -!$omp requires atomic_default_mem_order(release) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" } -!$omp requires atomic_default_mem_order(foobar) ! { dg-error "Expected SEQ_CST, ACQ_REL or RELAXED for ATOMIC_DEFAULT_MEM_ORDER clause" } +!$omp requires atomic_default_mem_order(foobar) ! { dg-error "Expected ACQ_REL, ACQUIRE, RELAXED, RELEASE or SEQ_CST for ATOMIC_DEFAULT_MEM_ORDER clause" } + +!$omp requires atomic_default_mem_order(acquire) ! OK since OpenMP 5.2 +!$omp requires atomic_default_mem_order(release) ! { dg-error "!.OMP REQUIRES clause 'atomic_default_mem_order\\(release\\)' specified at .1. overrides a previous 'atomic_default_mem_order\\(acquire\\)' \\(which might be through using a module\\)" } end diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-5.f90 b/gcc/testsuite/gfortran.dg/gomp/requires-5.f90 index ade2a3613c6..e719e929294 100644 --- a/gcc/testsuite/gfortran.dg/gomp/requires-5.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/requires-5.f90 @@ -8,7 +8,7 @@ subroutine foo !$omp requires unified_shared_memory !$omp requires atomic_default_mem_order(relaxed) !$omp requires atomic_default_mem_order(relaxed) -!$omp requires atomic_default_mem_order(seq_cst) ! { dg-error "overrides a previous 'atomic_default_mem_order\\(seq_cst\\)'" } +!$omp requires atomic_default_mem_order(seq_cst) ! { dg-error "overrides a previous 'atomic_default_mem_order\\(relaxed\\)'" } !$omp target !$omp end target end