[flang-commits] [flang] [Flang][OpenMP] Add Semantics support for Nested OpenMPLoopConstructs (PR #145917)

via flang-commits flang-commits at lists.llvm.org
Thu Jun 26 08:31:16 PDT 2025


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {clang-format}-->


:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff HEAD~1 HEAD --extensions h,cpp -- flang/include/flang/Parser/parse-tree.h flang/lib/Lower/OpenMP/OpenMP.cpp flang/lib/Parser/unparse.cpp flang/lib/Semantics/canonicalize-omp.cpp flang/lib/Semantics/check-omp-structure.cpp flang/lib/Semantics/resolve-directives.cpp
``````````

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 7aa925023..8d8735424 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -5025,7 +5025,9 @@ struct OpenMPLoopConstruct {
   TUPLE_CLASS_BOILERPLATE(OpenMPLoopConstruct);
   OpenMPLoopConstruct(OmpBeginLoopDirective &&a)
       : t({std::move(a), std::nullopt, std::nullopt}) {}
-  std::tuple<OmpBeginLoopDirective, std::optional<std::variant<DoConstruct, common::Indirection<OpenMPLoopConstruct>>>,
+  std::tuple<OmpBeginLoopDirective,
+      std::optional<
+          std::variant<DoConstruct, common::Indirection<OpenMPLoopConstruct>>>,
       std::optional<OmpEndLoopDirective>>
       t;
 };
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 3e6f0ff2e..c85d015b8 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -4232,8 +4232,10 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
       converter.genLocation(beginLoopDirective.source);
 
   auto &optLoopCons = std::get<1>(loopConstruct.t);
-  if(optLoopCons.has_value())
-    if(auto *ompNestedLoopCons{std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>(&*optLoopCons)}) {
+  if (optLoopCons.has_value())
+    if (auto *ompNestedLoopCons{
+            std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>(
+                &*optLoopCons)}) {
       genOMP(converter, symTable, semaCtx, eval, ompNestedLoopCons->value());
     }
 
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 276be878d..903287515 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2926,7 +2926,8 @@ public:
     Walk(std::get<OmpBeginLoopDirective>(x.t));
     Put("\n");
     EndOpenMP();
-    Walk(std::get<std::optional<std::variant<DoConstruct, common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t));
+    Walk(std::get<std::optional<std::variant<DoConstruct,
+            common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t));
     Walk(std::get<std::optional<OmpEndLoopDirective>>(x.t));
   }
   void Unparse(const BasedPointer &x) {
diff --git a/flang/lib/Semantics/canonicalize-omp.cpp b/flang/lib/Semantics/canonicalize-omp.cpp
index d68274351..68ba1c594 100644
--- a/flang/lib/Semantics/canonicalize-omp.cpp
+++ b/flang/lib/Semantics/canonicalize-omp.cpp
@@ -109,8 +109,8 @@ private:
 
   void missingDoConstruct(parser::OmpLoopDirective &dir) {
     messages_.Say(dir.source,
-      "A DO loop must follow the %s directive"_err_en_US,
-      parser::ToUpperCaseLetters(dir.source.ToString()));
+        "A DO loop must follow the %s directive"_err_en_US,
+        parser::ToUpperCaseLetters(dir.source.ToString()));
   }
 
   void RewriteOpenMPLoopConstruct(parser::OpenMPLoopConstruct &x,
@@ -142,7 +142,8 @@ private:
       if (auto *doCons{GetConstructIf<parser::DoConstruct>(*nextIt)}) {
         if (doCons->GetLoopControl()) {
           // move DoConstruct
-          std::get<std::optional<std::variant<parser::DoConstruct, common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t) =
+          std::get<std::optional<std::variant<parser::DoConstruct,
+              common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t) =
               std::move(*doCons);
           nextIt = block.erase(nextIt);
           // try to match OmpEndLoopDirective
@@ -159,34 +160,41 @@ private:
         }
       } else if (auto *ompLoopCons{
                      GetOmpIf<parser::OpenMPLoopConstruct>(*nextIt)}) {
-        // We should allow UNROLL and TILE constructs to be inserted between an OpenMP Loop Construct and the DO loop itself
+        // We should allow UNROLL and TILE constructs to be inserted between an
+        // OpenMP Loop Construct and the DO loop itself
         auto &beginDirective =
             std::get<parser::OmpBeginLoopDirective>(ompLoopCons->t);
         auto &beginLoopDirective =
-        std::get<parser::OmpLoopDirective>(beginDirective.t);
-        // iterate through the remaining block items to find the end directive for the unroll/tile directive.
+            std::get<parser::OmpLoopDirective>(beginDirective.t);
+        // iterate through the remaining block items to find the end directive
+        // for the unroll/tile directive.
         parser::Block::iterator endIt;
         endIt = nextIt;
-        while(endIt != block.end()) {
+        while (endIt != block.end()) {
           if (auto *endDir{
-            GetConstructIf<parser::OmpEndLoopDirective>(*endIt)}) {
-              auto &endLoopDirective = std::get<parser::OmpLoopDirective>(endDir->t);
-              if(endLoopDirective.v == dir.v) {
-                std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) =
-                std::move(*endDir);
-                endIt = block.erase(endIt);
-                continue;
-              }
+                  GetConstructIf<parser::OmpEndLoopDirective>(*endIt)}) {
+            auto &endLoopDirective =
+                std::get<parser::OmpLoopDirective>(endDir->t);
+            if (endLoopDirective.v == dir.v) {
+              std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) =
+                  std::move(*endDir);
+              endIt = block.erase(endIt);
+              continue;
             }
-            ++endIt;
           }
