-fopenmp-force-usm can be useful for some badly written code. Explicity
using 'omp requires' makes more sense but still. It might also make
sense for testing purpose.
Unfortunately, I did not see a simple way of testing it. When trying it
manually, I looked at the 'a.xamdgcn-amdhsa.c' -save-temps file, where
gcn_data has the omp_requires_mask as second argument and testing showed
that an explicit pragma and the -f... argument have the same result.
Alternative would be to move this code later, e.g. to lto-cgraph.cc's
omp_requires_mask, which might be safer (as it avoids changing as many
locations). On the other hand, it might require more special cases
elsewhere.*
Comment, suggestions?
Tobias
*I am especially thinking about a global variable and "#pragma omp
declare target". At least with 'omp requires self_maps' of OpenMP 6, it
seems as if 'declare target enter(global_var)' should become
'link(global_var)' where the global_var pointer is updated to point to
the host version.
At least I don't see how otherwise the "all corresponding list items
created by the 'enter' clauses specified by declare target directives in
the compilation unit share storage with the original list items." could
be fulfilled.
This will require generating different code for 'self_maps' (and,
potentially / [RFC] 'unified_shared_memory') than normal code, which
would be the first compiler code-gen change due to USM (→
GOMP_OFFLOAD_CAP_SHARED_MEM) for non-host devices.
OpenMP: Add -fopenmp-force-usm mode
Add an implicit 'omp requires unified_shared_memory' to all files that
use target constructs ("OMP_REQUIRES_TARGET_USED"). As constructed, the
diagnostic "'unified_shared_memory' clause used lexically after first target
construct or offloading API" is not inhibited.
The option has no effect without -fopenmp and does not affect OpenACC code,
matching what the directive would do. The name of the command-line option
matches Clang's, added in LLVM 18.
gcc/c-family/ChangeLog:
* c.opt (fopenmp-force-usm): New.
* c.opt.urls: Regenerated
gcc/c/ChangeLog:
* c-parser.cc (c_parser_omp_target_data, c_parser_omp_target_update,
c_parser_omp_target_enter_data, c_parser_omp_target_exit_data,
c_parser_omp_target): When setting OMP_REQUIRES_TARGET_USED, also
set OMP_REQUIRES_UNIFIED_SHARED_MEMORY if -fopenmp-force-usm is
in force.
gcc/cp/ChangeLog:
* parser.cc (cp_parser_omp_target_data,
cp_parser_omp_target_enter_data, cp_parser_omp_target_exit_data,
cp_parser_omp_target_update, cp_parser_omp_target): When setting
OMP_REQUIRES_TARGET_USED, also set OMP_REQUIRES_UNIFIED_SHARED_MEMORY
if -fopenmp-force-usm is in force.
gcc/ChangeLog:
* doc/invoke.texi (-fopenmp-force-usm): Document new option.
gcc/fortran/ChangeLog:
* invoke.texi (-fopenmp-force-usm): Document new option.
* lang.opt (fopenmp-force-usm): New.
* lang.opt.urls: Regenerate.
* parse.cc (gfc_parse_file): When setting
OMP_REQUIRES_TARGET_USED, also set OMP_REQUIRES_UNIFIED_SHARED_MEMORY
if -fopenmp-force-usm is in force.
gcc/c-family/c.opt | 4 ++++
gcc/c-family/c.opt.urls | 3 +++
gcc/c/c-parser.cc | 50 +++++++++++++++++++++++++++++++++++++----------
gcc/cp/parser.cc | 50 +++++++++++++++++++++++++++++++++++++----------
gcc/doc/invoke.texi | 11 +++++++++--
gcc/fortran/invoke.texi | 7 +++++++
gcc/fortran/lang.opt | 4 ++++
gcc/fortran/lang.opt.urls | 3 +++
gcc/fortran/parse.cc | 10 ++++++++--
9 files changed, 118 insertions(+), 24 deletions(-)
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index fb34c3b7031..4985cd61c48 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -2136,6 +2136,10 @@ fopenmp
C ObjC C++ ObjC++ LTO Var(flag_openmp)
Enable OpenMP (implies -frecursive in Fortran).
+fopenmp-force-usm
+C ObjC C++ ObjC++ Var(flag_openmp_force_usm)
+Behave as if the source file contained OpenMP's 'requires unified_shared_memory'.
+
fopenmp-simd
C ObjC C++ ObjC++ Var(flag_openmp_simd)
Enable OpenMP's SIMD directives.
diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls
index dd455d7c0dc..34b3a395e84 100644
--- a/gcc/c-family/c.opt.urls
+++ b/gcc/c-family/c.opt.urls
@@ -1222,6 +1222,9 @@ UrlSuffix(gcc/C-Dialect-Options.html#index-fopenacc-dim)
fopenmp
UrlSuffix(gcc/C-Dialect-Options.html#index-fopenmp) LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-fopenmp)
+fopenmp-force-usm
+UrlSuffix(gcc/C-Dialect-Options.html#index-fopenmp-force-usm) LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-fopenmp-force-usm)
+
fopenmp-simd
UrlSuffix(gcc/C-Dialect-Options.html#index-fopenmp-simd) LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-fopenmp-simd)
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 00f8bf4376e..93c9cd1c9d0 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -23849,8 +23849,14 @@ static tree
c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
{
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
@@ -23956,8 +23962,14 @@ c_parser_omp_target_update (location_t loc, c_parser *parser,
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree stmt = make_node (OMP_TARGET_UPDATE);
TREE_TYPE (stmt) = void_type_node;
@@ -24007,8 +24019,14 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
@@ -24117,8 +24135,14 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
@@ -24223,8 +24247,14 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
if (c_parser_next_token_is (parser, CPP_NAME))
{
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 779625144db..fc2026f0a01 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -46914,8 +46914,14 @@ static tree
cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
@@ -47029,8 +47035,14 @@ cp_parser_omp_target_enter_data (cp_parser *parser, cp_token *pragma_tok,
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
@@ -47144,8 +47156,14 @@ cp_parser_omp_target_exit_data (cp_parser *parser, cp_token *pragma_tok,
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
@@ -47255,8 +47273,14 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
}
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
tree stmt = make_node (OMP_TARGET_UPDATE);
TREE_TYPE (stmt) = void_type_node;
@@ -47290,8 +47314,14 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
enum pragma_context context, bool *if_p)
{
if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 2cba380718b..d6a19c8f561 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -203,8 +203,8 @@ in the following sections.
-ffreestanding -fgimple -fgnu-tm -fgnu89-inline -fhosted
-flax-vector-conversions -fms-extensions
-foffload=@var{arg} -foffload-options=@var{arg}
--fopenacc -fopenacc-dim=@var{geom}
--fopenmp -fopenmp-simd -fopenmp-target-simd-clone@r{[}=@var{device-type}@r{]}
+-fopenacc -fopenacc-dim=@var{geom} -fopenmp -fopenmp-force-usm
+-fopenmp-simd -fopenmp-target-simd-clone@r{[}=@var{device-type}@r{]}
-fpermitted-flt-eval-methods=@var{standard}
-fplan9-extensions -fsigned-bitfields -funsigned-bitfields
-fsigned-char -funsigned-char -fstrict-flex-arrays[=@var{n}]
@@ -2817,6 +2817,13 @@ implies @option{-pthread}, and thus is only supported on targets that
have support for @option{-pthread}. @option{-fopenmp} implies
@option{-fopenmp-simd}.
+@opindex fopenmp-force-usm
+@cindex OpenMP Unified Shared Memory
+@item -fopenmp-force-usm
+Behave as if each source file contained the OpenMP directive @code{requires}
+with the @code{unified_shared_memory} clause. This option only has an effect
+if @option{-fopenmp} has been specified.
+
@opindex fopenmp-simd
@cindex OpenMP SIMD
@cindex SIMD
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 6bc42afe2c4..a825941e1ae 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -445,6 +445,13 @@ implies @option{-pthread}, and thus is only supported on targets that
have support for @option{-pthread}. @option{-fopenmp} implies
@option{-fopenmp-simd} and @option{-frecursive}.
+@opindex fopenmp-force-usm
+@cindex OpenMP Unified Shared Memory
+@item -fopenmp-force-usm
+Behave as if each source file contained the OpenMP directive @code{requires}
+with the @code{unified_shared_memory} clause. This option only has an effect
+if @option{-fopenmp} has been specified.
+
@opindex fopenmp-allocators
@cindex OpenMP Allocators
@item -fopenmp-allocators
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 5efd4a0129a..bf72b0e4ff3 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -712,6 +712,10 @@ fopenmp
Fortran LTO
; Documented in C
+fopenmp-force-usm
+Fortran
+; Documented in C
+
fopenmp-simd
Fortran
; Documented in C
diff --git a/gcc/fortran/lang.opt.urls b/gcc/fortran/lang.opt.urls
index e335b42e357..d4e4efcb437 100644
--- a/gcc/fortran/lang.opt.urls
+++ b/gcc/fortran/lang.opt.urls
@@ -118,6 +118,9 @@ UrlSuffix(gcc/C-Dialect-Options.html#index-fopenacc-dim)
fopenmp
UrlSuffix(gcc/C-Dialect-Options.html#index-fopenmp) LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-fopenmp)
+fopenmp-force-usm
+UrlSuffix(gcc/C-Dialect-Options.html#index-fopenmp-force-usm) LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-fopenmp-force-usm)
+
fopenmp-simd
UrlSuffix(gcc/C-Dialect-Options.html#index-fopenmp-simd) LangUrlSuffix_Fortran(gfortran/Fortran-Dialect-Options.html#index-fopenmp-simd)
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index 79c810c86ba..78abafe1f53 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -7350,8 +7350,14 @@ done:
}
if (omp_target_seen)
- omp_requires_mask = (enum omp_requires) (omp_requires_mask
- | OMP_REQUIRES_TARGET_USED);
+ {
+ omp_requires_mask = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_TARGET_USED);
+ if (flag_openmp_force_usm)
+ omp_requires_mask
+ = (enum omp_requires) (omp_requires_mask
+ | OMP_REQUIRES_UNIFIED_SHARED_MEMORY);
+ }
if (omp_requires & OMP_REQ_REVERSE_OFFLOAD)
omp_requires_mask = (enum omp_requires) (omp_requires_mask
| OMP_REQUIRES_REVERSE_OFFLOAD);