https://gcc.gnu.org/g:b752eed3e3f2f27570ea89b7c2339468698472a8

commit r15-3822-gb752eed3e3f2f27570ea89b7c2339468698472a8
Author: Tobias Burnus <tbur...@baylibre.com>
Date:   Tue Sep 24 10:53:59 2024 +0200

    OpenMP: Add support for 'self_maps' to the 'require' directive
    
    'self_maps' implies 'unified_shared_memory', except that the latter
    also permits that explicit maps copy data to device memory while
    self_maps does not. In GCC, currently, both are handled identical.
    
    gcc/c/ChangeLog:
    
            * c-parser.cc (c_parser_omp_requires): Handle self_maps clause.
    
    gcc/cp/ChangeLog:
    
            * parser.cc (cp_parser_omp_requires): Handle self_maps clause.
    
    gcc/fortran/ChangeLog:
    
            * gfortran.h (enum gfc_omp_requires_kind): Add OMP_REQ_SELF_MAPS.
            (gfc_namespace): Enlarge omp_requires bitfield.
            * module.cc (enum ab_attribute, attr_bits): Add 
AB_OMP_REQ_SELF_MAPS.
            (mio_symbol_attribute): Handle it.
            * openmp.cc (gfc_check_omp_requires, gfc_match_omp_requires): Handle
            self_maps clause.
            * parse.cc (gfc_parse_file): Handle self_maps clause.
    
    gcc/ChangeLog:
    
            * lto-cgraph.cc (output_offload_tables, omp_requires_to_name): 
Handle
            self_maps clause.
            * omp-general.cc (struct omp_ts_info, omp_context_selector_matches):
            Likewise for the associated trait.
            * omp-general.h (enum omp_requires): Add OMP_REQUIRES_SELF_MAPS.
            * omp-selectors.h (enum omp_ts_code): Add
            OMP_TRAIT_IMPLEMENTATION_SELF_MAPS.
    
    include/ChangeLog:
    
            * gomp-constants.h (GOMP_REQUIRES_SELF_MAPS): #define.
    
    libgomp/ChangeLog:
    
            * plugin/plugin-gcn.c (GOMP_OFFLOAD_get_num_devices):
            Accept self_maps clause.
            * plugin/plugin-nvptx.c (GOMP_OFFLOAD_get_num_devices):
            Likewise.
            * libgomp.texi (TR13 Impl. Status): Set to 'Y'.
            * target.c (gomp_requires_to_name, GOMP_offload_register_ver,
            gomp_target_init): Handle self_maps clause.
            * testsuite/libgomp.fortran/self_maps.f90: New test.
    
    gcc/testsuite/ChangeLog:
    
            * c-c++-common/gomp/declare-variant-1.c: Add self_maps test.
            * c-c++-common/gomp/requires-4.c: Likewise.
            * gfortran.dg/gomp/declare-variant-3.f90:  Likewise.
            * c-c++-common/gomp/requires-2.c: Update dg-error msg.
            * gfortran.dg/gomp/requires-2.f90: Likewise.
            * gfortran.dg/gomp/requires-self-maps-aux.f90: New.
            * gfortran.dg/gomp/requires-self-maps.f90: New.

Diff:
---
 gcc/c/c-parser.cc                                  |  3 ++
 gcc/cp/parser.cc                                   |  3 ++
 gcc/fortran/gfortran.h                             | 10 +++--
 gcc/fortran/module.cc                              | 11 ++++-
 gcc/fortran/openmp.cc                              | 30 ++++++++-----
 gcc/fortran/parse.cc                               |  3 ++
 gcc/lto-cgraph.cc                                  |  4 ++
 gcc/omp-general.cc                                 | 21 ++++++++++
 gcc/omp-general.h                                  |  1 +
 gcc/omp-selectors.h                                |  1 +
 .../c-c++-common/gomp/declare-variant-1.c          |  6 +++
 gcc/testsuite/c-c++-common/gomp/requires-2.c       |  2 +-
 gcc/testsuite/c-c++-common/gomp/requires-4.c       |  1 +
 .../gfortran.dg/gomp/declare-variant-3.f90         |  3 ++
 gcc/testsuite/gfortran.dg/gomp/requires-2.f90      |  2 +-
 .../gfortran.dg/gomp/requires-self-maps-aux.f90    | 18 ++++++++
 .../gfortran.dg/gomp/requires-self-maps.f90        | 17 ++++++++
 include/gomp-constants.h                           |  4 ++
 libgomp/libgomp.texi                               |  2 +-
 libgomp/plugin/plugin-gcn.c                        |  4 +-
 libgomp/plugin/plugin-nvptx.c                      |  4 +-
 libgomp/target.c                                   | 10 +++--
 libgomp/testsuite/libgomp.fortran/self_maps.f90    | 49 ++++++++++++++++++++++
 23 files changed, 185 insertions(+), 24 deletions(-)

diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index aff5af174303..6a46577f5119 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -26208,6 +26208,8 @@ c_parser_omp_requires (c_parser *parser)
            this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
          else if (!strcmp (p, "unified_shared_memory"))
            this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
+         else if (!strcmp (p, "self_maps"))
+           this_req = OMP_REQUIRES_SELF_MAPS;
          else if (!strcmp (p, "dynamic_allocators"))
            this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
          else if (!strcmp (p, "reverse_offload"))
@@ -26274,6 +26276,7 @@ c_parser_omp_requires (c_parser *parser)
            {
              error_at (cloc, "expected %<unified_address%>, "
                              "%<unified_shared_memory%>, "
+                             "%<self_maps%>, "
                              "%<dynamic_allocators%>, "
                               "%<reverse_offload%> "
                               "or %<atomic_default_mem_order%> clause");
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index dbc607027dfb..35c266659e46 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -50244,6 +50244,8 @@ cp_parser_omp_requires (cp_parser *parser, cp_token 
*pragma_tok)
            this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
          else if (!strcmp (p, "unified_shared_memory"))
            this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
+         else if (!strcmp (p, "self_maps"))
+           this_req = OMP_REQUIRES_SELF_MAPS;
          else if (!strcmp (p, "dynamic_allocators"))
            this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
          else if (!strcmp (p, "reverse_offload"))
@@ -50316,6 +50318,7 @@ cp_parser_omp_requires (cp_parser *parser, cp_token 
*pragma_tok)
            {
              error_at (cloc, "expected %<unified_address%>, "
                              "%<unified_shared_memory%>, "
+                             "%<self_maps%>, "
                              "%<dynamic_allocators%>, "
                               "%<reverse_offload%> "
                               "or %<atomic_default_mem_order%> clause");
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 37c28691f41b..66c9736122a9 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1521,7 +1521,7 @@ enum gfc_omp_atomic_op
 
 enum gfc_omp_requires_kind
 {
-  /* Keep in sync with gfc_namespace, esp. with omp_req_mem_order.  */
+  /* Keep gfc_namespace's omp_requires bitfield size in sync.  */
   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 */
@@ -1530,10 +1530,12 @@ enum gfc_omp_requires_kind
   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_SELF_MAPS = (1 << 6),
+  OMP_REQ_DYNAMIC_ALLOCATORS = (1 << 7),
   OMP_REQ_TARGET_MASK = (OMP_REQ_REVERSE_OFFLOAD
                         | OMP_REQ_UNIFIED_ADDRESS
-                        | OMP_REQ_UNIFIED_SHARED_MEMORY),
+                        | OMP_REQ_UNIFIED_SHARED_MEMORY
+                        | OMP_REQ_SELF_MAPS),
   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
@@ -2290,7 +2292,7 @@ typedef struct gfc_namespace
   unsigned implicit_interface_calls:1;
 
   /* OpenMP requires. */
-  unsigned omp_requires:7;
+  unsigned omp_requires:8;
   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 8cf58ff51429..bf38127d213a 100644
--- a/gcc/fortran/module.cc
+++ b/gcc/fortran/module.cc
@@ -2095,7 +2095,7 @@ enum ab_attribute
   AB_OACC_ROUTINE_LOP_GANG, AB_OACC_ROUTINE_LOP_WORKER,
   AB_OACC_ROUTINE_LOP_VECTOR, AB_OACC_ROUTINE_LOP_SEQ,
   AB_OACC_ROUTINE_NOHOST,
-  AB_OMP_REQ_REVERSE_OFFLOAD, AB_OMP_REQ_UNIFIED_ADDRESS,
+  AB_OMP_REQ_REVERSE_OFFLOAD, AB_OMP_REQ_UNIFIED_ADDRESS, AB_OMP_REQ_SELF_MAPS,
   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,
@@ -2178,6 +2178,7 @@ static const mstring attr_bits[] =
     minit ("OMP_REQ_REVERSE_OFFLOAD", AB_OMP_REQ_REVERSE_OFFLOAD),
     minit ("OMP_REQ_UNIFIED_ADDRESS", AB_OMP_REQ_UNIFIED_ADDRESS),
     minit ("OMP_REQ_UNIFIED_SHARED_MEMORY", AB_OMP_REQ_UNIFIED_SHARED_MEMORY),
+    minit ("OMP_REQ_SELF_MAPS", AB_OMP_REQ_SELF_MAPS),
     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),
@@ -2442,6 +2443,8 @@ mio_symbol_attribute (symbol_attribute *attr)
            MIO_NAME (ab_attribute) (AB_OMP_REQ_UNIFIED_ADDRESS, attr_bits);
          if (gfc_current_ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
            MIO_NAME (ab_attribute) (AB_OMP_REQ_UNIFIED_SHARED_MEMORY, 
attr_bits);
+         if (gfc_current_ns->omp_requires & OMP_REQ_SELF_MAPS)
+           MIO_NAME (ab_attribute) (AB_OMP_REQ_SELF_MAPS, attr_bits);
          if (gfc_current_ns->omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
            MIO_NAME (ab_attribute) (AB_OMP_REQ_DYNAMIC_ALLOCATORS, attr_bits);
          if ((gfc_current_ns->omp_requires & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
@@ -2722,6 +2725,12 @@ mio_symbol_attribute (symbol_attribute *attr)
                                           &gfc_current_locus,
                                           module_name);
              break;
+           case AB_OMP_REQ_SELF_MAPS:
+             gfc_omp_requires_add_clause (OMP_REQ_SELF_MAPS,
+                                          "self_maps",
+                                          &gfc_current_locus,
+                                          module_name);
+             break;
            case AB_OMP_REQ_DYNAMIC_ALLOCATORS:
              gfc_omp_requires_add_clause (OMP_REQ_DYNAMIC_ALLOCATORS,
                                           "dynamic_allocators",
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 050409e00a08..2d5c4305d2a3 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -6759,6 +6759,9 @@ gfc_match_omp_parallel_workshare (void)
 void
 gfc_check_omp_requires (gfc_namespace *ns, int ref_omp_requires)
 {
+  const char *msg = G_("Program unit at %L has OpenMP device "
+                      "constructs/routines but does not set !$OMP REQUIRES %s "
+                      "but other program units do");
   if (ns->omp_target_seen
       && (ns->omp_requires & OMP_REQ_TARGET_MASK)
         != (ref_omp_requires & OMP_REQ_TARGET_MASK))
@@ -6766,19 +6769,16 @@ gfc_check_omp_requires (gfc_namespace *ns, int 
ref_omp_requires)
       gcc_assert (ns->proc_name);
       if ((ref_omp_requires & OMP_REQ_REVERSE_OFFLOAD)
          && !(ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
-       gfc_error ("Program unit at %L has OpenMP device constructs/routines "
-                  "but does not set !$OMP REQUIRES REVERSE_OFFLOAD but other "
-                  "program units do", &ns->proc_name->declared_at);
+       gfc_error (msg, &ns->proc_name->declared_at, "REVERSE_OFFLOAD");
       if ((ref_omp_requires & OMP_REQ_UNIFIED_ADDRESS)
          && !(ns->omp_requires & OMP_REQ_UNIFIED_ADDRESS))
-       gfc_error ("Program unit at %L has OpenMP device constructs/routines "
-                  "but does not set !$OMP REQUIRES UNIFIED_ADDRESS but other "
-                  "program units do", &ns->proc_name->declared_at);
+       gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_ADDRESS");
       if ((ref_omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY)
          && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
-       gfc_error ("Program unit at %L has OpenMP device constructs/routines "
-                  "but does not set !$OMP REQUIRES UNIFIED_SHARED_MEMORY but "
-                  "other program units do", &ns->proc_name->declared_at);
+       gfc_error (msg, &ns->proc_name->declared_at, "UNIFIED_SHARED_MEMORY");
+      if ((ref_omp_requires & OMP_REQ_SELF_MAPS)
+         && !(ns->omp_requires & OMP_REQ_UNIFIED_SHARED_MEMORY))
+       gfc_error (msg, &ns->proc_name->declared_at, "SELF_MAPS");
     }
 }
 
@@ -6868,6 +6868,7 @@ gfc_match_omp_requires (void)
   static const char *clauses[] = {"reverse_offload",
                                  "unified_address",
                                  "unified_shared_memory",
+                                 "self_maps",
                                  "dynamic_allocators",
                                  "atomic_default"};
   const char *clause = NULL;
@@ -6921,13 +6922,20 @@ gfc_match_omp_requires (void)
       else if (gfc_match (clauses[3]) == MATCH_YES)
        {
          clause = clauses[3];
+         requires_clause = OMP_REQ_SELF_MAPS;
+         if (requires_clauses & OMP_REQ_SELF_MAPS)
+           goto duplicate_clause;
+       }
+      else if (gfc_match (clauses[4]) == MATCH_YES)
+       {
+         clause = clauses[4];
          requires_clause = OMP_REQ_DYNAMIC_ALLOCATORS;
          if (requires_clauses & OMP_REQ_DYNAMIC_ALLOCATORS)
            goto duplicate_clause;
        }
       else if (gfc_match ("atomic_default_mem_order (") == MATCH_YES)
        {
-         clause = clauses[4];
+         clause = clauses[5];
          if (requires_clauses & OMP_REQ_ATOMIC_MEM_ORDER_MASK)
            goto duplicate_clause;
          if (gfc_match (" seq_cst )") == MATCH_YES)
@@ -6982,7 +6990,7 @@ duplicate_clause:
   gfc_error ("%qs clause at %L specified more than once", clause, &old_loc);
 error:
   if (!gfc_error_flag_test ())
-    gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, "
+    gfc_error ("Expected UNIFIED_ADDRESS, UNIFIED_SHARED_MEMORY, SELF_MAPS, "
               "DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or "
               "ATOMIC_DEFAULT_MEM_ORDER clause at %L", &old_loc);
   return MATCH_ERROR;
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index c506e18233e3..e749bbdc6b59 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -7415,6 +7415,9 @@ done:
     omp_requires_mask
          = (enum omp_requires) (omp_requires_mask
                                 | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+  if (omp_requires & OMP_REQ_SELF_MAPS)
+    omp_requires_mask
+         = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_SELF_MAPS);
   if (omp_requires & OMP_REQ_DYNAMIC_ALLOCATORS)
     omp_requires_mask = (enum omp_requires) (omp_requires_mask
                                             | OMP_REQUIRES_DYNAMIC_ALLOCATORS);
diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
index 1492409427c9..1d4311a8832b 100644
--- a/gcc/lto-cgraph.cc
+++ b/gcc/lto-cgraph.cc
@@ -1129,6 +1129,7 @@ output_offload_tables (void)
       HOST_WIDE_INT val = ((HOST_WIDE_INT) omp_requires_mask
                           & (OMP_REQUIRES_UNIFIED_ADDRESS
                              | OMP_REQUIRES_UNIFIED_SHARED_MEMORY
+                             | OMP_REQUIRES_SELF_MAPS
                              | OMP_REQUIRES_REVERSE_OFFLOAD
                              | OMP_REQUIRES_TARGET_USED));
       /* (Mis)use LTO_symtab_edge for this variable.  */
@@ -1808,6 +1809,9 @@ omp_requires_to_name (char *buf, size_t size, 
HOST_WIDE_INT requires_mask)
   if (requires_mask & GOMP_REQUIRES_UNIFIED_SHARED_MEMORY)
     p += snprintf (p, end - p, "%sunified_shared_memory",
                   (p == buf ? "" : ", "));
+  if (requires_mask & GOMP_REQUIRES_SELF_MAPS)
+    p += snprintf (p, end - p, "%sself_maps",
+                  (p == buf ? "" : ", "));
   if (requires_mask & GOMP_REQUIRES_REVERSE_OFFLOAD)
     p += snprintf (p, end - p, "%sreverse_offload",
                   (p == buf ? "" : ", "));
diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index 3dfbc315056f..c93bf129e4d7 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -1207,6 +1207,11 @@ struct omp_ts_info omp_ts_map[] =
      OMP_TRAIT_PROPERTY_NONE, true,
      NULL
    },
+   { "self_maps",
+     (1 << OMP_TRAIT_SET_IMPLEMENTATION),
+     OMP_TRAIT_PROPERTY_NONE, true,
+     NULL
+   },
    { "dynamic_allocators",
      (1 << OMP_TRAIT_SET_IMPLEMENTATION),
      OMP_TRAIT_PROPERTY_NONE, true,
@@ -1654,6 +1659,22 @@ omp_context_selector_matches (tree ctx)
                    }
                }
              break;
+           case OMP_TRAIT_IMPLEMENTATION_SELF_MAPS:
+             if (set == OMP_TRAIT_SET_IMPLEMENTATION)
+               {
+                 if (cfun && (cfun->curr_properties & PROP_gimple_any) != 0)
+                   break;
+
+                 if ((omp_requires_mask
+                      & OMP_REQUIRES_SELF_MAPS) == 0)
+                   {
+                     if (symtab->state == PARSING)
+                       ret = -1;
+                     else
+                       return 0;
+                   }
+               }
+             break;
            case OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS:
              if (set == OMP_TRAIT_SET_IMPLEMENTATION)
                {
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 37f0548befde..891f467556e4 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -195,6 +195,7 @@ enum omp_requires {
   OMP_REQUIRES_REVERSE_OFFLOAD = GOMP_REQUIRES_REVERSE_OFFLOAD,
   OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED = 0x100,
   OMP_REQUIRES_TARGET_USED = GOMP_REQUIRES_TARGET_USED,
+  OMP_REQUIRES_SELF_MAPS = GOMP_REQUIRES_SELF_MAPS
 };
 
 extern GTY(()) enum omp_requires omp_requires_mask;
diff --git a/gcc/omp-selectors.h b/gcc/omp-selectors.h
index c61808ec0ad1..730021ea7475 100644
--- a/gcc/omp-selectors.h
+++ b/gcc/omp-selectors.h
@@ -47,6 +47,7 @@ enum omp_ts_code {
   OMP_TRAIT_IMPLEMENTATION_REQUIRES,
   OMP_TRAIT_IMPLEMENTATION_UNIFIED_ADDRESS,
   OMP_TRAIT_IMPLEMENTATION_UNIFIED_SHARED_MEMORY,
+  OMP_TRAIT_IMPLEMENTATION_SELF_MAPS,
   OMP_TRAIT_IMPLEMENTATION_DYNAMIC_ALLOCATORS,
   OMP_TRAIT_IMPLEMENTATION_REVERSE_OFFLOAD,
   OMP_TRAIT_USER_CONDITION,
diff --git a/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c 
b/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c
index 75fcb7bf0e7b..f130a4130b6b 100644
--- a/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c
+++ b/gcc/testsuite/c-c++-common/gomp/declare-variant-1.c
@@ -1,10 +1,16 @@
 int foo (int, int, int *);
 int bar (int, int, int *);
+int foobar (int, int, int *);
 #pragma omp declare variant (foo) \
   match (construct={parallel,for},\
         device={isa(avx512f,avx512vl),kind(host,cpu)},\
         implementation={vendor(score(0):gnu),unified_shared_memory},\
         user={condition(score(0):0)})
+#pragma omp declare variant (foo) \
+  match (construct={parallel,for},\
+        device={isa(avx512f,avx512vl),kind(host,cpu)},\
+        implementation={vendor(score(0):gnu),self_maps},\
+        user={condition(score(0):0)})
 #pragma omp declare variant (bar) \
   match (device={arch(x86_64,powerpc64),isa(avx512f,popcntb)}, \
         
implementation={atomic_default_mem_order(seq_cst),made_up_selector("foo", 13, 
"bar")}, \
diff --git a/gcc/testsuite/c-c++-common/gomp/requires-2.c 
b/gcc/testsuite/c-c++-common/gomp/requires-2.c
index d7430b1b1a47..d29729fe555a 100644
--- a/gcc/testsuite/c-c++-common/gomp/requires-2.c
+++ b/gcc/testsuite/c-c++-common/gomp/requires-2.c
@@ -2,7 +2,7 @@
 #pragma omp requires unified_shared_memory,unified_shared_memory       /* { 
dg-error "too many 'unified_shared_memory' clauses" } */
 #pragma omp requires unified_address   unified_address /* { dg-error "too many 
'unified_address' clauses" } */
 #pragma omp requires reverse_offload reverse_offload   /* { dg-error "too many 
'reverse_offload' clauses" } */
-#pragma omp requires foobarbaz /* { dg-error "expected 'unified_address', 
'unified_shared_memory', 'dynamic_allocators', 'reverse_offload' or 
'atomic_default_mem_order' clause" } */
+#pragma omp requires foobarbaz /* { dg-error "expected 'unified_address', 
'unified_shared_memory', 'self_maps', 'dynamic_allocators', 'reverse_offload' 
or 'atomic_default_mem_order' clause" } */
 #pragma omp requires dynamic_allocators , dynamic_allocators   /* { dg-error 
"too many 'dynamic_allocators' clauses" } */
 #pragma omp requires atomic_default_mem_order(seq_cst) 
atomic_default_mem_order(seq_cst)       /* { dg-error "too many 
'atomic_default_mem_order' clauses" } */
 #pragma omp requires atomic_default_mem_order (seq_cst)        /* { 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-4.c 
b/gcc/testsuite/c-c++-common/gomp/requires-4.c
index 8f45d83ea6e3..0b61fa905bb7 100644
--- a/gcc/testsuite/c-c++-common/gomp/requires-4.c
+++ b/gcc/testsuite/c-c++-common/gomp/requires-4.c
@@ -9,3 +9,4 @@ foo (void)
 #pragma omp requires unified_shared_memory     /* { dg-error 
"'unified_shared_memory' clause used lexically after first target construct or 
offloading API" } */
 #pragma omp requires unified_address   /* { dg-error "'unified_address' clause 
used lexically after first target construct or offloading API" } */
 #pragma omp requires reverse_offload   /* { dg-error "'reverse_offload' clause 
used lexically after first target construct or offloading API" } */
+#pragma omp requires self_maps /* { dg-error "'self_maps' clause used 
lexically after first target construct or offloading API" } */
diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90 
b/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90
index 6b23d40e4109..90674281f226 100644
--- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f90
@@ -129,6 +129,9 @@ contains
   subroutine f45 ()
     !$omp declare variant (f13) match (implementation={unified_shared_memory})
   end subroutine
+  subroutine f45a ()
+    !$omp declare variant (f13) match (implementation={self_maps})
+  end subroutine
   subroutine f46 ()
     !$omp declare variant (f13) match (implementation={unified_address})
   end subroutine
diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-2.f90 
b/gcc/testsuite/gfortran.dg/gomp/requires-2.f90
index f144d3910348..ed9f8ea352a7 100644
--- a/gcc/testsuite/gfortran.dg/gomp/requires-2.f90
+++ b/gcc/testsuite/gfortran.dg/gomp/requires-2.f90
@@ -2,7 +2,7 @@
 !$omp requires unified_shared_memory,unified_shared_memory     ! { dg-error 
"specified more than once" }
 !$omp requires unified_address unified_address ! { dg-error "specified more 
than once" }
 !$omp requires reverse_offload reverse_offload ! { dg-error "specified more 
than once" }
-!$omp requires foobarbaz       ! { dg-error "Expected UNIFIED_ADDRESS, 
UNIFIED_SHARED_MEMORY, DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or 
ATOMIC_DEFAULT_MEM_ORDER clause" }
+!$omp requires foobarbaz       ! { dg-error "Expected UNIFIED_ADDRESS, 
UNIFIED_SHARED_MEMORY, SELF_MAPS, DYNAMIC_ALLOCATORS, REVERSE_OFFLOAD, or 
ATOMIC_DEFAULT_MEM_ORDER clause" }
 !$omp requires dynamic_allocators , dynamic_allocators ! { dg-error "specified 
more than once" }
 !$omp requires atomic_default_mem_order(seq_cst) 
atomic_default_mem_order(seq_cst)     ! { dg-error "specified more than once" }
 !$omp requires atomic_default_mem_order (seq_cst)
diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-self-maps-aux.f90 
b/gcc/testsuite/gfortran.dg/gomp/requires-self-maps-aux.f90
new file mode 100644
index 000000000000..86cb1472b371
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/requires-self-maps-aux.f90
@@ -0,0 +1,18 @@
+! { dg-do compile  { target skip-all-targets } }
+
+! used by requires-self-maps.f90
+
+module m2
+  implicit none
+contains
+  integer function g()
+    !$omp target map(from:g)
+       g = 99
+    !$omp end target
+  end
+end
+
+program main
+  use m
+  use m2
+end
diff --git a/gcc/testsuite/gfortran.dg/gomp/requires-self-maps.f90 
b/gcc/testsuite/gfortran.dg/gomp/requires-self-maps.f90
new file mode 100644
index 000000000000..8c45ca4f256a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/requires-self-maps.f90
@@ -0,0 +1,17 @@
+! { dg-do link }
+! { dg-additional-sources "requires-self-maps-aux.f90" }
+
+module m
+  !$omp requires self_maps
+  implicit none
+contains
+  integer function f()
+    !$omp target map(from:f)
+       f = 42
+    !$omp end target
+  end
+end
+
+! This shows up in line 5 of requires-self-maps-aux.f90, but adding dg-error 
there is ignored when
+! invoked as additional files – but this file needs to come first in order to 
create the .mod file:
+! { dg-error "Program unit at .1. has OpenMP device constructs/routines but 
does not set !.OMP REQUIRES SELF_MAPS but other program units do" "" { target 
*-*-* } 0 }
diff --git a/include/gomp-constants.h b/include/gomp-constants.h
index 0fae337f9d62..9618727888d8 100644
--- a/include/gomp-constants.h
+++ b/include/gomp-constants.h
@@ -383,10 +383,14 @@ enum gomp_map_kind
 #define GOMP_DEPEND_INOUTSET           5
 
 /* Flag values for OpenMP 'requires' directive features.  */
+// compiler use only: OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER  0xf
 #define GOMP_REQUIRES_UNIFIED_ADDRESS       0x10
 #define GOMP_REQUIRES_UNIFIED_SHARED_MEMORY 0x20
+// compiler use only: OMP_REQUIRES_DYNAMIC_ALLOCATORS 0x40
 #define GOMP_REQUIRES_REVERSE_OFFLOAD       0x80
+// compiler use only: OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED 0x100
 #define GOMP_REQUIRES_TARGET_USED           0x200
+#define GOMP_REQUIRES_SELF_MAPS             0x400
 
 /* Interop foreign-runtime data.  */
 #define GOMP_INTEROP_IFR_LAST  7
diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi
index 936d3f4e2e49..29f5419cd0f1 100644
--- a/libgomp/libgomp.texi
+++ b/libgomp/libgomp.texi
@@ -539,7 +539,7 @@ Technical Report (TR) 13 is the third preview for OpenMP 
6.0.
 @item Scope requirement changes for @code{declare_target} @tab N @tab
 @item @code{message} and @code{severity} clauses to @code{parallel} directive
       @tab N @tab
-@item @code{self_maps} clause to @code{requires} directive @tab N @tab
+@item @code{self_maps} clause to @code{requires} directive @tab Y @tab
 @item @code{no_openmp_constructs} assumptions clause @tab N @tab
 @item Restriction for @code{ordered} regarding loop-transforming directives
       @tab N @tab
diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c
index f805206852dc..1bd90dc381ed 100644
--- a/libgomp/plugin/plugin-gcn.c
+++ b/libgomp/plugin/plugin-gcn.c
@@ -3378,13 +3378,15 @@ GOMP_OFFLOAD_get_num_devices (unsigned int 
omp_requires_mask)
       && ((omp_requires_mask
           & ~(GOMP_REQUIRES_UNIFIED_ADDRESS
               | GOMP_REQUIRES_UNIFIED_SHARED_MEMORY
+              | GOMP_REQUIRES_SELF_MAPS
               | GOMP_REQUIRES_REVERSE_OFFLOAD)) != 0))
     return -1;
   /* Check whether host page access is supported; this is per system level
      (all GPUs supported by HSA).  While intrinsically true for APUs, it
      requires XNACK support for discrete GPUs.  */
   if (hsa_context.agent_count > 0
-      && (omp_requires_mask & GOMP_REQUIRES_UNIFIED_SHARED_MEMORY))
+      && (omp_requires_mask
+         & (GOMP_REQUIRES_UNIFIED_SHARED_MEMORY | GOMP_REQUIRES_SELF_MAPS)))
     {
       bool b;
       hsa_system_info_t type = HSA_AMD_SYSTEM_INFO_SVM_ACCESSIBLE_BY_DEFAULT;
diff --git a/libgomp/plugin/plugin-nvptx.c b/libgomp/plugin/plugin-nvptx.c
index 9310241d4fb9..e9a9d798fe6b 100644
--- a/libgomp/plugin/plugin-nvptx.c
+++ b/libgomp/plugin/plugin-nvptx.c
@@ -1301,6 +1301,7 @@ GOMP_OFFLOAD_get_num_devices (unsigned int 
omp_requires_mask)
   if (num_devices > 0
       && ((omp_requires_mask
           & ~(GOMP_REQUIRES_UNIFIED_ADDRESS
+              | GOMP_REQUIRES_SELF_MAPS
               | GOMP_REQUIRES_UNIFIED_SHARED_MEMORY
               | GOMP_REQUIRES_REVERSE_OFFLOAD)) != 0))
     return -1;
@@ -1308,7 +1309,8 @@ GOMP_OFFLOAD_get_num_devices (unsigned int 
omp_requires_mask)
      if so, enable USM.  Currently, capabilities is per device type, hence,
      check all devices.  */
   if (num_devices > 0
-      && (omp_requires_mask & GOMP_REQUIRES_UNIFIED_SHARED_MEMORY))
+      && (omp_requires_mask
+         & (GOMP_REQUIRES_UNIFIED_SHARED_MEMORY | GOMP_REQUIRES_SELF_MAPS)))
     for (int dev = 0; dev < num_devices; dev++)
       {
        int pi;
diff --git a/libgomp/target.c b/libgomp/target.c
index abd1ac8bcca9..6918694a843b 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -2587,6 +2587,9 @@ gomp_requires_to_name (char *buf, size_t size, int 
requires_mask)
   if (requires_mask & GOMP_REQUIRES_UNIFIED_SHARED_MEMORY)
     p += snprintf (p, end - p, "%sunified_shared_memory",
                   (p == buf ? "" : ", "));
+  if (requires_mask & GOMP_REQUIRES_SELF_MAPS)
+    p += snprintf (p, end - p, "%sself_maps",
+                  (p == buf ? "" : ", "));
   if (requires_mask & GOMP_REQUIRES_REVERSE_OFFLOAD)
     p += snprintf (p, end - p, "%sreverse_offload",
                   (p == buf ? "" : ", "));
@@ -2624,9 +2627,9 @@ GOMP_offload_register_ver (unsigned version, const void 
*host_table,
   if (omp_req && omp_requires_mask && omp_requires_mask != omp_req)
     {
       char buf1[sizeof ("unified_address, unified_shared_memory, "
-                       "reverse_offload")];
+                       "self_maps, reverse_offload")];
       char buf2[sizeof ("unified_address, unified_shared_memory, "
-                       "reverse_offload")];
+                       "self_maps, reverse_offload")];
       gomp_requires_to_name (buf2, sizeof (buf2),
                             omp_req != GOMP_REQUIRES_TARGET_USED
                             ? omp_req : omp_requires_mask);
@@ -5493,7 +5496,8 @@ gomp_target_init (void)
 
                /* If USM has been requested and is supported by all devices
                   of this type, set the capability accordingly.  */
-               if (omp_requires_mask & GOMP_REQUIRES_UNIFIED_SHARED_MEMORY)
+               if (omp_requires_mask
+                   & (GOMP_REQUIRES_UNIFIED_SHARED_MEMORY | 
GOMP_REQUIRES_SELF_MAPS))
                  current_device.capabilities |= GOMP_OFFLOAD_CAP_SHARED_MEM;
 
                devs = realloc (devs, (num_devs + new_num_devs)
diff --git a/libgomp/testsuite/libgomp.fortran/self_maps.f90 
b/libgomp/testsuite/libgomp.fortran/self_maps.f90
new file mode 100644
index 000000000000..208fd1c71d5c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/self_maps.f90
@@ -0,0 +1,49 @@
+! Basic test whether self_maps work
+
+module m
+  !$omp requires self_maps
+  implicit none (type, external)
+  type t
+    integer :: val
+    type(t), pointer :: next
+  end type t
+contains
+  subroutine init(p)
+    integer :: i
+    type(t), pointer :: p, x
+    allocate(x)
+    p => x
+    do i = 1, 5
+      x%val = i
+      if (i < 5) then
+        allocate(x%next)
+        x => x%next
+      end if
+    end do
+  end subroutine
+
+  subroutine check(p)
+    !$omp declare target enter(check)
+    integer :: i
+    type(t), pointer :: p, x
+    x => p
+    do i = 1, 5
+      if (x%val /= i) stop 1
+       x => x%next
+    end do
+end subroutine
+end module
+
+use omp_lib
+use m
+implicit none (type, external)
+type(t), pointer :: linked
+integer :: i
+
+call init(linked)
+do i = 0, omp_get_num_devices()
+  !$omp target device(i)
+    call check(linked)
+  !$omp end target
+end do
+end

Reply via email to