[flang] [llvm] [Frontend][OpenMP] Move isPrivatizingConstruct from flang (PR #155477)

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 26 12:34:36 PDT 2025


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/155477

The check of whether a construct can privatize is a general utility, not dependent on language-specific definitions.

>From 800d99c1559c3375e5d3d7aae09e773e97d34289 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 26 Aug 2025 14:23:59 -0500
Subject: [PATCH] [Frontend][OpenMP] Move isPrivatizingConstruct from flang

The check of whether a construct can privatize is a general utility,
not dependent on language-specific definitions.
---
 .../lib/Lower/OpenMP/DataSharingProcessor.cpp | 42 ++-----------------
 llvm/include/llvm/Frontend/OpenMP/OMP.h       |  4 ++
 llvm/lib/Frontend/OpenMP/OMP.cpp              | 34 +++++++++++++++
 3 files changed, 41 insertions(+), 39 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 9d1c730b38edd..c4054ef0fc961 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -30,6 +30,7 @@
 #include "flang/Semantics/tools.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 #include <variant>
 
 namespace Fortran {
@@ -422,47 +423,10 @@ static parser::CharBlock getSource(const semantics::SemanticsContext &semaCtx,
   });
 }
 
-static void collectPrivatizingConstructs(
-    llvm::SmallSet<llvm::omp::Directive, 16> &constructs, unsigned version) {
-  using Clause = llvm::omp::Clause;
-  using Directive = llvm::omp::Directive;
-
-  static const Clause privatizingClauses[] = {
-      Clause::OMPC_private,
-      Clause::OMPC_lastprivate,
-      Clause::OMPC_firstprivate,
-      Clause::OMPC_in_reduction,
-      Clause::OMPC_reduction,
-      Clause::OMPC_linear,
-      // TODO: Clause::OMPC_induction,
-      Clause::OMPC_task_reduction,
-      Clause::OMPC_detach,
-      Clause::OMPC_use_device_ptr,
-      Clause::OMPC_is_device_ptr,
-  };
-
-  for (auto dir : llvm::enum_seq_inclusive<Directive>(Directive::First_,
-                                                      Directive::Last_)) {
-    bool allowsPrivatizing = llvm::any_of(privatizingClauses, [&](Clause cls) {
-      return llvm::omp::isAllowedClauseForDirective(dir, cls, version);
-    });
-    if (allowsPrivatizing)
-      constructs.insert(dir);
-  }
-}
-
 bool DataSharingProcessor::isOpenMPPrivatizingConstruct(
     const parser::OpenMPConstruct &omp, unsigned version) {
-  static llvm::SmallSet<llvm::omp::Directive, 16> privatizing;
-  [[maybe_unused]] static bool init =
-      (collectPrivatizingConstructs(privatizing, version), true);
-
-  // As of OpenMP 6.0, privatizing constructs (with the test being if they
-  // allow a privatizing clause) are: dispatch, distribute, do, for, loop,
-  // parallel, scope, sections, simd, single, target, target_data, task,
-  // taskgroup, taskloop, and teams.
-  return llvm::is_contained(privatizing,
-                            parser::omp::GetOmpDirectiveName(omp).v);
+  return llvm::omp::isPrivatizingConstruct(
+      parser::omp::GetOmpDirectiveName(omp).v, version);
 }
 
 bool DataSharingProcessor::isOpenMPPrivatizingEvaluation(
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.h b/llvm/include/llvm/Frontend/OpenMP/OMP.h
index 9d0a55432e1ae..d5d08aed76e12 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.h
@@ -71,6 +71,10 @@ static constexpr inline bool isPrivatizingClause(Clause C) {
 static constexpr unsigned FallbackVersion = 52;
 LLVM_ABI ArrayRef<unsigned> getOpenMPVersions();
 
+/// Can directive D, under some circumstances, create a private copy
+/// of a variable in given OpenMP version?
+bool isPrivatizingConstruct(Directive D, unsigned Version);
+
 /// Create a nicer version of a function name for humans to look at.
 LLVM_ABI std::string prettifyFunctionName(StringRef FunctionName);
 
diff --git a/llvm/lib/Frontend/OpenMP/OMP.cpp b/llvm/lib/Frontend/OpenMP/OMP.cpp
index 9e625b809de9e..f12941492547e 100644
--- a/llvm/lib/Frontend/OpenMP/OMP.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMP.cpp
@@ -9,6 +9,8 @@
 #include "llvm/Frontend/OpenMP/OMP.h"
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Sequence.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Demangle/Demangle.h"
@@ -75,6 +77,26 @@ getFirstCompositeRange(iterator_range<ArrayRef<Directive>::iterator> Leafs) {
   return llvm::make_range(Begin, End);
 }
 
+static void
+collectPrivatizingConstructs(llvm::SmallSet<Directive, 16> &Constructs,
+                             unsigned Version) {
+  llvm::SmallSet<Clause, 16> Privatizing;
+  for (auto C :
+       llvm::enum_seq_inclusive<Clause>(Clause::First_, Clause::Last_)) {
+    if (isPrivatizingClause(C))
+      Privatizing.insert(C);
+  }
+
+  for (auto D : llvm::enum_seq_inclusive<Directive>(Directive::First_,
+                                                    Directive::Last_)) {
+    bool AllowsPrivatizing = llvm::any_of(Privatizing, [&](Clause C) {
+      return isAllowedClauseForDirective(D, C, Version);
+    });
+    if (AllowsPrivatizing)
+      Constructs.insert(D);
+  }
+}
+
 namespace llvm::omp {
 ArrayRef<Directive> getLeafConstructs(Directive D) {
   auto Idx = static_cast<std::size_t>(D);
@@ -194,6 +216,18 @@ ArrayRef<unsigned> getOpenMPVersions() {
   return Versions;
 }
 
+bool isPrivatizingConstruct(Directive D, unsigned Version) {
+  static llvm::SmallSet<Directive, 16> Privatizing;
+  [[maybe_unused]] static bool Init =
+      (collectPrivatizingConstructs(Privatizing, Version), true);
+
+  // As of OpenMP 6.0, privatizing constructs (with the test being if they
+  // allow a privatizing clause) are: dispatch, distribute, do, for, loop,
+  // parallel, scope, sections, simd, single, target, target_data, task,
+  // taskgroup, taskloop, and teams.
+  return llvm::is_contained(Privatizing, D);
+}
+
 std::string prettifyFunctionName(StringRef FunctionName) {
   // Internalized functions have the right name, but simply a suffix.
   if (FunctionName.ends_with(".internalized"))



More information about the llvm-commits mailing list