openmp, c++: Fix up OpenMP/OpenACC handling in C++ modules [PR119102]
modules.cc has apparently support for extensions and attempts to ensure that if a module is compiled with those extensions enabled, sources which use the module are compiled with the same extensions. The only extension supported is SE_OPENMP right now. And the use of the extension is keyed on streaming out or in OMP_CLAUSE tree. This is undesirable for several reasons. OMP_CLAUSE is the only tree which can appear in the IL even without -fopenmp/-fopenmp-simd/-fopenacc (when simd ("notinbranch") or simd ("inbranch") attributes are used), and it can appear also in all the 3 modes mentioned above. On the other side, with the exception of arguments of attributes added e.g. for declare simd where no harm should be done if -fopenmp/-fopenmp-simd isn't enabled later on, OMP_CLAUSE appears in OMP_*_CLAUSES of OpenMP/OpenACC construct trees. And those construct trees often have no clauses at all, so keying the extension on OMP_CLAUSE doesn't catch many cases that should be caught. Furthermore, for OpenMP we have 2 modes, -fopenmp-simd which parses some OpenMP but constructs from that mostly OMP_SIMD and a few other cases, and -fopenmp which includes that and far more on top of that; and there is also -fopenacc. So, this patch stops setting/requesting the extension on OMP_CLAUSE, introduces 3 extensions rather than one (SE_OPENMP_SIMD, SE_OPENMP and SE_OPENACC) and keyes those on OpenMP constructs from the -fopenmp-simd subset, other OpenMP constructs and OpenACC constructs. 2025-03-05 Jakub Jelinek <jakub@redhat.com> PR c++/119102 gcc/cp/ * module.cc (enum streamed_extensions): Add SE_OPENMP_SIMD and SE_OPENACC, change value of SE_OPENMP and SE_BITS. (CASE_OMP_SIMD_CODE, CASE_OMP_CODE, CASE_OACC_CODE): Define. (trees_out::start): Don't set SE_OPENMP extension for OMP_CLAUSE. Set SE_OPENMP_SIMD extension for CASE_OMP_SIMD_CODE, SE_OPENMP for CASE_OMP_CODE and SE_OPENACC for CASE_OACC_CODE. (trees_in::start): Don't fail for OMP_CLAUSE with missing SE_OPENMP extension. Do fail for CASE_OMP_SIMD_CODE and missing SE_OPENMP_SIMD extension, or CASE_OMP_CODE and missing SE_OPENMP extension, or CASE_OACC_CODE and missing SE_OPENACC extension. (module_state::write_readme): Write all of SE_OPENMP_SIMD, SE_OPENMP and SE_OPENACC extensions. (module_state::read_config): Diagnose missing -fopenmp, -fopenmp-simd and/or -fopenacc depending on extensions used. gcc/testsuite/ * g++.dg/modules/pr119102_a.H: New test. * g++.dg/modules/pr119102_b.C: New test. * g++.dg/modules/omp-3_a.C: New test. * g++.dg/modules/omp-3_b.C: New test. * g++.dg/modules/omp-3_c.C: New test. * g++.dg/modules/omp-3_d.C: New test. * g++.dg/modules/oacc-1_a.C: New test. * g++.dg/modules/oacc-1_b.C: New test. * g++.dg/modules/oacc-1_c.C: New test.
This commit is contained in:
parent
b85b405ed3
commit
ddeb70548c
10 changed files with 197 additions and 12 deletions
111
gcc/cp/module.cc
111
gcc/cp/module.cc
|
@ -3613,8 +3613,10 @@ void slurping::release_macros ()
|
|||
/* Flags for extensions that end up being streamed. */
|
||||
|
||||
enum streamed_extensions {
|
||||
SE_OPENMP = 1 << 0,
|
||||
SE_BITS = 1
|
||||
SE_OPENMP_SIMD = 1 << 0,
|
||||
SE_OPENMP = 1 << 1,
|
||||
SE_OPENACC = 1 << 2,
|
||||
SE_BITS = 3
|
||||
};
|
||||
|
||||
/* Counter indices. */
|
||||
|
@ -5276,6 +5278,53 @@ trees_in::tree_list (bool has_purpose)
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define CASE_OMP_SIMD_CODE \
|
||||
case OMP_SIMD: \
|
||||
case OMP_STRUCTURED_BLOCK: \
|
||||
case OMP_LOOP: \
|
||||
case OMP_ORDERED: \
|
||||
case OMP_TILE: \
|
||||
case OMP_UNROLL
|
||||
#define CASE_OMP_CODE \
|
||||
case OMP_PARALLEL: \
|
||||
case OMP_TASK: \
|
||||
case OMP_FOR: \
|
||||
case OMP_DISTRIBUTE: \
|
||||
case OMP_TASKLOOP: \
|
||||
case OMP_TEAMS: \
|
||||
case OMP_TARGET_DATA: \
|
||||
case OMP_TARGET: \
|
||||
case OMP_SECTIONS: \
|
||||
case OMP_CRITICAL: \
|
||||
case OMP_SINGLE: \
|
||||
case OMP_SCOPE: \
|
||||
case OMP_TASKGROUP: \
|
||||
case OMP_MASKED: \
|
||||
case OMP_DISPATCH: \
|
||||
case OMP_INTEROP: \
|
||||
case OMP_MASTER: \
|
||||
case OMP_TARGET_UPDATE: \
|
||||
case OMP_TARGET_ENTER_DATA: \
|
||||
case OMP_TARGET_EXIT_DATA: \
|
||||
case OMP_METADIRECTIVE: \
|
||||
case OMP_ATOMIC: \
|
||||
case OMP_ATOMIC_READ: \
|
||||
case OMP_ATOMIC_CAPTURE_OLD: \
|
||||
case OMP_ATOMIC_CAPTURE_NEW
|
||||
#define CASE_OACC_CODE \
|
||||
case OACC_PARALLEL: \
|
||||
case OACC_KERNELS: \
|
||||
case OACC_SERIAL: \
|
||||
case OACC_DATA: \
|
||||
case OACC_HOST_DATA: \
|
||||
case OACC_LOOP: \
|
||||
case OACC_CACHE: \
|
||||
case OACC_DECLARE: \
|
||||
case OACC_ENTER_DATA: \
|
||||
case OACC_EXIT_DATA: \
|
||||
case OACC_UPDATE
|
||||
|
||||
/* Start tree write. Write information to allocate the receiving
|
||||
node. */
|
||||
|
||||
|
@ -5311,10 +5360,21 @@ trees_out::start (tree t, bool code_streamed)
|
|||
break;
|
||||
|
||||
case OMP_CLAUSE:
|
||||
state->extensions |= SE_OPENMP;
|
||||
u (OMP_CLAUSE_CODE (t));
|
||||
break;
|
||||
|
||||
CASE_OMP_SIMD_CODE:
|
||||
state->extensions |= SE_OPENMP_SIMD;
|
||||
break;
|
||||
|
||||
CASE_OMP_CODE:
|
||||
state->extensions |= SE_OPENMP;
|
||||
break;
|
||||
|
||||
CASE_OACC_CODE:
|
||||
state->extensions |= SE_OPENACC;
|
||||
break;
|
||||
|
||||
case STRING_CST:
|
||||
str (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t));
|
||||
break;
|
||||
|
@ -5383,13 +5443,25 @@ trees_in::start (unsigned code)
|
|||
break;
|
||||
|
||||
case OMP_CLAUSE:
|
||||
{
|
||||
if (!(state->extensions & SE_OPENMP))
|
||||
goto fail;
|
||||
t = build_omp_clause (UNKNOWN_LOCATION, omp_clause_code (u ()));
|
||||
break;
|
||||
|
||||
unsigned omp_code = u ();
|
||||
t = build_omp_clause (UNKNOWN_LOCATION, omp_clause_code (omp_code));
|
||||
}
|
||||
CASE_OMP_SIMD_CODE:
|
||||
if (!(state->extensions & SE_OPENMP_SIMD))
|
||||
goto fail;
|
||||
t = make_node (tree_code (code));
|
||||
break;
|
||||
|
||||
CASE_OMP_CODE:
|
||||
if (!(state->extensions & SE_OPENMP))
|
||||
goto fail;
|
||||
t = make_node (tree_code (code));
|
||||
break;
|
||||
|
||||
CASE_OACC_CODE:
|
||||
if (!(state->extensions & SE_OPENACC))
|
||||
goto fail;
|
||||
t = make_node (tree_code (code));
|
||||
break;
|
||||
|
||||
case STRING_CST:
|
||||
|
@ -15402,8 +15474,13 @@ module_state::write_readme (elf_out *to, cpp_reader *reader, const char *dialect
|
|||
readme.printf ("source: %s", main_input_filename);
|
||||
readme.printf ("dialect: %s", dialect);
|
||||
if (extensions)
|
||||
readme.printf ("extensions: %s",
|
||||
extensions & SE_OPENMP ? "-fopenmp" : "");
|
||||
readme.printf ("extensions: %s%s%s",
|
||||
extensions & SE_OPENMP ? "-fopenmp"
|
||||
: extensions & SE_OPENMP_SIMD ? "-fopenmp-simd" : "",
|
||||
(extensions & SE_OPENACC)
|
||||
&& (extensions & (SE_OPENMP | SE_OPENMP_SIMD))
|
||||
? " " : "",
|
||||
extensions & SE_OPENACC ? "-fopenacc" : "");
|
||||
|
||||
/* The following fields could be expected to change between
|
||||
otherwise identical compilations. Consider a distributed build
|
||||
|
@ -19166,12 +19243,22 @@ module_state::read_config (module_state_config &config)
|
|||
too. */
|
||||
{
|
||||
unsigned ext = cfg.u ();
|
||||
unsigned allowed = (flag_openmp ? SE_OPENMP : 0);
|
||||
unsigned allowed = (flag_openmp ? SE_OPENMP | SE_OPENMP_SIMD : 0);
|
||||
if (flag_openmp_simd)
|
||||
allowed |= SE_OPENMP_SIMD;
|
||||
if (flag_openacc)
|
||||
allowed |= SE_OPENACC;
|
||||
|
||||
if (unsigned bad = ext & ~allowed)
|
||||
{
|
||||
if (bad & SE_OPENMP)
|
||||
error_at (loc, "module contains OpenMP, use %<-fopenmp%> to enable");
|
||||
else if (bad & SE_OPENMP_SIMD)
|
||||
error_at (loc, "module contains OpenMP, use %<-fopenmp%> or "
|
||||
"%<-fopenmp-simd%> to enable");
|
||||
if (bad & SE_OPENACC)
|
||||
error_at (loc, "module contains OpenACC, use %<-fopenacc%> to "
|
||||
"enable");
|
||||
cfg.set_overrun ();
|
||||
goto done;
|
||||
}
|
||||
|
|
15
gcc/testsuite/g++.dg/modules/oacc-1_a.C
Normal file
15
gcc/testsuite/g++.dg/modules/oacc-1_a.C
Normal file
|
@ -0,0 +1,15 @@
|
|||
// { dg-additional-options "-fmodules-ts -fopenacc" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
export module foo;
|
||||
// { dg-module-cmi foo { target pthread } }
|
||||
|
||||
export inline void frob (unsigned (&ary)[64])
|
||||
{
|
||||
int sum, i;
|
||||
#pragma acc parallel
|
||||
#pragma acc loop gang worker vector reduction (+:sum)
|
||||
for (i = 0; i < 64; i++)
|
||||
sum += ary[i];
|
||||
ary[0] += sum;
|
||||
}
|
11
gcc/testsuite/g++.dg/modules/oacc-1_b.C
Normal file
11
gcc/testsuite/g++.dg/modules/oacc-1_b.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// { dg-additional-options "-fmodules-ts -fopenacc" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
import foo;
|
||||
|
||||
unsigned ary[64];
|
||||
|
||||
int main ()
|
||||
{
|
||||
frob (ary);
|
||||
}
|
9
gcc/testsuite/g++.dg/modules/oacc-1_c.C
Normal file
9
gcc/testsuite/g++.dg/modules/oacc-1_c.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// { dg-additional-options "-fmodules-ts" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
import foo;
|
||||
|
||||
// { dg-regexp "In module imported at \[^\n]*oacc-1_c.C:4:1:\nfoo: error: module contains OpenACC, use '-fopenacc' to enable\n" }
|
||||
// { dg-prune-output "failed to read" }
|
||||
// { dg-prune-output "fatal error:" }
|
||||
// { dg-prune-output "compilation terminated" }
|
14
gcc/testsuite/g++.dg/modules/omp-3_a.C
Normal file
14
gcc/testsuite/g++.dg/modules/omp-3_a.C
Normal file
|
@ -0,0 +1,14 @@
|
|||
// { dg-additional-options "-fmodules-ts -fopenmp-simd" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
export module foo;
|
||||
// { dg-module-cmi foo { target pthread } }
|
||||
|
||||
export inline void frob (unsigned (&ary)[64])
|
||||
{
|
||||
int sum = 0;
|
||||
|
||||
#pragma omp simd safelen(16) aligned (ary : 16)
|
||||
for (unsigned ix = 0; ix < 64; ix++)
|
||||
ary[ix] *= 2;
|
||||
}
|
11
gcc/testsuite/g++.dg/modules/omp-3_b.C
Normal file
11
gcc/testsuite/g++.dg/modules/omp-3_b.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// { dg-additional-options "-fmodules-ts -fopenmp-simd" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
import foo;
|
||||
|
||||
unsigned ary[64];
|
||||
|
||||
int main ()
|
||||
{
|
||||
frob (ary);
|
||||
}
|
11
gcc/testsuite/g++.dg/modules/omp-3_c.C
Normal file
11
gcc/testsuite/g++.dg/modules/omp-3_c.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// { dg-additional-options "-fmodules-ts -fopenmp" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
import foo;
|
||||
|
||||
unsigned ary[64];
|
||||
|
||||
int main ()
|
||||
{
|
||||
frob (ary);
|
||||
}
|
9
gcc/testsuite/g++.dg/modules/omp-3_d.C
Normal file
9
gcc/testsuite/g++.dg/modules/omp-3_d.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// { dg-additional-options "-fmodules-ts" }
|
||||
// { dg-require-effective-target pthread }
|
||||
|
||||
import foo;
|
||||
|
||||
// { dg-regexp "In module imported at \[^\n]*omp-3_d.C:4:1:\nfoo: error: module contains OpenMP, use '-fopenmp' or '-fopenmp-simd' to enable\n" }
|
||||
// { dg-prune-output "failed to read" }
|
||||
// { dg-prune-output "fatal error:" }
|
||||
// { dg-prune-output "compilation terminated" }
|
9
gcc/testsuite/g++.dg/modules/pr119102_a.H
Normal file
9
gcc/testsuite/g++.dg/modules/pr119102_a.H
Normal file
|
@ -0,0 +1,9 @@
|
|||
// PR c++/119102
|
||||
// { dg-additional-options "-fmodule-header" }
|
||||
// { dg-module-cmi {} }
|
||||
|
||||
int foo (int)
|
||||
#if defined __x86_64__ || defined __aarch64__
|
||||
__attribute__((simd ("notinbranch")))
|
||||
#endif
|
||||
;
|
9
gcc/testsuite/g++.dg/modules/pr119102_b.C
Normal file
9
gcc/testsuite/g++.dg/modules/pr119102_b.C
Normal file
|
@ -0,0 +1,9 @@
|
|||
// PR c++/119102
|
||||
// { dg-additional-options "-fmodules-ts" }
|
||||
|
||||
import "pr119102_a.H";
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
}
|
Loading…
Add table
Reference in a new issue