[flang-commits] [flang] [flang][OpenMP] Move two functions to openmp-utils.cpp, NFC (PR #185291)

Krzysztof Parzyszek via flang-commits flang-commits at lists.llvm.org
Mon Mar 9 05:58:39 PDT 2026


https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/185291

>From 2d7d763b4cb55c3112454d5ad0022048125bc713 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 19 Feb 2026 13:16:34 -0600
Subject: [PATCH 1/3] [flang][OpenMP] Import ExecutionPartIterator et al into
 semantics::omp, NFC

---
 flang/include/flang/Semantics/openmp-utils.h | 13 +++++++++++++
 flang/lib/Semantics/check-omp-loop.cpp       |  3 ---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 90fd36708de0e..221e4cb23eada 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -27,6 +27,14 @@
 #include <type_traits>
 #include <utility>
 
+namespace Fortran::parser::omp {
+struct ExecutionPartIterator;
+struct LoopNestIterator;
+template <typename T> struct ExecutionPartRange;
+using BlockRange = ExecutionPartRange<ExecutionPartIterator>;
+using LoopRange = ExecutionPartRange<LoopNestIterator>;
+} // namespace Fortran::parser::omp
+
 namespace Fortran::semantics {
 class Scope;
 class SemanticsContext;
@@ -34,6 +42,11 @@ class Symbol;
 
 // Add this namespace to avoid potential conflicts
 namespace omp {
+using Fortran::parser::omp::ExecutionPartIterator;
+using Fortran::parser::omp::LoopNestIterator;
+using Fortran::parser::omp::BlockRange;
+using Fortran::parser::omp::LoopRange;
+
 template <typename T, typename U = std::remove_const_t<T>> U AsRvalue(T &t) {
   return U(t);
 }
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index f81bde981594d..e13ea820c7ef6 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -334,7 +334,6 @@ static std::optional<size_t> CountGeneratedNests(const parser::Block &block) {
   // messages about a potentially incorrect loop count.
   // In such cases reset the count to nullopt. Once it becomes nullopt,
   // keep it that way.
-  using LoopRange = parser::omp::LoopRange;
   std::optional<size_t> numLoops{0};
   for (auto &epc : LoopRange(block, LoopRange::Step::Over)) {
     if (auto genCount{CountGeneratedNests(epc)}) {
@@ -371,7 +370,6 @@ void OmpStructureChecker::CheckNestedConstruct(
 
   // Check constructs contained in the body of the loop construct.
   auto &body{std::get<parser::Block>(x.t)};
-  using BlockRange = parser::omp::BlockRange;
   for (auto &stmt : BlockRange(body, BlockRange::Step::Over)) {
     if (auto *dir{parser::Unwrap<parser::CompilerDirective>(stmt)}) {
       context_.Say(dir->source,
@@ -495,7 +493,6 @@ void OmpStructureChecker::SetLoopInfo(const parser::OpenMPLoopConstruct &x) {
 
 void OmpStructureChecker::CheckIterationVariableType(
     const parser::OpenMPLoopConstruct &x) {
-  using LoopRange = parser::omp::LoopRange;
   auto &body{std::get<parser::Block>(x.t)};
   for (auto &construct : LoopRange(body, LoopRange::Step::Into)) {
     // 'construct' can also be OpenMPLoopConstruct

>From 77235406105e7e686f1ca19bbfb4956aeef9257e Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 18 Feb 2026 10:53:13 -0600
Subject: [PATCH 2/3] [flang][OpenMP] Remember original range in
 ExecutionPartIterator

Storing the original range (instead of just the "remaining part")
will allow the iterator component to be reused.
---
 flang/include/flang/Parser/openmp-utils.h | 25 ++++++++++++++++++-----
 flang/lib/Parser/openmp-utils.cpp         | 11 ++++------
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index f23e52585d567..20754ad28d26d 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -296,14 +296,28 @@ struct ExecutionPartIterator {
   using IteratorType = Block::const_iterator;
   using IteratorRange = llvm::iterator_range<IteratorType>;
 
+  // An iterator range with a third iterator indicating a position inside
+  // the range.
+  struct IteratorGauge : public IteratorRange {
+    IteratorGauge(IteratorType b, IteratorType e)
+        : IteratorRange(b, e), at(b) {}
+    IteratorGauge(IteratorRange r) : IteratorRange(r), at(r.begin()) {}
+
+    bool atEnd() const { return at == end(); }
+    IteratorType at;
+  };
+
   struct Construct {
     Construct(IteratorType b, IteratorType e, const ExecutionPartConstruct *c)
-        : range(b, e), owner(c) {}
+        : location(b, e), owner(c) {}
     template <typename R>
     Construct(const R &r, const ExecutionPartConstruct *c)
-        : range(r), owner(c) {}
+        : location(r), owner(c) {}
     Construct(const Construct &c) = default;
-    IteratorRange range;
+    // The original range of the construct with the current position in it.
+    // The location.at is the construct currently being pointed at, or
+    // stepped into.
+    IteratorGauge location;
     const ExecutionPartConstruct *owner;
   };
 
@@ -332,6 +346,7 @@ struct ExecutionPartIterator {
 
   bool valid() const { return !stack_.empty(); }
 
+  const std::vector<Construct> &stack() const { return stack_; }
   decltype(auto) operator*() const { return *at(); }
   bool operator==(const ExecutionPartIterator &other) const {
     if (valid() != other.valid()) {
@@ -339,7 +354,7 @@ struct ExecutionPartIterator {
     }
     // Invalid iterators are considered equal.
     return !valid() ||
-        stack_.back().range.begin() == other.stack_.back().range.begin();
+        stack_.back().location.at == other.stack_.back().location.at;
   }
   bool operator!=(const ExecutionPartIterator &other) const {
     return !(*this == other);
@@ -368,7 +383,7 @@ struct ExecutionPartIterator {
   using iterator_category = std::forward_iterator_tag;
 
 private:
-  IteratorType at() const { return stack_.back().range.begin(); };
+  IteratorType at() const { return stack_.back().location.at; };
 
   // If the iterator is not at a legal location, keep advancing it until
   // it lands at a legal location or becomes invalid.
diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index 6d4326af78344..f83a658104396 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -243,8 +243,7 @@ void ExecutionPartIterator::step() {
     } else if (auto *loop{GetDoConstruct(*where)}) {
       stack_.emplace_back(std::get<Block>(loop->t), &*where);
     } else {
-      stack_.back().range =
-          IteratorRange(std::next(where), stack_.back().range.end());
+      ++stack_.back().location.at;
     }
     adjust();
   }
@@ -254,8 +253,7 @@ void ExecutionPartIterator::next() {
   // Advance the iterator to the next legal position. If the current
   // position is a DO-loop or a loop construct, step over it.
   if (valid()) {
-    stack_.back().range =
-        IteratorRange(std::next(at()), stack_.back().range.end());
+    ++stack_.back().location.at;
     adjust();
   }
 }
@@ -264,11 +262,10 @@ void ExecutionPartIterator::adjust() {
   // If the iterator is not at a legal location, keep advancing it until
   // it lands at a legal location or becomes invalid.
   while (valid()) {
-    if (stack_.back().range.empty()) {
+    if (stack_.back().location.atEnd()) {
       stack_.pop_back();
       if (valid()) {
-        stack_.back().range =
-            IteratorRange(std::next(at()), stack_.back().range.end());
+        ++stack_.back().location.at;
       }
     } else if (auto *block{GetFortranBlockConstruct(*at())}) {
       stack_.emplace_back(std::get<Block>(block->t), &*at());

>From dfa96281667b3523448d1fc3afacf798d6283438 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 26 Feb 2026 11:28:32 -0600
Subject: [PATCH 3/3] [flang][OpenMP] Move two functions to openmp-utils.cpp,
 NFC

Move `IsLoopTransforming` and `IsFullUnroll` from check-omp-loop.cpp
to openmp-utils.cpp.
---
 flang/include/flang/Semantics/openmp-utils.h |  3 ++
 flang/lib/Semantics/check-omp-loop.cpp       | 29 --------------------
 flang/lib/Semantics/openmp-utils.cpp         | 27 ++++++++++++++++++
 3 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 221e4cb23eada..a10d826e4050c 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -114,6 +114,9 @@ bool IsAssignment(const parser::ActionStmt *x);
 bool IsPointerAssignment(const evaluate::Assignment &x);
 
 MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp);
+
+bool IsLoopTransforming(llvm::omp::Directive dir);
+bool IsFullUnroll(const parser::OpenMPLoopConstruct &x);
 } // namespace omp
 } // namespace Fortran::semantics
 
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index e13ea820c7ef6..d6e5a3f0aa7fb 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -38,8 +38,6 @@
 #include <variant>
 
 namespace Fortran::semantics {
-static bool IsLoopTransforming(llvm::omp::Directive dir);
-static bool IsFullUnroll(const parser::OpenMPLoopConstruct &x);
 static std::optional<size_t> CountGeneratedNests(
     const parser::ExecutionPartConstruct &epc);
 static std::optional<size_t> CountGeneratedNests(const parser::Block &block);
@@ -248,33 +246,6 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
   }
 }
 
-static bool IsLoopTransforming(llvm::omp::Directive dir) {
-  switch (dir) {
-  // TODO case llvm::omp::Directive::OMPD_flatten:
-  case llvm::omp::Directive::OMPD_fuse:
-  case llvm::omp::Directive::OMPD_interchange:
-  case llvm::omp::Directive::OMPD_nothing:
-  case llvm::omp::Directive::OMPD_reverse:
-  // TODO case llvm::omp::Directive::OMPD_split:
-  case llvm::omp::Directive::OMPD_stripe:
-  case llvm::omp::Directive::OMPD_tile:
-  case llvm::omp::Directive::OMPD_unroll:
-    return true;
-  default:
-    return false;
-  }
-}
-
-static bool IsFullUnroll(const parser::OpenMPLoopConstruct &x) {
-  const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
-
-  if (beginSpec.DirName().v == llvm::omp::Directive::OMPD_unroll) {
-    return parser::omp::FindClause(
-               beginSpec, llvm::omp::Clause::OMPC_partial) == nullptr;
-  }
-  return false;
-}
-
 // Count the number of loop nests generated by `epc`. This is just a helper
 // function for counting the number of loop nests in a parser::Block.
 static std::optional<size_t> CountGeneratedNests(
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 937938a0d10ce..dbc7e216c4788 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -523,4 +523,31 @@ MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp) {
       },
       instance.u);
 }
+
+bool IsLoopTransforming(llvm::omp::Directive dir) {
+  switch (dir) {
+  // TODO case llvm::omp::Directive::OMPD_flatten:
+  case llvm::omp::Directive::OMPD_fuse:
+  case llvm::omp::Directive::OMPD_interchange:
+  case llvm::omp::Directive::OMPD_nothing:
+  case llvm::omp::Directive::OMPD_reverse:
+  // TODO case llvm::omp::Directive::OMPD_split:
+  case llvm::omp::Directive::OMPD_stripe:
+  case llvm::omp::Directive::OMPD_tile:
+  case llvm::omp::Directive::OMPD_unroll:
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool IsFullUnroll(const parser::OpenMPLoopConstruct &x) {
+  const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
+
+  if (beginSpec.DirName().v == llvm::omp::Directive::OMPD_unroll) {
+    return parser::omp::FindClause(
+               beginSpec, llvm::omp::Clause::OMPC_partial) == nullptr;
+  }
+  return false;
+}
 } // namespace Fortran::semantics::omp



More information about the flang-commits mailing list