]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
OpenMP: Support acquires/release in 'omp require atomic_default_mem_order'
authorTobias Burnus <tobias@codesourcery.com>
Mon, 11 Dec 2023 14:19:02 +0000 (15:19 +0100)
committerTobias Burnus <tobias@codesourcery.com>
Mon, 11 Dec 2023 14:19:02 +0000 (15:19 +0100)
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.

16 files changed:
gcc/c/c-parser.cc
gcc/cp/parser.cc
gcc/fortran/gfortran.h
gcc/fortran/module.cc
gcc/fortran/openmp.cc
gcc/fortran/parse.cc
gcc/testsuite/c-c++-common/gomp/requires-3.c
gcc/testsuite/c-c++-common/gomp/requires-5.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/requires-6.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/requires-7.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/gomp/requires-8.c [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/requires-10.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/requires-11.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/requires-2.f90
gcc/testsuite/gfortran.dg/gomp/requires-3.f90
gcc/testsuite/gfortran.dg/gomp/requires-5.f90

index df9a07928b5662e970950019e99bbedbb5f1a2c4..5700ccccc4930e8a95c2228a01c395b2f6fd7f6b 100644 (file)
@@ -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 "
+                            "%<acquire%> clause implicitly provided by a "
+                            "%<requires%> 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 "
+                            "%<release%> clause implicitly provided by a "
+                            "%<requires%> 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 %<seq_cst%>, %<relaxed%> or "
-                               "%<acq_rel%>");
+                               "expected %<acq_rel%>, %<acquire%>, "
+                               "%<relaxed%>, %<release%> or %<seq_cst%>");
                      switch (c_parser_peek_token (parser)->type)
                        {
                        case CPP_EOF:
index b987324f6691a5c90d48be3704693e6a32a26ae7..fe8845b0fc31f4930ca053dd4a888fa0b5b3e071 100644 (file)
@@ -42504,6 +42504,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 "
+                            "%<acquire%> clause implicitly provided by a "
+                            "%<requires%> 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 "
+                            "%<release%> clause implicitly provided by a "
+                            "%<requires%> directive");
+             memory_order = OMP_MEMORY_ORDER_SEQ_CST;
+           }
+         else
+           memory_order = OMP_MEMORY_ORDER_RELEASE;
+         break;
        case OMP_MEMORY_ORDER_ACQ_REL:
          switch (code)
            {
@@ -49194,15 +49216,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 %<seq_cst%>, %<relaxed%> or "
-                               "%<acq_rel%>");
+                               "expected %<acq_rel%>, %<acquire%>, "
+                               "%<relaxed%>, %<release%> or %<seq_cst%>");
                      switch (cp_lexer_peek_token (parser->lexer)->type)
                        {
                        case CPP_EOF:
index 28569d07e7161fd502d53f8bf4f09b5e86c6aa28..c86a025a3fce0957fa328a94f7516534cbd2edcc 100644 (file)
@@ -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
@@ -2258,7 +2262,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.  */
index c07e9dc9ba2131f3a4d771234d63d29e2c7ce8e6..3c07818e2cf9e58ce3d99ff6c932b0189caea553 100644 (file)
@@ -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;
index 251da667236d6379b1a58b3a5d08b02caa6ded95..8c0e5445ddb8fe5a24a7ee9d8f13b4c6c317daf5 100644 (file)
@@ -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 %<atomic_default_mem_order(%s)%> "
@@ -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 ();
        }
index c0eb0575a90ff3a3596ec6094a83f606d79bfb5a..9b4c39274bea3cde0a5699e38f3c23fdcbfbc684 100644 (file)
@@ -7274,10 +7274,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)
index bd2479ba8ffa59a92cd9fb09a2a938b7d9d3f4dd..2fd601acefa4631f32ae6ae2eb575874a0e8b40f 100644 (file)
@@ -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 (file)
index 0000000..53e0b75
--- /dev/null
@@ -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 (file)
index 0000000..4470c8c
--- /dev/null
@@ -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 (file)
index 0000000..4735ef2
--- /dev/null
@@ -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 (file)
index 0000000..4d56e7d
--- /dev/null
@@ -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 (file)
index 0000000..e912e3e
--- /dev/null
@@ -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 (file)
index 0000000..c55009d
--- /dev/null
@@ -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
+
+
index 7b63d4a8b3bdb990b5fcb147b58c8a09a70d1d93..5f11a7bfb2ad4b8f6dc760e7765f440e4f398120 100644 (file)
@@ -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" }
index 4429aab2ee62c619dab12c85ff76122a059d4a2d..8c9d6ed3b21023614083d2081a43216bddf076d6 100644 (file)
@@ -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
index ade2a3613c666790c995dcc9111b4c7cc713cae8..e719e929294cf1211ce2559e248b24decc1fc63a 100644 (file)
@@ -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