[flang-commits] [flang] [Flang][OpenMP] Add Semantics support for Nested OpenMPLoopConstructs (PR #145917)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Thu Jun 26 09:17:36 PDT 2025
================
@@ -135,31 +142,74 @@ class CanonicalizationOfOmp {
if (auto *doCons{GetConstructIf<parser::DoConstruct>(*nextIt)}) {
if (doCons->GetLoopControl()) {
// move DoConstruct
- std::get<std::optional<parser::DoConstruct>>(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
- if (nextIt != block.end()) {
+ if (auto *endDir{
+ GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) {
+ std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) =
+ std::move(*endDir);
+ nextIt = block.erase(nextIt);
+ }
+ } else {
+ messages_.Say(dir.source,
+ "DO loop after the %s directive must have loop control"_err_en_US,
+ parser::ToUpperCaseLetters(dir.source.ToString()));
+ }
+ } 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
+ auto &beginDirective =
+ std::get<parser::OmpBeginLoopDirective>(ompLoopCons->t);
+ auto &beginLoopDirective =
+ std::get<parser::OmpLoopDirective>(beginDirective.t);
+ if ((beginLoopDirective.v == llvm::omp::Directive::OMPD_unroll ||
+ beginLoopDirective.v == llvm::omp::Directive::OMPD_tile)) {
+ // 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()) {
if (auto *endDir{
- GetConstructIf<parser::OmpEndLoopDirective>(*nextIt)}) {
- std::get<std::optional<parser::OmpEndLoopDirective>>(x.t) =
- std::move(*endDir);
- block.erase(nextIt);
+ 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;
}
+ 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)}}};
+ nextIt = block.erase(nextIt);
} else {
messages_.Say(dir.source,
- "DO loop after the %s directive must have loop control"_err_en_US,
+ "Only OpenMP Loop Transformation Constructs can be nested within OpenMPLoopConstruct's"_err_en_US,
----------------
tblah wrote:
I don't think this would be a clear compiler error for end users. Maybe "only loop transformation constructs or loop nests can be nested within loop constructs"
https://github.com/llvm/llvm-project/pull/145917
More information about the flang-commits
mailing list