+          ++endIt;
+        }
         if ((beginLoopDirective.v == llvm::omp::Directive::OMPD_unroll ||
-            beginLoopDirective.v == llvm::omp::Directive::OMPD_tile)) {
+                beginLoopDirective.v == llvm::omp::Directive::OMPD_tile)) {
           RewriteOpenMPLoopConstruct(*ompLoopCons, block, nextIt);
-          auto &ompLoop = std::get<std::optional<std::variant<parser::DoConstruct, common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t);
-          ompLoop = std::optional<std::variant<parser::DoConstruct, common::Indirection<parser::OpenMPLoopConstruct>>>{
-            std::variant<parser::DoConstruct, common::Indirection<parser::OpenMPLoopConstruct>>{
-            common::Indirection{std::move(*ompLoopCons)}}};
+          auto &ompLoop =
+              std::get<std::optional<std::variant<parser::DoConstruct,
+                  common::Indirection<parser::OpenMPLoopConstruct>>>>(x.t);
+          ompLoop = std::optional<std::variant<parser::DoConstruct,
+              common::Indirection<parser::OpenMPLoopConstruct>>>{
+              std::variant<parser::DoConstruct,
+                  common::Indirection<parser::OpenMPLoopConstruct>>{
+                  common::Indirection{std::move(*ompLoopCons)}}};
           nextIt = block.erase(nextIt);
         }
       } else {
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index b54cd30ec..81c1c3e76 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -763,7 +763,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
   SetLoopInfo(x);
 
   auto &optLoopCons = std::get<1>(x.t);
-  if(optLoopCons.has_value()) {
+  if (optLoopCons.has_value()) {
     if (const auto &doConstruct{
             std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
       const auto &doBlock{std::get<parser::Block>(doConstruct->t)};
@@ -785,7 +785,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
   if (beginDir.v == llvm::omp::Directive::OMPD_tile) {
     const auto &clauses{std::get<parser::OmpClauseList>(beginLoopDir.t)};
     for (auto &clause : clauses.v) {
-
     }
   }
 }
@@ -872,26 +871,26 @@ void OmpStructureChecker::CheckLoopItrVariableIsInt(
   auto &optLoopCons = std::get<1>(x.t);
   if (optLoopCons.has_value()) {
     if (const auto &loopConstruct{
-          std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
+            std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
 
-    for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) {
-      if (loop->IsDoNormal()) {
-        const parser::Name &itrVal{GetLoopIndex(loop)};
-        if (itrVal.symbol) {
-          const auto *type{itrVal.symbol->GetType()};
-          if (!type->IsNumeric(TypeCategory::Integer)) {
-            context_.Say(itrVal.source,
-                "The DO loop iteration"
-                " variable must be of the type integer."_err_en_US,
-                itrVal.ToString());
+      for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) {
+        if (loop->IsDoNormal()) {
+          const parser::Name &itrVal{GetLoopIndex(loop)};
+          if (itrVal.symbol) {
+            const auto *type{itrVal.symbol->GetType()};
+            if (!type->IsNumeric(TypeCategory::Integer)) {
+              context_.Say(itrVal.source,
+                  "The DO loop iteration"
+                  " variable must be of the type integer."_err_en_US,
+                  itrVal.ToString());
+            }
           }
         }
-      }
-      // Get the next DoConstruct if block is not empty.
-      const auto &block{std::get<parser::Block>(loop->t)};
-      const auto it{block.begin()};
-      loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
-                               : nullptr;
+        // Get the next DoConstruct if block is not empty.
+        const auto &block{std::get<parser::Block>(loop->t)};
+        const auto it{block.begin()};
+        loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
+                                 : nullptr;
       }
     }
   }
@@ -1094,25 +1093,25 @@ void OmpStructureChecker::CheckDistLinear(
     // clauses.
     auto &optLoopCons = std::get<1>(x.t);
     if (optLoopCons.has_value()) {
-    if (const auto &loopConstruct{
-            std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
-      for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) {
-        if (loop->IsDoNormal()) {
-          const parser::Name &itrVal{GetLoopIndex(loop)};
-          if (itrVal.symbol) {
-            // Remove the symbol from the collected set
-            indexVars.erase(&itrVal.symbol->GetUltimate());
-          }
-          collapseVal--;
-          if (collapseVal == 0) {
-            break;
+      if (const auto &loopConstruct{
+              std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
+        for (const parser::DoConstruct *loop{&*loopConstruct}; loop;) {
+          if (loop->IsDoNormal()) {
+            const parser::Name &itrVal{GetLoopIndex(loop)};
+            if (itrVal.symbol) {
+              // Remove the symbol from the collected set
+              indexVars.erase(&itrVal.symbol->GetUltimate());
+            }
+            collapseVal--;
+            if (collapseVal == 0) {
+              break;
+            }
           }
-        }
-        // Get the next DoConstruct if block is not empty.
-        const auto &block{std::get<parser::Block>(loop->t)};
-        const auto it{block.begin()};
-        loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
-                                 : nullptr;
+          // Get the next DoConstruct if block is not empty.
+          const auto &block{std::get<parser::Block>(loop->t)};
+          const auto it{block.begin()};
+          loop = it != block.end() ? parser::Unwrap<parser::DoConstruct>(*it)
+                                   : nullptr;
         }
       }
     }
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 36bea4fbe..9b8686022 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1968,10 +1968,11 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
   auto &optLoopCons = std::get<1>(x.t);
   if (optLoopCons.has_value()) {
     if (const auto &outer{std::get_if<parser::DoConstruct>(&*optLoopCons)}) {
-      for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) {
+      for (const parser::DoConstruct *loop{&*outer}; loop && level > 0;
+          --level) {
         if (loop->IsDoConcurrent()) {
-          // DO CONCURRENT is explicitly allowed for the LOOP construct so long as
-          // there isn't a COLLAPSE clause
+          // DO CONCURRENT is explicitly allowed for the LOOP construct so long
+          // as there isn't a COLLAPSE clause
           if (isLoopConstruct) {
             if (hasCollapseClause) {
               // hasCollapseClause implies clause != nullptr
@@ -2000,16 +2001,20 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
         }
       }
       CheckAssocLoopLevel(level, GetAssociatedClause());
-    } else if (const auto &loop{std::get_if<common::Indirection<parser::OpenMPLoopConstruct>>(&*optLoopCons)}) {
+    } else if (const auto &loop{std::get_if<
+                   common::Indirection<parser::OpenMPLoopConstruct>>(
+                   &*optLoopCons)}) {
       auto &beginDirective =
-            std::get<parser::OmpBeginLoopDirective>(loop->value().t);
+          std::get<parser::OmpBeginLoopDirective>(loop->value().t);
       auto &beginLoopDirective =
           std::get<parser::OmpLoopDirective>(beginDirective.t);
       if ((beginLoopDirective.v != llvm::omp::Directive::OMPD_unroll &&
-            beginLoopDirective.v != llvm::omp::Directive::OMPD_tile)) {
+              beginLoopDirective.v != llvm::omp::Directive::OMPD_tile)) {
         context_.Say(GetContext().directiveSource,
-          "Only UNROLL or TILE constructs are allowed between an OpenMP Loop Construct and a DO construct"_err_en_US,
-          parser::ToUpperCaseLetters(llvm::omp::getOpenMPDirectiveName(GetContext().directive, version).str()));
+            "Only UNROLL or TILE constructs are allowed between an OpenMP Loop Construct and a DO construct"_err_en_US,
+            parser::ToUpperCaseLetters(llvm::omp::getOpenMPDirectiveName(
+                GetContext().directive, version)
+                    .str()));
       } else {
         PrivatizeAssociatedLoopIndexAndCheckLoopLevel(loop->value());
       }

``````````

</details>


https://github.com/llvm/llvm-project/pull/145917


More information about the flang-commits mailing list