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