Skip to content

[flang][OpenMP] Include check for fully unrolled loops into nest chec…#181729

Open
kparzysz wants to merge 1 commit intomainfrom
users/kparzysz/l01-full-unroll
Open

[flang][OpenMP] Include check for fully unrolled loops into nest chec…#181729
kparzysz wants to merge 1 commit intomainfrom
users/kparzysz/l01-full-unroll

Conversation

@kparzysz
Copy link
Contributor

…k, NFC

It's naturally a part of the verification of constructs nested in loop constructs, so perform that check there instead of having it in a separate function.

…k, NFC

It's naturally a part of the verification of constructs nested in loop
constructs, so perform that check there instead of having it in a separate
function.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Feb 16, 2026
@llvmbot
Copy link
Member

llvmbot commented Feb 16, 2026

@llvm/pr-subscribers-flang-semantics

Author: Krzysztof Parzyszek (kparzysz)

Changes

…k, NFC

It's naturally a part of the verification of constructs nested in loop constructs, so perform that check there instead of having it in a separate function.


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

2 Files Affected:

  • (modified) flang/lib/Semantics/check-omp-loop.cpp (+15-24)
  • (modified) flang/lib/Semantics/check-omp-structure.h (-1)
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 02580e16a8bf4..8a74f8b98686b 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -270,6 +270,17 @@ static bool IsLoopTransforming(llvm::omp::Directive dir) {
   }
 }
 
+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 false;
+}
+
 void OmpStructureChecker::CheckNestedBlock(
     const parser::OpenMPLoopConstruct &x, const parser::Block &body) {
   using BlockRange = parser::omp::BlockRange;
@@ -282,6 +293,10 @@ void OmpStructureChecker::CheckNestedBlock(
         context_.Say(omp->source,
             "Only loop-transforming OpenMP constructs are allowed inside OpenMP loop constructs"_err_en_US);
       }
+      if (IsFullUnroll(*omp)) {
+        context_.Say(x.source,
+            "OpenMP loop construct cannot apply to a fully unrolled loop"_err_en_US);
+      }
     } else if (!parser::Unwrap<parser::DoConstruct>(stmt)) {
       parser::CharBlock source{parser::GetSource(stmt).value_or(x.source)};
       context_.Say(source,
@@ -290,17 +305,6 @@ void OmpStructureChecker::CheckNestedBlock(
   }
 }
 
-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 false;
-}
-
 static std::optional<size_t> CountGeneratedNests(
     const parser::ExecutionPartConstruct &epc) {
   if (parser::Unwrap<parser::DoConstruct>(epc)) {
@@ -403,18 +407,6 @@ void OmpStructureChecker::CheckNestedConstruct(
   }
 }
 
-void OmpStructureChecker::CheckFullUnroll(
-    const parser::OpenMPLoopConstruct &x) {
-  // If the nested construct is a full unroll, then this construct is invalid
-  // since it won't contain a loop.
-  if (const parser::OpenMPLoopConstruct *nested{x.GetNestedConstruct()}) {
-    if (IsFullUnroll(*nested)) {
-      context_.Say(x.source,
-          "OpenMP loop construct cannot apply to a fully unrolled loop"_err_en_US);
-    }
-  }
-}
-
 void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
   loopStack_.push_back(&x);
 
@@ -472,7 +464,6 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) {
   }
   CheckLoopItrVariableIsInt(x);
   CheckNestedConstruct(x);
-  CheckFullUnroll(x);
   CheckAssociatedLoopConstraints(x);
   HasInvalidDistributeNesting(x);
   HasInvalidLoopBinding(x);
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 9b5b0525dd27f..21460ab0fbe08 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -330,7 +330,6 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   void CheckNestedBlock(
       const parser::OpenMPLoopConstruct &x, const parser::Block &body);
   void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x);
-  void CheckFullUnroll(const parser::OpenMPLoopConstruct &x);
   void CheckTargetNest(const parser::OpenMPConstruct &x);
   void CheckTargetUpdate();
   void CheckTaskgraph(const parser::OmpBlockConstruct &x);

@kparzysz kparzysz requested review from Stylie777 and tblah February 16, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants