aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorTobias Burnus <tburnus@baylibre.com>2024-09-24 10:53:59 +0200
committerTobias Burnus <tburnus@baylibre.com>2024-09-24 10:53:59 +0200
commitb752eed3e3f2f27570ea89b7c2339468698472a8 (patch)
treef09990037b25102e5e209a062d8cf13bea5e3f01 /gcc
parent7e560ffd7562cbd1a51ae6298c515b89ebed1363 (diff)
downloadgcc-b752eed3e3f2f27570ea89b7c2339468698472a8.zip
gcc-b752eed3e3f2f27570ea89b7c2339468698472a8.tar.gz
gcc-b752eed3e3f2f27570ea89b7c2339468698472a8.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-parser.cc3
-rw-r--r--gcc/cp/parser.cc3
-rw-r--r--gcc/fortran/gfortran.h10
-rw-r--r--gcc/fortran/module.cc11
-rw-r--r--gcc/fortran/openmp.cc30
-rw-r--r--gcc/fortran/parse.cc3
-rw-r--r--gcc/lto-cgraph.cc4
-rw-r--r--gcc/omp-general.cc21
-rw-r--r--gcc/omp-general.h1
-rw-r--r--gcc/omp-selectors.h1
-rw-r--r--gcc/testsuite/c-c++-common/gomp/declare-variant-1.c6
-rw-r--r--gcc/testsuite/c-c++-common/gomp/requires-2.c2
-rw-r--r--gcc/testsuite/c-c++-common/gomp/requires-4.c1
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/declare-variant-3.f903
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/requires-2.f902
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/requires-self-maps-aux.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/requires-self-maps.f9017
17 files changed, 118 insertions, 18 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index aff5af1..6a46577 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 dbc6070..35c2666 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 37c2869..66c9736 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 8cf58ff..bf38127 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 050409e..2d5c430 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 c506e18..e749bbd 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 1492409..1d4311a 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 3dfbc31..c93bf12 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 37f0548..891f467 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 c61808e..730021e 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 75fcb7b..f130a41 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 d7430b1..d29729f 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 8f45d83..0b61fa9 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 6b23d40..9067428 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 f144d39..ed9f8ea 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 0000000..86cb147
--- /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 0000000..8c45ca4
--- /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 }