[flang-commits] [flang] [flang][OpenMP] Move leftover functions from structure to loop, NFC (PR #228705)
via flang-commits
flang-commits at lists.llvm.org
Sat Oct 3 05:47:18 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
There were some loop-related functions still left in the check-omp-structure.cpp file. Move them to check-omp-loop.cpp.
---
Full diff: https://github.com/llvm/llvm-project/pull/228705.diff
3 Files Affected:
- (modified) flang/lib/Semantics/check-omp-loop.cpp (+142)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (-142)
- (modified) flang/lib/Semantics/check-omp-structure.h (+2-2)
``````````diff
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index d2466cdf219cb..7797c19db0f18 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -741,10 +741,105 @@ void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) {
}
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Collapse &x) {
+ RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_collapse, x.v);
+}
+
void OmpStructureChecker::Enter(const parser::OmpClause::Depth &x) {
RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_depth, x.v);
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Doacross &x) {
+ CheckDoacross(x.v.v, llvm::omp::Clause::OMPC_doacross);
+}
+
+void OmpStructureChecker::CheckDoacross(
+ const parser::OmpDoacross &doa, llvm::omp::Clause clauseId) {
+ auto &iterVec{std::get<std::optional<parser::OmpIterationVector>>(doa.t)};
+
+ auto &modifiers{OmpGetModifiers(doa)};
+ auto &depType{*OmpGetUniqueModifier<parser::OmpDependenceType>(modifiers)};
+ if (depType.v == parser::OmpDependenceType::Value::Source) {
+ if (iterVec) {
+ context_.Say(OmpGetModifierSource(modifiers, &depType),
+ "Iteration vector may not be specified with SOURCE dependence type"_err_en_US);
+ }
+ return;
+ }
+ assert(depType.v == parser::OmpDependenceType::Value::Sink &&
+ "Unexpected dependence-type");
+ if (!iterVec) {
+ context_.Say(OmpGetModifierSource(modifiers, &depType),
+ "Iteration vector must be specified with SINK dependence type"_err_en_US);
+ return;
+ }
+
+ // Process SINK dependence type. SINK may only appear in an ORDER construct,
+ // which references a prior ORDERED(n) clause on a DO or SIMD construct
+ // that marks the top of the loop nest.
+
+ const std::list<parser::OmpIteration> &vec{iterVec->v};
+
+ // Check if the variables in the iteration vector are unique.
+ struct Less {
+ using Iterator = std::list<parser::OmpIteration>::const_iterator;
+ bool operator()(Iterator a, Iterator b) const {
+ auto namea{std::get<parser::Name>(a->t)};
+ auto nameb{std::get<parser::Name>(b->t)};
+ assert(namea.symbol && nameb.symbol && "Unresolved symbols");
+ // The non-determinism of the "<" doesn't matter, we only care about
+ // equality, i.e. a == b <=> !(a < b) && !(b < a)
+ return reinterpret_cast<uintptr_t>(namea.symbol) <
+ reinterpret_cast<uintptr_t>(nameb.symbol);
+ }
+ };
+ if (auto maybeIter{FindDuplicate<Less>(vec)}) {
+ auto name{std::get<parser::Name>((*maybeIter)->t)};
+ context_.Say(name.source,
+ "Duplicate variable '%s' in the iteration vector"_err_en_US,
+ name.ToString());
+ }
+
+ // Check if the variables in the iteration vector are induction variables.
+ // Ignore any mismatch between the size of the iteration vector and the
+ // number of DO constructs on the stack. This is checked elsewhere.
+
+ std::set<const Symbol *> inductionVars;
+ for (const LoopOrConstruct &c : llvm::reverse(constructStack_)) {
+ if (auto *doc{std::get_if<const parser::DoConstruct *>(&c)}) {
+ // Do-construct, collect the induction variable.
+ if (auto &control{(*doc)->GetLoopControl()}) {
+ if (auto *b{std::get_if<parser::LoopControl::Bounds>(&control->u)}) {
+ inductionVars.insert(b->Name().thing.symbol);
+ }
+ }
+ } else {
+ // Omp-loop-construct, check if it's do/simd with an ORDERED clause.
+ auto *omp{std::get_if<const parser::OpenMPConstruct *>(&c)};
+ assert(omp && "Expecting OpenMPConstruct");
+ if (auto *loop{parser::Unwrap<parser::OpenMPLoopConstruct>(*omp)}) {
+ const parser::OmpDirectiveSpecification &beginSpec{loop->BeginDir()};
+ llvm::omp::Directive loopDir{beginSpec.DirId()};
+ if (loopDir == llvm::omp::OMPD_do || loopDir == llvm::omp::OMPD_simd) {
+ // If it has ORDERED clause, stop the traversal.
+ if (parser::omp::FindClause(
+ beginSpec, llvm::omp::Clause::OMPC_ordered)) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ for (const parser::OmpIteration &iter : vec) {
+ auto &name{std::get<parser::Name>(iter.t)};
+ if (!inductionVars.count(name.symbol)) {
+ context_.Say(name.source,
+ "The iteration vector element '%s' is not an induction variable within the ORDERED loop nest"_err_en_US,
+ name.ToString());
+ }
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
parser::CharBlock source{GetContext().clauseSource};
@@ -888,6 +983,53 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
}
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Safelen &x) {
+ RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_safelen, x.v);
+}
+
+void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
+ const parser::OmpScheduleClause &scheduleClause = x.v;
+
+ // 2.7 Loop Construct Restriction
+ if (llvm::omp::allDoSet.test(GetContext().directive)) {
+ auto &modifiers{OmpGetModifiers(scheduleClause)};
+ auto kind{std::get<parser::OmpScheduleClause::Kind>(scheduleClause.t)};
+ auto &chunk{
+ std::get<std::optional<parser::ScalarIntExpr>>(scheduleClause.t)};
+ if (chunk) {
+ if (kind == parser::OmpScheduleClause::Kind::Runtime ||
+ kind == parser::OmpScheduleClause::Kind::Auto) {
+ context_.Say(GetContext().clauseSource,
+ "When SCHEDULE clause has %s specified, "
+ "it must not have chunk size specified"_err_en_US,
+ parser::ToUpperCaseLetters(
+ parser::OmpScheduleClause::EnumToString(kind)));
+ }
+ if (const auto &chunkExpr{std::get<std::optional<parser::ScalarIntExpr>>(
+ scheduleClause.t)}) {
+ RequiresPositiveParameter(
+ llvm::omp::Clause::OMPC_schedule, *chunkExpr, "chunk size");
+ }
+ }
+
+ auto *ordering{
+ OmpGetUniqueModifier<parser::OmpOrderingModifier>(modifiers)};
+ if (ordering &&
+ ordering->v == parser::OmpOrderingModifier::Value::Nonmonotonic) {
+ if (kind != parser::OmpScheduleClause::Kind::Dynamic &&
+ kind != parser::OmpScheduleClause::Kind::Guided) {
+ context_.Say(GetContext().clauseSource,
+ "The NONMONOTONIC modifier can only be specified with "
+ "SCHEDULE(DYNAMIC) or SCHEDULE(GUIDED)"_err_en_US);
+ }
+ }
+ }
+}
+
+void OmpStructureChecker::Enter(const parser::OmpClause::Simdlen &x) {
+ RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_simdlen, x.v);
+}
+
void OmpStructureChecker::Enter(const parser::OmpClause::Sizes &c) {
for (const parser::Cosubscript &v : c.v)
RequiresPositiveParameter(llvm::omp::Clause::OMPC_sizes, v,
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 3880128545f5e..bef046d79df6c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -5116,45 +5116,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
- const parser::OmpScheduleClause &scheduleClause = x.v;
-
- // 2.7 Loop Construct Restriction
- if (llvm::omp::allDoSet.test(GetContext().directive)) {
- auto &modifiers{OmpGetModifiers(scheduleClause)};
- auto kind{std::get<parser::OmpScheduleClause::Kind>(scheduleClause.t)};
- auto &chunk{
- std::get<std::optional<parser::ScalarIntExpr>>(scheduleClause.t)};
- if (chunk) {
- if (kind == parser::OmpScheduleClause::Kind::Runtime ||
- kind == parser::OmpScheduleClause::Kind::Auto) {
- context_.Say(GetContext().clauseSource,
- "When SCHEDULE clause has %s specified, "
- "it must not have chunk size specified"_err_en_US,
- parser::ToUpperCaseLetters(
- parser::OmpScheduleClause::EnumToString(kind)));
- }
- if (const auto &chunkExpr{std::get<std::optional<parser::ScalarIntExpr>>(
- scheduleClause.t)}) {
- RequiresPositiveParameter(
- llvm::omp::Clause::OMPC_schedule, *chunkExpr, "chunk size");
- }
- }
-
- auto *ordering{
- OmpGetUniqueModifier<parser::OmpOrderingModifier>(modifiers)};
- if (ordering &&
- ordering->v == parser::OmpOrderingModifier::Value::Nonmonotonic) {
- if (kind != parser::OmpScheduleClause::Kind::Dynamic &&
- kind != parser::OmpScheduleClause::Kind::Guided) {
- context_.Say(GetContext().clauseSource,
- "The NONMONOTONIC modifier can only be specified with "
- "SCHEDULE(DYNAMIC) or SCHEDULE(GUIDED)"_err_en_US);
- }
- }
- }
-}
-
void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
const parser::OmpDeviceClause &deviceClause{x.v};
const auto &device{std::get<parser::ScalarIntExpr>(deviceClause.t)};
@@ -5281,97 +5242,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpClause::Doacross &x) {
- CheckDoacross(x.v.v, llvm::omp::Clause::OMPC_doacross);
-}
-
-void OmpStructureChecker::CheckDoacross(
- const parser::OmpDoacross &doa, llvm::omp::Clause clauseId) {
- auto &iterVec{std::get<std::optional<parser::OmpIterationVector>>(doa.t)};
-
- auto &modifiers{OmpGetModifiers(doa)};
- auto &depType{*OmpGetUniqueModifier<parser::OmpDependenceType>(modifiers)};
- if (depType.v == parser::OmpDependenceType::Value::Source) {
- if (iterVec) {
- context_.Say(OmpGetModifierSource(modifiers, &depType),
- "Iteration vector may not be specified with SOURCE dependence type"_err_en_US);
- }
- return;
- }
- assert(depType.v == parser::OmpDependenceType::Value::Sink &&
- "Unexpected dependence-type");
- if (!iterVec) {
- context_.Say(OmpGetModifierSource(modifiers, &depType),
- "Iteration vector must be specified with SINK dependence type"_err_en_US);
- return;
- }
-
- // Process SINK dependence type. SINK may only appear in an ORDER construct,
- // which references a prior ORDERED(n) clause on a DO or SIMD construct
- // that marks the top of the loop nest.
-
- const std::list<parser::OmpIteration> &vec{iterVec->v};
-
- // Check if the variables in the iteration vector are unique.
- struct Less {
- using Iterator = std::list<parser::OmpIteration>::const_iterator;
- bool operator()(Iterator a, Iterator b) const {
- auto namea{std::get<parser::Name>(a->t)};
- auto nameb{std::get<parser::Name>(b->t)};
- assert(namea.symbol && nameb.symbol && "Unresolved symbols");
- // The non-determinism of the "<" doesn't matter, we only care about
- // equality, i.e. a == b <=> !(a < b) && !(b < a)
- return reinterpret_cast<uintptr_t>(namea.symbol) <
- reinterpret_cast<uintptr_t>(nameb.symbol);
- }
- };
- if (auto maybeIter{FindDuplicate<Less>(vec)}) {
- auto name{std::get<parser::Name>((*maybeIter)->t)};
- context_.Say(name.source,
- "Duplicate variable '%s' in the iteration vector"_err_en_US,
- name.ToString());
- }
-
- // Check if the variables in the iteration vector are induction variables.
- // Ignore any mismatch between the size of the iteration vector and the
- // number of DO constructs on the stack. This is checked elsewhere.
-
- std::set<const Symbol *> inductionVars;
- for (const LoopOrConstruct &c : llvm::reverse(constructStack_)) {
- if (auto *doc{std::get_if<const parser::DoConstruct *>(&c)}) {
- // Do-construct, collect the induction variable.
- if (auto &control{(*doc)->GetLoopControl()}) {
- if (auto *b{std::get_if<parser::LoopControl::Bounds>(&control->u)}) {
- inductionVars.insert(b->Name().thing.symbol);
- }
- }
- } else {
- // Omp-loop-construct, check if it's do/simd with an ORDERED clause.
- auto *omp{std::get_if<const parser::OpenMPConstruct *>(&c)};
- assert(omp && "Expecting OpenMPConstruct");
- if (auto *loop{parser::Unwrap<parser::OpenMPLoopConstruct>(*omp)}) {
- const parser::OmpDirectiveSpecification &beginSpec{loop->BeginDir()};
- llvm::omp::Directive loopDir{beginSpec.DirId()};
- if (loopDir == llvm::omp::OMPD_do || loopDir == llvm::omp::OMPD_simd) {
- // If it has ORDERED clause, stop the traversal.
- if (parser::omp::FindClause(
- beginSpec, llvm::omp::Clause::OMPC_ordered)) {
- break;
- }
- }
- }
- }
- }
- for (const parser::OmpIteration &iter : vec) {
- auto &name{std::get<parser::Name>(iter.t)};
- if (!inductionVars.count(name.symbol)) {
- context_.Say(name.source,
- "The iteration vector element '%s' is not an induction variable within the ORDERED loop nest"_err_en_US,
- name.ToString());
- }
- }
-}
-
void OmpStructureChecker::CheckCopyingPolymorphicAllocatable(
SymbolSourceMap &symbols, const llvm::omp::Clause clause) {
llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
@@ -6830,18 +6700,6 @@ void OmpStructureChecker::Leave(const parser::OpenMPInvalidDirective &x) {
dirContext_.pop_back();
}
-void OmpStructureChecker::Enter(const parser::OmpClause::Collapse &x) {
- RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_collapse, x.v);
-}
-
-void OmpStructureChecker::Enter(const parser::OmpClause::Safelen &x) {
- RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_safelen, x.v);
-}
-
-void OmpStructureChecker::Enter(const parser::OmpClause::Simdlen &x) {
- RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_simdlen, x.v);
-}
-
void OmpStructureChecker::Enter(const parser::OmpClause::OmpxDynCgroupMem &x) {
RequiresPositiveParameter(llvm::omp::Clause::OMPC_ompx_dyn_cgroup_mem, x.v);
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index a77506e329934..c04336694f423 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -318,6 +318,8 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);
void CheckAssociatedLoopConstraints(const parser::OpenMPLoopConstruct &x);
void CheckScanModifier(const parser::OmpClause::Reduction &x);
+ void CheckDoacross(
+ const parser::OmpDoacross &doa, llvm::omp::Clause clauseId);
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
void CheckUnrollFullTripCount(const parser::OpenMPLoopConstruct &x);
@@ -430,8 +432,6 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
std::optional<IterTy> FindDuplicate(RangeTy &&);
void CheckDependList(const parser::DataRef &);
- void CheckDoacross(
- const parser::OmpDoacross &doa, llvm::omp::Clause clauseId);
void CheckDimsModifier(parser::CharBlock source, size_t numValues,
const parser::OmpDimsModifier &x);
void CheckTypeParamInquiry(const parser::CharBlock &source,
``````````
</details>
https://github.com/llvm/llvm-project/pull/228705
More information about the flang-commits
mailing list