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.
This commit is contained in:
parent
7e560ffd75
commit
b752eed3e3
23 changed files with 185 additions and 24 deletions
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ? "" : ", "));
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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")}, \
|
||||
|
|
|
@ -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" } */
|
||||
|
|
|
@ -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" } */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
18
gcc/testsuite/gfortran.dg/gomp/requires-self-maps-aux.f90
Normal file
18
gcc/testsuite/gfortran.dg/gomp/requires-self-maps-aux.f90
Normal file
|
@ -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
|
17
gcc/testsuite/gfortran.dg/gomp/requires-self-maps.f90
Normal file
17
gcc/testsuite/gfortran.dg/gomp/requires-self-maps.f90
Normal file
|
@ -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 }
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
49
libgomp/testsuite/libgomp.fortran/self_maps.f90
Normal file
49
libgomp/testsuite/libgomp.fortran/self_maps.f90
Normal file
|
@ -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
|
Loading…
Add table
Reference in a new issue