[flang-commits] [flang] [flang][OpenMP] Inline CheckNestedBlock, NFC (PR #181732)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Wed Feb 25 11:47:10 PST 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/181732
>From dd6747b915b3818434fa0290324e230e90086ad8 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 12 Feb 2026 10:09:43 -0600
Subject: [PATCH 1/4] [flang][OpenMP] Include check for fully unrolled loops
into nest check, 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.
---
flang/lib/Semantics/check-omp-loop.cpp | 39 +++++++++--------------
flang/lib/Semantics/check-omp-structure.h | 1 -
2 files changed, 15 insertions(+), 25 deletions(-)
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);
>From 26520a92547e2aea23fee27bd8b4bc444188985f Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 13 Feb 2026 08:34:10 -0600
Subject: [PATCH 2/4] [flang][OpenMP] Inline CheckNestedBlock, NFC
CheckNestedBlock no longer calls itself, which was the primary reason
for the code to be in a separate function.
---
flang/lib/Semantics/check-omp-loop.cpp | 46 ++++++++++-------------
flang/lib/Semantics/check-omp-structure.h | 2 -
2 files changed, 20 insertions(+), 28 deletions(-)
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 8a74f8b98686b..c46f2562bbf49 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -281,30 +281,6 @@ static bool IsFullUnroll(const parser::OpenMPLoopConstruct &x) {
return false;
}
-void OmpStructureChecker::CheckNestedBlock(
- const parser::OpenMPLoopConstruct &x, const parser::Block &body) {
- 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,
- "Compiler directives are not allowed inside OpenMP loop constructs"_warn_en_US);
- } else if (auto *omp{parser::Unwrap<parser::OpenMPLoopConstruct>(stmt)}) {
- if (!IsLoopTransforming(omp->BeginDir().DirId())) {
- 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,
- "OpenMP loop construct can only contain DO loops or loop-nest-generating OpenMP constructs"_err_en_US);
- }
- }
-}
-
static std::optional<size_t> CountGeneratedNests(
const parser::ExecutionPartConstruct &epc) {
if (parser::Unwrap<parser::DoConstruct>(epc)) {
@@ -386,9 +362,27 @@ void OmpStructureChecker::CheckNestedConstruct(
}
}
+ // Check constructs contained in the body of the loop construct.
auto &body{std::get<parser::Block>(x.t)};
-
- CheckNestedBlock(x, body);
+ for (auto &stmt : BlockRange(body, BlockRange::Step::Over)) {
+ if (auto *dir{parser::Unwrap<parser::CompilerDirective>(stmt)}) {
+ context_.Say(dir->source,
+ "Compiler directives are not allowed inside OpenMP loop constructs"_warn_en_US);
+ } else if (auto *omp{parser::Unwrap<parser::OpenMPLoopConstruct>(stmt)}) {
+ if (!IsLoopTransforming(*omp)) {
+ 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,
+ "OpenMP loop construct can only contain DO loops or loop-nest-generating OpenMP constructs"_err_en_US);
+ }
+ }
// Check if a loop-nest-associated construct has only one top-level loop
// in it.
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 21460ab0fbe08..2b3407964aa2b 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -327,8 +327,6 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void CheckLooprangeBounds(const parser::OpenMPLoopConstruct &x);
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
void CheckSIMDNest(const parser::OpenMPConstruct &x);
- void CheckNestedBlock(
- const parser::OpenMPLoopConstruct &x, const parser::Block &body);
void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x);
void CheckTargetNest(const parser::OpenMPConstruct &x);
void CheckTargetUpdate();
>From 55642914c3cdd01802362086080ac20f24ebfd8a Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 16 Feb 2026 13:44:59 -0600
Subject: [PATCH 3/4] Add using BlockRange
---
flang/lib/Semantics/check-omp-loop.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index c46f2562bbf49..c5d91ebac5e01 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -364,6 +364,7 @@ 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,
>From 76a15e6b0547adb77d1caa8e392f4fe753192dcc Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 25 Feb 2026 13:46:58 -0600
Subject: [PATCH 4/4] Update check-omp-loop.cpp
---
flang/lib/Semantics/check-omp-loop.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index c5d91ebac5e01..038c265a281b7 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -370,7 +370,7 @@ void OmpStructureChecker::CheckNestedConstruct(
context_.Say(dir->source,
"Compiler directives are not allowed inside OpenMP loop constructs"_warn_en_US);
} else if (auto *omp{parser::Unwrap<parser::OpenMPLoopConstruct>(stmt)}) {
- if (!IsLoopTransforming(*omp)) {
+ if (!IsLoopTransforming(omp->BeginDir().DirId())) {
context_.Say(omp->source,
"Only loop-transforming OpenMP constructs are allowed inside OpenMP loop constructs"_err_en_US);
}
More information about the flang-commits
mailing list