Skip to content

Conversation

kparzysz
Copy link
Contributor

No description provided.

REQUIRES clauses apply to the compilation unit, which the OpenMP spec
defines as the program unit in Fortran.

Don't set REQUIRES flags on all containing scopes, only on the containng
program unit, where flags coming from different directives are gathered.
If we wanted to set the flags on subprograms, we would need to first
accummulate all of them, then propagate them down to all subprograms.
That is not done as it is not necessary (the containing program unit is
always available).
For each program unit, collect the set of requirements from REQUIRES
directives in the source, and modules used by the program unit, and
add them to the details of the program unit symbol.

The requirements in the symbol details as now stored as clauses. Since
requirements need to be emitted in the module files as OpenMP directives,
this makes the clause emission straightforward via getOpenMPClauseName.

Each program unit, including modules, the corresponding symbol will have
the transitive closure of the requirements for everything contained or
used in that program unit.
@kparzysz kparzysz requested review from Stylie777 and tblah October 14, 2025 20:50
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:openmp flang:semantics labels Oct 14, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 14, 2025

@llvm/pr-subscribers-flang-openmp

Author: Krzysztof Parzyszek (kparzysz)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/163450.diff

3 Files Affected:

  • (modified) flang/include/flang/Semantics/symbol.h (+3)
  • (modified) flang/lib/Semantics/symbol.cpp (+31-1)
  • (added) flang/test/Semantics/OpenMP/dump-requires-details.f90 (+14)
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 14da5b443633f..04a063957082a 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -73,6 +73,9 @@ class WithOmpDeclarative {
     ompAtomicDefaultMemOrder_ = flags;
   }
 
+  friend llvm::raw_ostream &operator<<(
+      llvm::raw_ostream &, const WithOmpDeclarative &);
+
 private:
   std::optional<RequiresClauses> ompRequires_;
   std::optional<common::OmpMemoryOrderType> ompAtomicDefaultMemOrder_;
diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index 69169469fe8ce..a5f9706a73cf7 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -70,6 +70,32 @@ static void DumpList(llvm::raw_ostream &os, const char *label, const T &list) {
   }
 }
 
+llvm::raw_ostream &operator<<(
+    llvm::raw_ostream &os, const WithOmpDeclarative &x) {
+  if (x.has_ompRequires() || x.has_ompAtomicDefaultMemOrder()) {
+    os << " OmpRequirements:(";
+    if (const common::OmpMemoryOrderType *atmo{x.ompAtomicDefaultMemOrder()}) {
+      os << parser::ToLowerCaseLetters(llvm::omp::getOpenMPClauseName(
+                llvm::omp::Clause::OMPC_atomic_default_mem_order))
+         << '(' << parser::ToLowerCaseLetters(EnumToString(*atmo)) << ')';
+      if (x.has_ompRequires()) {
+        os << ',';
+      }
+    }
+    if (const WithOmpDeclarative::RequiresClauses *reqs{x.ompRequires()}) {
+      size_t num{0}, size{reqs->count()};
+      reqs->IterateOverMembers([&](llvm::omp::Clause f) {
+        os << parser::ToLowerCaseLetters(llvm::omp::getOpenMPClauseName(f));
+        if (++num < size) {
+          os << ',';
+        }
+      });
+    }
+    os << ')';
+  }
+  return os;
+}
+
 void SubprogramDetails::set_moduleInterface(Symbol &symbol) {
   CHECK(!moduleInterface_);
   moduleInterface_ = &symbol;
@@ -150,6 +176,7 @@ llvm::raw_ostream &operator<<(
       os << x;
     }
   }
+  os << static_cast<const WithOmpDeclarative&>(x);
   return os;
 }
 
