https://gcc.gnu.org/g:ddeb70548c81f5dba91f281290584698897151d8

commit r15-7824-gddeb70548c81f5dba91f281290584698897151d8
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Wed Mar 5 07:47:52 2025 +0100

    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  <ja...@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.

Diff:
---
 gcc/cp/module.cc                          | 111 ++++++++++++++++++++++++++----
 gcc/testsuite/g++.dg/modules/oacc-1_a.C   |  15 ++++
 gcc/testsuite/g++.dg/modules/oacc-1_b.C   |  11 +++
 gcc/testsuite/g++.dg/modules/oacc-1_c.C   |   9 +++
 gcc/testsuite/g++.dg/modules/omp-3_a.C    |  14 ++++
 gcc/testsuite/g++.dg/modules/omp-3_b.C    |  11 +++
 gcc/testsuite/g++.dg/modules/omp-3_c.C    |  11 +++
 gcc/testsuite/g++.dg/modules/omp-3_d.C    |   9 +++
 gcc/testsuite/g++.dg/modules/pr119102_a.H |   9 +++
 gcc/testsuite/g++.dg/modules/pr119102_b.C |   9 +++
 10 files changed, 197 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 59716e1873e9..8b0f42951c24 100644
--- a/gcc/cp/module.cc
+++ b/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;
       }
diff --git a/gcc/testsuite/g++.dg/modules/oacc-1_a.C 
b/gcc/testsuite/g++.dg/modules/oacc-1_a.C
new file mode 100644
index 000000000000..e3f802d4aa55
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/oacc-1_a.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/modules/oacc-1_b.C 
b/gcc/testsuite/g++.dg/modules/oacc-1_b.C
new file mode 100644
index 000000000000..6546b6f3eea6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/oacc-1_b.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fopenacc" }
+// { dg-require-effective-target pthread }
+
+import foo;
+
+unsigned ary[64];
+
+int main ()
+{
+  frob (ary);
+}
diff --git a/gcc/testsuite/g++.dg/modules/oacc-1_c.C 
b/gcc/testsuite/g++.dg/modules/oacc-1_c.C
new file mode 100644
index 000000000000..e340cbe9bff6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/oacc-1_c.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/modules/omp-3_a.C 
b/gcc/testsuite/g++.dg/modules/omp-3_a.C
new file mode 100644
index 000000000000..b449f3820f23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-3_a.C
@@ -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;
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-3_b.C 
b/gcc/testsuite/g++.dg/modules/omp-3_b.C
new file mode 100644
index 000000000000..da943cbf6499
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-3_b.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-3_c.C 
b/gcc/testsuite/g++.dg/modules/omp-3_c.C
new file mode 100644
index 000000000000..09d97e4ac4eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-3_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options "-fmodules-ts -fopenmp" }
+// { dg-require-effective-target pthread }
+
+import foo;
+
+unsigned ary[64];
+
+int main ()
+{
+  frob (ary);
+}
diff --git a/gcc/testsuite/g++.dg/modules/omp-3_d.C 
b/gcc/testsuite/g++.dg/modules/omp-3_d.C
new file mode 100644
index 000000000000..fdfe323119e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/omp-3_d.C
@@ -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" }
diff --git a/gcc/testsuite/g++.dg/modules/pr119102_a.H 
b/gcc/testsuite/g++.dg/modules/pr119102_a.H
new file mode 100644
index 000000000000..61b467a484a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119102_a.H
@@ -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
+;
diff --git a/gcc/testsuite/g++.dg/modules/pr119102_b.C 
b/gcc/testsuite/g++.dg/modules/pr119102_b.C
new file mode 100644
index 000000000000..5015fd4a3404
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119102_b.C
@@ -0,0 +1,9 @@
+// PR c++/119102
+// { dg-additional-options "-fmodules-ts" }
+
+import "pr119102_a.H";
+
+int
+main ()
+{
+}

Reply via email to