[flang-commits] [flang] [flang][OpenMP] Implement utility to locate OmpClause in ODS, NFC (PR #184866)

Krzysztof Parzyszek via flang-commits flang-commits at lists.llvm.org
Thu Mar 5 11:50:20 PST 2026


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

Simplify looking for a specific clause in OmpDirectiveSpecification. This is alternative to DirectiveStructureChecker::FindClause for when the internal checker structures have not yet been updated in the AST traversal.

>From d679178933f60c788eab3ceed690f56b4f834208 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 5 Mar 2026 10:30:13 -0600
Subject: [PATCH] [flang][OpenMP] Implement utility to locate OmpClause in ODS,
 NFC

Simplify looking for a specific clause in OmpDirectiveSpecification.
This is alternative to DirectiveStructureChecker::FindClause for when
the internal checker structures have not yet been updated in the AST
traversal.
---
 flang/include/flang/Parser/openmp-utils.h   |  3 +
 flang/lib/Lower/OpenMP/Utils.cpp            | 10 +--
 flang/lib/Parser/openmp-utils.cpp           | 10 +++
 flang/lib/Parser/parse-tree.cpp             |  8 +--
 flang/lib/Semantics/check-omp-loop.cpp      | 71 +++++++++------------
 flang/lib/Semantics/check-omp-structure.cpp | 18 ++----
 6 files changed, 53 insertions(+), 67 deletions(-)

diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index b8fb6078d59a5..f23e52585d567 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -226,6 +226,9 @@ const T *GetFirstArgument(const OmpDirectiveSpecification &spec) {
   return nullptr;
 }
 
+const OmpClause *FindClause(
+    const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId);
+
 const BlockConstruct *GetFortranBlockConstruct(
     const ExecutionPartConstruct &epc);
 const Block &GetInnermostExecPart(const Block &block);
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index e9ba5f386803a..394c7a485525f 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -786,13 +786,9 @@ static void processTileSizesFromOpenMPConstruct(
           innerConstruct->BeginDir();
       if (innerBeginSpec.DirId() == llvm::omp::Directive::OMPD_tile) {
         // Get the size values from parse tree and convert to a vector.
-        for (const auto &clause : innerBeginSpec.Clauses().v) {
-          if (const auto tclause{
-                  std::get_if<parser::OmpClause::Sizes>(&clause.u)}) {
-            processFun(tclause);
-            break;
-          }
-        }
+        if (auto *clause = parser::omp::FindClause(
+                innerBeginSpec, llvm::omp::Clause::OMPC_sizes))
+          processFun(&std::get<parser::OmpClause::Sizes>(clause->u));
       }
     }
   }
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index c81f48f6323dd..6d4326af78344 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -145,6 +145,16 @@ const OmpObjectList *GetOmpObjectList(const OmpDependClause::TaskDep &x) {
   return &std::get<OmpObjectList>(x.t);
 }
 
+const OmpClause *FindClause(
+    const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId) {
+  for (auto &clause : spec.Clauses().v) {
+    if (clause.Id() == clauseId) {
+      return &clause;
+    }
+  }
+  return nullptr;
+}
+
 const BlockConstruct *GetFortranBlockConstruct(
     const ExecutionPartConstruct &epc) {
   // ExecutionPartConstruct -> ExecutableConstruct
diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index afe28182f8627..5bdfa47bea1cb 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -347,16 +347,12 @@ llvm::omp::Clause OpenMPAtomicConstruct::GetKind() const {
 
 bool OpenMPAtomicConstruct::IsCapture() const {
   const OmpDirectiveSpecification &dirSpec{std::get<OmpBeginDirective>(t)};
-  return llvm::any_of(dirSpec.Clauses().v, [](auto &clause) {
-    return clause.Id() == llvm::omp::Clause::OMPC_capture;
-  });
+  return omp::FindClause(dirSpec, llvm::omp::Clause::OMPC_capture);
 }
 
 bool OpenMPAtomicConstruct::IsCompare() const {
   const OmpDirectiveSpecification &dirSpec{std::get<OmpBeginDirective>(t)};
-  return llvm::any_of(dirSpec.Clauses().v, [](auto &clause) {
-    return clause.Id() == llvm::omp::Clause::OMPC_compare;
-  });
+  return omp::FindClause(dirSpec, llvm::omp::Clause::OMPC_compare);
 }
 } // namespace Fortran::parser
 
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 0cad16dc3deb1..f81bde981594d 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -159,12 +159,11 @@ void OmpStructureChecker::HasInvalidLoopBinding(
   const parser::OmpDirectiveName &beginName{beginSpec.DirName()};
 
   auto teamsBindingChecker = [&](parser::MessageFixedText msg) {
-    for (const auto &clause : beginSpec.Clauses().v) {
-      if (const auto *bindClause{
-              std::get_if<parser::OmpClause::Bind>(&clause.u)}) {
-        if (bindClause->v.v != parser::OmpBindClause::Binding::Teams) {
-          context_.Say(beginName.source, msg);
-        }
+    if (auto *clause{
+            parser::omp::FindClause(beginSpec, llvm::omp::Clause::OMPC_bind)}) {
+      auto &bind{std::get<parser::OmpClause::Bind>(clause->u).v};
+      if (bind.v != parser::OmpBindClause::Binding::Teams) {
+        context_.Say(beginName.source, msg);
       }
     }
   };
@@ -204,11 +203,9 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
           [&](const parser::OmpBlockConstruct &c) {
             const parser::OmpDirectiveSpecification &beginSpec{c.BeginDir()};
             if (beginSpec.DirId() == llvm::omp::Directive::OMPD_ordered) {
-              for (const auto &clause : beginSpec.Clauses().v) {
-                if (std::get_if<parser::OmpClause::Simd>(&clause.u)) {
-                  eligibleSIMD = true;
-                  break;
-                }
+              if (parser::omp::FindClause(
+                      beginSpec, llvm::omp::Clause::OMPC_simd)) {
+                eligibleSIMD = true;
               }
             }
           },
@@ -217,11 +214,9 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
                     &c.u)}) {
               llvm::omp::Directive dirId{ssc->v.DirId()};
               if (dirId == llvm::omp::Directive::OMPD_ordered) {
-                for (const parser::OmpClause &x : ssc->v.Clauses().v) {
-                  if (x.Id() == llvm::omp::Clause::OMPC_simd) {
-                    eligibleSIMD = true;
-                    break;
-                  }
+                if (parser::omp::FindClause(
+                        ssc->v, llvm::omp::Clause::OMPC_simd)) {
+                  eligibleSIMD = true;
                 }
               } else if (dirId == llvm::omp::Directive::OMPD_scan) {
                 eligibleSIMD = true;
@@ -274,9 +269,8 @@ static bool IsFullUnroll(const parser::OpenMPLoopConstruct &x) {
   const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
 
   if (beginSpec.DirName().v == llvm::omp::Directive::OMPD_unroll) {
-    return llvm::none_of(beginSpec.Clauses().v, [](const parser::OmpClause &c) {
-      return c.Id() == llvm::omp::Clause::OMPC_partial;
-    });
+    return parser::omp::FindClause(
+               beginSpec, llvm::omp::Clause::OMPC_partial) == nullptr;
   }
   return false;
 }
@@ -312,15 +306,13 @@ static std::optional<size_t> CountGeneratedNests(
     if (!nestedCount || *nestedCount == 0) {
       return std::nullopt;
     }
-    auto rangeAt{
-        llvm::find_if(beginSpec.Clauses().v, [](const parser::OmpClause &c) {
-          return c.Id() == llvm::omp::Clause::OMPC_looprange;
-        })};
-    if (rangeAt == beginSpec.Clauses().v.end()) {
+    auto *clause{
+        parser::omp::FindClause(beginSpec, llvm::omp::Clause::OMPC_looprange)};
+    if (!clause) {
       return 1;
     }
 
-    auto *loopRange{parser::Unwrap<parser::OmpLooprangeClause>(*rangeAt)};
+    auto *loopRange{parser::Unwrap<parser::OmpLooprangeClause>(*clause)};
     std::optional<int64_t> count{GetIntValue(std::get<1>(loopRange->t))};
     if (!count || *count <= 0) {
       return std::nullopt;
@@ -617,23 +609,22 @@ void OmpStructureChecker::CheckDistLinear(
 
 void OmpStructureChecker::CheckLooprangeBounds(
     const parser::OpenMPLoopConstruct &x) {
-  for (const parser::OmpClause &clause : x.BeginDir().Clauses().v) {
-    if (auto *lrClause{parser::Unwrap<parser::OmpLooprangeClause>(clause)}) {
-      auto first{GetIntValue(std::get<0>(lrClause->t))};
-      auto count{GetIntValue(std::get<1>(lrClause->t))};
-      if (!first || !count || *first <= 0 || *count <= 0) {
-        return;
-      }
-      auto requiredCount{static_cast<size_t>(*first + *count - 1)};
-      if (auto loopCount{CountGeneratedNests(std::get<parser::Block>(x.t))}) {
-        if (*loopCount < requiredCount) {
-          context_.Say(clause.source,
-              "The specified loop range requires %zu loops, but the loop sequence has a length of %zu"_err_en_US,
-              requiredCount, *loopCount);
-        }
-      }
+  if (auto *clause{parser::omp::FindClause(
+          x.BeginDir(), llvm::omp::Clause::OMPC_looprange)}) {
+    auto *lrClause{parser::Unwrap<parser::OmpLooprangeClause>(clause)};
+    auto first{GetIntValue(std::get<0>(lrClause->t))};
+    auto count{GetIntValue(std::get<1>(lrClause->t))};
+    if (!first || !count || *first <= 0 || *count <= 0) {
       return;
     }
+    auto requiredCount{static_cast<size_t>(*first + *count - 1)};
+    if (auto loopCount{CountGeneratedNests(std::get<parser::Block>(x.t))}) {
+      if (*loopCount < requiredCount) {
+        context_.Say(clause->source,
+            "The specified loop range requires %zu loops, but the loop sequence has a length of %zu"_err_en_US,
+            requiredCount, *loopCount);
+      }
+    }
   }
 }
 
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 7ffda12c1fb83..431c41f443f7a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1800,16 +1800,8 @@ void OmpStructureChecker::CheckIndividualAllocateDirective(
     return true;
   }};
 
-  const auto *allocator{[&]() {
-    // Can't use FindClause in Enter (because clauses haven't been visited
-    // yet).
-    for (const parser::OmpClause &c : beginSpec.Clauses().v) {
-      if (c.Id() == llvm::omp::Clause::OMPC_allocator) {
-        return &c;
-      }
-    }
-    return static_cast<const parser::OmpClause *>(nullptr);
-  }()};
+  const auto *allocator{
+      parser::omp::FindClause(beginSpec, llvm::omp::Clause::OMPC_allocator)};
 
   if (InTargetRegion()) {
     bool hasDynAllocators{
@@ -4674,11 +4666,9 @@ void OmpStructureChecker::CheckDoacross(const parser::OmpDoacross &doa) {
       const parser::OmpDirectiveSpecification &beginSpec{(*loopc)->BeginDir()};
       llvm::omp::Directive loopDir{beginSpec.DirId()};
       if (loopDir == llvm::omp::OMPD_do || loopDir == llvm::omp::OMPD_simd) {
-        auto IsOrdered{[](const parser::OmpClause &c) {
-          return c.Id() == llvm::omp::OMPC_ordered;
-        }};
         // If it has ORDERED clause, stop the traversal.
-        if (llvm::any_of(beginSpec.Clauses().v, IsOrdered)) {
+        if (parser::omp::FindClause(
+                beginSpec, llvm::omp::Clause::OMPC_ordered)) {
           break;
         }
       }



More information about the flang-commits mailing list