@@ -580,7 +607,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
   common::visit( //
       common::visitors{
           [&](const UnknownDetails &) {},
-          [&](const MainProgramDetails &) {},
+          [&](const MainProgramDetails &x) {
+            os << static_cast<const WithOmpDeclarative&>(x);
+          },
           [&](const ModuleDetails &x) {
             if (x.isSubmodule()) {
               os << " (";
@@ -599,6 +628,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
             if (x.isDefaultPrivate()) {
               os << " isDefaultPrivate";
             }
+            os << static_cast<const WithOmpDeclarative&>(x);
           },
           [&](const SubprogramNameDetails &x) {
             os << ' ' << EnumToString(x.kind());
diff --git a/flang/test/Semantics/OpenMP/dump-requires-details.f90 b/flang/test/Semantics/OpenMP/dump-requires-details.f90
new file mode 100644
index 0000000000000..9c844c092c5e6
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/dump-requires-details.f90
@@ -0,0 +1,14 @@
+!RUN: %flang_fc1 -fopenmp -fopenmp-version=60 -fdebug-dump-symbols %s | FileCheck %s
+
+module fred
+!$omp requires atomic_default_mem_order(relaxed)
+contains
+subroutine f00
+  !$omp requires unified_address
+end
+subroutine f01
+  !$omp requires unified_shared_memory
+end
+end module
+
+!CHECK: fred: Module OmpRequirements:(atomic_default_mem_order(relaxed),unified_address,unified_shared_memory)

@llvmbot
Copy link
Member

llvmbot commented Oct 14, 2025

@llvm/pr-subscribers-flang-semantics

Author: Krzysztof Parzyszek (kparzysz)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/163450.diff

3 Files Affected:

  • (modified) flang/include/flang/Semantics/symbol.h (+3)
  • (modified) flang/lib/Semantics/symbol.cpp (+31-1)
  • (added) flang/test/Semantics/OpenMP/dump-requires-details.f90 (+14)
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index 14da5b443633f..04a063957082a 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -73,6 +73,9 @@ class WithOmpDeclarative {
     ompAtomicDefaultMemOrder_ = flags;
   }
 
+  friend llvm::raw_ostream &operator<<(
+      llvm::raw_ostream &, const WithOmpDeclarative &);
+
 private:
   std::optional<RequiresClauses> ompRequires_;
   std::optional<common::OmpMemoryOrderType> ompAtomicDefaultMemOrder_;
diff --git a/flang/lib/Semantics/symbol.cpp b/flang/lib/Semantics/symbol.cpp
index 69169469fe8ce..a5f9706a73cf7 100644
--- a/flang/lib/Semantics/symbol.cpp
+++ b/flang/lib/Semantics/symbol.cpp
@@ -70,6 +70,32 @@ static void DumpList(llvm::raw_ostream &os, const char *label, const T &list) {
   }
 }
 
+llvm::raw_ostream &operator<<(
+    llvm::raw_ostream &os, const WithOmpDeclarative &x) {
+  if (x.has_ompRequires() || x.has_ompAtomicDefaultMemOrder()) {
+    os << " OmpRequirements:(";
+    if (const common::OmpMemoryOrderType *atmo{x.ompAtomicDefaultMemOrder()}) {
+      os << parser::ToLowerCaseLetters(llvm::omp::getOpenMPClauseName(
+                llvm::omp::Clause::OMPC_atomic_default_mem_order))
+         << '(' << parser::ToLowerCaseLetters(EnumToString(*atmo)) << ')';
+      if (x.has_ompRequires()) {
+        os << ',';
+      }
+    }
+    if (const WithOmpDeclarative::RequiresClauses *reqs{x.ompRequires()}) {
+      size_t num{0}, size{reqs->count()};
+      reqs->IterateOverMembers([&](llvm::omp::Clause f) {
+        os << parser::ToLowerCaseLetters(llvm::omp::getOpenMPClauseName(f));
+        if (++num < size) {
+          os << ',';
+        }
+      });
+    }
+    os << ')';
+  }
+  return os;
+}
+
 void SubprogramDetails::set_moduleInterface(Symbol &symbol) {
   CHECK(!moduleInterface_);
   moduleInterface_ = &symbol;
@@ -150,6 +176,7 @@ llvm::raw_ostream &operator<<(
       os << x;
     }
   }
+  os << static_cast<const WithOmpDeclarative&>(x);
   return os;
 }
 
@@ -580,7 +607,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
   common::visit( //
       common::visitors{
           [&](const UnknownDetails &) {},
-          [&](const MainProgramDetails &) {},
+          [&](const MainProgramDetails &x) {
+            os << static_cast<const WithOmpDeclarative&>(x);
+          },
           [&](const ModuleDetails &x) {
             if (x.isSubmodule()) {
               os << " (";
@@ -599,6 +628,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Details &details) {
             if (x.isDefaultPrivate()) {
               os << " isDefaultPrivate";
             }
+            os << static_cast<const WithOmpDeclarative&>(x);
           },
           [&](const SubprogramNameDetails &x) {
             os << ' ' << EnumToString(x.kind());
diff --git a/flang/test/Semantics/OpenMP/dump-requires-details.f90 b/flang/test/Semantics/OpenMP/dump-requires-details.f90
new file mode 100644
index 0000000000000..9c844c092c5e6
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/dump-requires-details.f90
@@ -0,0 +1,14 @@
+!RUN: %flang_fc1 -fopenmp -fopenmp-version=60 -fdebug-dump-symbols %s | FileCheck %s
+
+module fred
+!$omp requires atomic_default_mem_order(relaxed)
+contains
+subroutine f00
+  !$omp requires unified_address
+end
+subroutine f01
+  !$omp requires unified_shared_memory
+end
+end module
+
+!CHECK: fred: Module OmpRequirements:(atomic_default_mem_order(relaxed),unified_address,unified_shared_memory)

Copy link

github-actions bot commented Oct 14, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Base automatically changed from users/kparzysz/q02-module-requires to main October 16, 2025 12:02
Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

@kparzysz kparzysz merged commit a45bbd4 into main Oct 16, 2025
10 checks passed
@kparzysz kparzysz deleted the users/kparzysz/q03-dump-requires-details branch October 16, 2025 12:27
@klausler
Copy link
Contributor

This patch breaks a gfortran regression test (llvm-test-suite/Fortran/gfortran/regression/gomp/requires-9.f90) and that has broken the "2stage" build bots like https://lab.llvm.org/buildbot/#/builders/41/builds/9666.

@kparzysz
Copy link
Contributor Author

This patch breaks a gfortran regression test (llvm-test-suite/Fortran/gfortran/regression/gomp/requires-9.f90) and that has broken the "2stage" build bots like https://lab.llvm.org/buildbot/#/builders/41/builds/9666.

It's actually the module one that did it (163449). I have a PR with a fix pending review: #163805. Sorry about the inconvenience.

@klausler
Copy link
Contributor

This patch breaks a gfortran regression test (llvm-test-suite/Fortran/gfortran/regression/gomp/requires-9.f90) and that has broken the "2stage" build bots like https://lab.llvm.org/buildbot/#/builders/41/builds/9666.

It's actually the module one that did it (163449). I have a PR with a fix pending review: #163805. Sorry about the inconvenience.

Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:openmp flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants