[llvm-branch-commits] [flang] [flang][OpenMP] Implement checks for rectangular loops (PR #190648)
Krzysztof Parzyszek via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Apr 6 11:59:32 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/190648
>From 33e555beae86d04cb4ee268a0a419bb3e52242f3 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 24 Mar 2026 12:11:40 -0500
Subject: [PATCH 1/2] [flang][OpenMP] Implement checks for rectangular loops
Detect non-rectangular loops, emit diagnostic messages when the construct
requires that the affected loops are rectangular. Delete similar checks
from resolve-directive.cpp.
Issue: https://github.com/llvm/llvm-project/issues/185287
---
flang/include/flang/Semantics/openmp-utils.h | 15 ++
flang/lib/Semantics/check-omp-loop.cpp | 31 +++
flang/lib/Semantics/check-omp-structure.h | 2 +
flang/lib/Semantics/openmp-utils.cpp | 191 +++++++++++++++++++
flang/lib/Semantics/resolve-directives.cpp | 84 --------
flang/test/Semantics/OpenMP/do22.f90 | 18 +-
flang/test/Semantics/OpenMP/tile06.f90 | 12 +-
7 files changed, 260 insertions(+), 93 deletions(-)
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index f6aebaf8ffdfc..487a0373b10f0 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -192,6 +192,8 @@ WithReason<int64_t> GetArgumentValueWithReason(
WithReason<int64_t> GetNumArgumentsWithReason(
const parser::OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId,
unsigned version);
+WithReason<int64_t> GetHeightWithReason(
+ const parser::OmpDirectiveSpecification &spec, unsigned version);
// Return the depth of the affected nests:
// {affected-depth, reason, must-be-perfect-nest}.
@@ -202,6 +204,9 @@ std::pair<WithReason<int64_t>, bool> GetAffectedNestDepthWithReason(
// If the range is "the whole sequence", the return value will be {1, -1, ...}.
WithReason<std::pair<int64_t, int64_t>> GetAffectedLoopRangeWithReason(
const parser::OmpDirectiveSpecification &spec, unsigned version);
+/// Return the depth in which all loops must be rectangular.
+WithReason<int64_t> GetRectangularNestDepthWithReason(
+ const parser::OmpDirectiveSpecification &spec, unsigned version);
// Count the required loop count from range. If count == -1, return -1,
// indicating all loops in the sequence.
@@ -233,8 +238,10 @@ struct LoopSequence {
bool isNest() const { return length_.value == 1; }
const WithReason<int64_t> &length() const { return length_; }
+ const WithReason<int64_t> &height() const { return height_; }
const Depth &depth() const { return depth_; }
const std::vector<LoopSequence> &children() const { return children_; }
+ const parser::ExecutionPartConstruct *owner() const { return entry_->owner; }
WithReason<bool> isWellFormedSequence() const;
WithReason<bool> isWellFormedNest() const;
@@ -270,6 +277,7 @@ struct LoopSequence {
WithReason<int64_t> getNestedLength() const;
Depth calculateDepths() const;
Depth getNestedDepths() const;
+ WithReason<int64_t> calculateHeight() const;
/// The construct that is not a loop or a loop-transforming construct,
/// that is also not a valid intervening code. Unset if no such code is
@@ -287,6 +295,13 @@ struct LoopSequence {
WithReason<int64_t> length_;
/// Precalculated depths. Only meaningful if the sequence is a nest.
Depth depth_;
+ /// Precalculated height of the sequence. The height is the difference
+ /// in the nesting level between "this" and any of the children (should
+ /// be the same for each child). Intuitively it is the number of nested
+ /// loops that are added by this construct. If this->depth_ included
+ /// child->depth_ for some child, then
+ /// height_ = this->depth_ - child->depth_
+ WithReason<int64_t> height_;
// The core structure of the class:
unsigned version_; // Needed for GetXyzWithReason
diff --git a/flang/lib/Semantics/check-omp-loop.cpp b/flang/lib/Semantics/check-omp-loop.cpp
index 48d0684320e1c..951751228f34b 100644
--- a/flang/lib/Semantics/check-omp-loop.cpp
+++ b/flang/lib/Semantics/check-omp-loop.cpp
@@ -232,6 +232,35 @@ void OmpStructureChecker::CheckSIMDNest(const parser::OpenMPConstruct &c) {
}
}
+void OmpStructureChecker::CheckRectangularNest(
+ const parser::OmpDirectiveSpecification &spec, const LoopSequence &nest) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ auto depth{GetRectangularNestDepthWithReason(spec, version)};
+ if (!depth || *depth.value == 0) {
+ return;
+ }
+
+ int64_t height{0};
+ std::vector<const LoopSequence *> outer;
+ for (const LoopSequence *n{&nest}; n;) {
+ if (n->owner()) {
+ WithReason<bool> rect{n->isRectangular(outer)};
+ if (!rect.value.value_or(true)) {
+ auto &msg{context_.Say(spec.DirName().source,
+ "This construct requires a rectangular loop nest, but the associated nest is not"_err_en_US)};
+ depth.reason.AttachTo(msg);
+ rect.reason.AttachTo(msg);
+ }
+ outer.push_back(n);
+ }
+ height += n->height().value.value_or(1);
+ if (height >= *depth.value) {
+ break;
+ }
+ n = n->children().empty() ? nullptr : &n->children().front();
+ }
+}
+
void OmpStructureChecker::CheckNestedConstruct(
const parser::OpenMPLoopConstruct &x) {
const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
@@ -311,6 +340,8 @@ void OmpStructureChecker::CheckNestedConstruct(
perfectTxt, *needDepth.value, perfectTxt, *haveDepth.value)};
haveDepth.reason.AttachTo(msg);
needDepth.reason.AttachTo(msg);
+ } else {
+ CheckRectangularNest(beginSpec, sequence);
}
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index a27b16561d3f7..7b4859e312c3f 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -332,6 +332,8 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
void CheckScanModifier(const parser::OmpClause::Reduction &x);
void CheckDistLinear(const parser::OpenMPLoopConstruct &x);
void CheckSIMDNest(const parser::OpenMPConstruct &x);
+ void CheckRectangularNest(const parser::OmpDirectiveSpecification &spec,
+ const omp::LoopSequence &nest);
void CheckNestedConstruct(const parser::OpenMPLoopConstruct &x);
void CheckTargetNest(const parser::OpenMPConstruct &x);
void CheckTargetUpdate();
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index bdde253580c26..18a10be3276a5 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -665,6 +665,24 @@ parser::Message &Reason::AttachTo(parser::Message &msg) {
return msg;
}
+/// From `vars` select the subsequence of symbols that are used in `expr`
+/// either directly, or via some kind of association.
+static SymbolVector SelectUsedSymbols(
+ const SymbolVector &vars, const SomeExpr &expr) {
+ std::set<const Symbol *> uses;
+ for (SymbolRef s : evaluate::GetSymbolVector(expr)) {
+ uses.insert(&s->GetUltimate());
+ }
+
+ SymbolVector deps;
+ for (SymbolRef s : vars) {
+ if (uses.count(&s->GetUltimate())) {
+ deps.push_back(s);
+ }
+ }
+ return deps;
+}
+
WithReason<int64_t> GetArgumentValueWithReason(
const parser::OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId,
unsigned version) {
@@ -719,6 +737,53 @@ WithReason<int64_t> GetNumArgumentsWithReason(
return {};
}
+WithReason<int64_t> GetHeightWithReason(
+ const parser::OmpDirectiveSpecification &spec, unsigned version) {
+ bool isFullUnroll{IsFullUnroll(spec)};
+
+ if (!isFullUnroll && !IsTransformableLoop(spec)) {
+ Reason reason;
+ reason.Say(spec.DirName().source,
+ "This construct is not a DO-loop or a loop-transformation construct"_because_en_US);
+ return {0, reason};
+ }
+ switch (spec.DirName().v) {
+ case llvm::omp::Directive::OMPD_flatten:
+ if (auto &&value{GetArgumentValueWithReason(
+ spec, llvm::omp::Clause::OMPC_depth, version)}) {
+ // FLATTEN DEPTH(n) replaces n loops with 1.
+ return {int64_t(1) - *value.value, std::move(value.reason)};
+ } else {
+ Reason reason;
+ reason.Say(spec.DirName().source, MsgClauseAbsentAssume,
+ GetUpperName(llvm::omp::Clause::OMPC_depth, version),
+ "a depth of 2");
+ return {-1, std::move(reason)};
+ }
+ case llvm::omp::Directive::OMPD_fuse:
+ case llvm::omp::Directive::OMPD_split:
+ return {0, Reason()};
+ case llvm::omp::Directive::OMPD_interchange:
+ case llvm::omp::Directive::OMPD_nothing:
+ case llvm::omp::Directive::OMPD_reverse:
+ return {0, Reason()};
+ case llvm::omp::Directive::OMPD_stripe:
+ case llvm::omp::Directive::OMPD_tile:
+ return GetNumArgumentsWithReason(
+ spec, llvm::omp::Clause::OMPC_sizes, version);
+ case llvm::omp::Directive::OMPD_unroll:
+ if (isFullUnroll) {
+ Reason reason;
+ reason.Say(spec.DirName().source, MsgConstructDoesNotResult,
+ "Fully unrolled loop", "a loop nest");
+ return {-1, std::move(reason)};
+ }
+ return {0, Reason()};
+ default:
+ llvm_unreachable("Expecting loop-transforming construct");
+ }
+}
+
namespace {
// Helper class to check if a given evaluate::Expr is an array expression.
// This does not check any proper subexpressions of the expression (except
@@ -1000,6 +1065,56 @@ WithReason<std::pair<int64_t, int64_t>> GetAffectedLoopRangeWithReason(
return {std::make_pair(1, 1), Reason()};
}
+WithReason<int64_t> GetRectangularNestDepthWithReason(
+ const parser::OmpDirectiveSpecification &spec, unsigned version) {
+ auto [depth, _]{GetAffectedNestDepthWithReason(spec, version)};
+ if (!depth) {
+ return {};
+ }
+
+ // Remove the reasons for the affected depth. Reasons for needing
+ // rectangular loops will be added instead.
+ depth.reason.msgs.clear();
+
+ static const std::array directives{
+ llvm::omp::Directive::OMPD_interchange,
+ llvm::omp::Directive::OMPD_stripe,
+ llvm::omp::Directive::OMPD_tile,
+ };
+
+ llvm::omp::Directive dirId{spec.DirId()};
+ if (llvm::is_contained(directives, dirId)) {
+ depth.reason.Say(spec.DirName().source,
+ "None of the loops affected by %s can be non-rectangular"_because_en_US,
+ GetUpperName(dirId, version));
+ return std::move(depth);
+ }
+
+ static const std::array clauses{
+ llvm::omp::Clause::OMPC_dist_schedule,
+ llvm::omp::Clause::OMPC_grainsize,
+ llvm::omp::Clause::OMPC_induction,
+ llvm::omp::Clause::OMPC_linear,
+ llvm::omp::Clause::OMPC_schedule,
+ };
+
+ auto clauseAt{
+ llvm::find_if(spec.Clauses().v, [&](const parser::OmpClause &c) {
+ llvm::omp::Clause clauseId{c.Id()};
+ return llvm::is_contained(clauses, clauseId) &&
+ llvm::omp::isAllowedClauseForDirective(dirId, clauseId, version);
+ })};
+ if (clauseAt != spec.Clauses().v.end()) {
+ depth.reason.Say(clauseAt->source,
+ "When %s clause is present, none of the loops affected by %s can be non-rectangular"_because_en_US,
+ GetUpperName(clauseAt->Id(), version), GetUpperName(dirId, version));
+ return std::move(depth);
+ }
+
+ // No restrictions.
+ return {0, Reason()};
+}
+
std::optional<int64_t> GetRequiredCount(
std::optional<int64_t> first, std::optional<int64_t> count) {
if (first && count && *first > 0) {
@@ -1154,6 +1269,7 @@ void LoopSequence::precalculate() {
// Calculate length before depths.
length_ = calculateLength();
depth_ = calculateDepths();
+ height_ = calculateHeight();
}
WithReason<int64_t> LoopSequence::calculateLength() const {
@@ -1405,6 +1521,23 @@ LoopSequence::Depth LoopSequence::getNestedDepths() const {
return children_.front().depth_;
}
+WithReason<int64_t> LoopSequence::calculateHeight() const {
+ if (!entry_->owner) {
+ return {0, Reason()};
+ }
+ if (parser::Unwrap<parser::DoConstruct>(*entry_->owner)) {
+ return {1, Reason()};
+ }
+ if (auto *omp{parser::Unwrap<parser::OpenMPLoopConstruct>(*entry_->owner)}) {
+ const parser::OmpDirectiveSpecification &beginSpec{omp->BeginDir()};
+ if (IsLoopTransforming(beginSpec.DirId())) {
+ return GetHeightWithReason(beginSpec, version_);
+ }
+ return {0, Reason()};
+ }
+ return {};
+}
+
static bool IsDoConcurrent(const parser::ExecutionPartConstruct &x) {
if (auto *loop{parser::Unwrap<parser::DoConstruct>(x)}) {
return loop->IsDoConcurrent();
@@ -1465,4 +1598,62 @@ WithReason<bool> LoopSequence::isWellFormedNest() const {
}
return {true, Reason()};
}
+
+static std::string JoinSymbolNames(const SymbolVector &syms) {
+ std::vector<std::string> names;
+ for (SymbolRef s : syms) {
+ names.push_back("'" + s->name().ToString() + "'");
+ }
+ return llvm::join(names, ", ");
+}
+
+static void CheckSymbolExprOverlap(WithReason<bool> &result,
+ const SymbolVector &syms, const SomeExpr &expr, std::string exprName,
+ parser::CharBlock exprSource) {
+ if (auto used{SelectUsedSymbols(syms, expr)}; !used.empty()) {
+ result.value = false;
+ result.reason.Say(exprSource,
+ "The %s of the affected loop uses iteration variables of enclosing loops: %s"_because_en_US,
+ exprName, JoinSymbolNames(used));
+ }
+}
+
+WithReason<bool> LoopSequence::isRectangular(
+ const std::vector<const LoopSequence *> &outer) const {
+ assert(entry_->owner && "Must have owner construct");
+ auto *loop{parser::Unwrap<parser::DoConstruct>(*entry_->owner)};
+ if (!loop) {
+ // Can "rectangular" property be computed for a loop-nest-generating
+ // construct? What if the loops in the nest are not rectangular with
+ // respect to each other?
+ return {};
+ }
+
+ SymbolVector outerIVs;
+ for (auto *sequence : llvm::reverse(outer)) {
+ for (auto &control : sequence->getLoopControls()) {
+ if (control.iv) {
+ outerIVs.emplace_back(*control.iv);
+ }
+ }
+ }
+
+ WithReason<bool> result(true);
+
+ for (auto &control : getLoopControls()) {
+ if (!control.iv || !control.lbound.value || !control.ubound.value) {
+ continue;
+ }
+ CheckSymbolExprOverlap(result, outerIVs, *control.lbound.value,
+ "lower bound", control.lbound.source);
+ CheckSymbolExprOverlap(result, outerIVs, *control.ubound.value,
+ "upper bound", control.ubound.source);
+ if (control.step.value) {
+ CheckSymbolExprOverlap(result, outerIVs, *control.step.value,
+ "iteration step", control.step.source);
+ }
+ }
+
+ return result;
+}
} // namespace Fortran::semantics::omp
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index fb241d2606b47..4553c90d88f7f 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -1097,13 +1097,6 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
privateDataSharingAttributeObjects_.clear();
}
- /// Check that loops in the loop nest are perfectly nested, as well that lower
- /// bound, upper bound, and step expressions do not use the iv
- /// of a surrounding loop of the associated loops nest.
- /// We do not support non-perfectly nested loops not non-rectangular loops yet
- /// (both introduced in OpenMP 5.0)
- void CheckPerfectNestAndRectangularLoop(const parser::OpenMPLoopConstruct &x);
-
// Predetermined DSA rules
void PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
const parser::OpenMPLoopConstruct &);
@@ -2062,9 +2055,6 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
}
}
- // Must be done before iv privatization
- CheckPerfectNestAndRectangularLoop(x);
-
PrivatizeAssociatedLoopIndexAndCheckLoopLevel(x);
ordCollapseLevel = GetNumAffectedLoopsFromLoopConstruct(x) + 1;
return true;
@@ -2275,80 +2265,6 @@ void OmpAttributeVisitor::CollectNumAffectedLoopsFromClauses(
}
}
-void OmpAttributeVisitor::CheckPerfectNestAndRectangularLoop(
- const parser::OpenMPLoopConstruct &x) {
- auto &dirContext{GetContext()};
- std::int64_t dirDepth{dirContext.associatedLoopLevel};
- if (dirDepth <= 0)
- return;
-
- auto checkExprHasSymbols = [&](llvm::SmallVector<Symbol *> &ivs,
- const parser::ScalarExpr *bound) {
- if (ivs.empty())
- return;
- auto boundExpr{semantics::AnalyzeExpr(context_, *bound)};
- if (!boundExpr)
- return;
- semantics::UnorderedSymbolSet boundSyms{
- evaluate::CollectSymbols(*boundExpr)};
- if (boundSyms.empty())
- return;
- for (Symbol *iv : ivs) {
- if (boundSyms.count(*iv) != 0) {
- // TODO: Point to occurence of iv in boundExpr, directiveSource as a
- // note
- context_.Say(dirContext.directiveSource,
- "Trip count must be computable and invariant"_err_en_US);
- }
- }
- };
-
- // Find the associated region by skipping nested loop-associated constructs
- // such as loop transformations
- for (auto &construct : std::get<parser::Block>(x.t)) {
- if (const auto *innermostConstruct{parser::omp::GetOmpLoop(construct)}) {
- CheckPerfectNestAndRectangularLoop(*innermostConstruct);
- } else if (const auto *doConstruct{
- parser::omp::GetDoConstruct(construct)}) {
-
- llvm::SmallVector<Symbol *> ivs;
- int curLevel{0};
- const auto *loop{doConstruct};
- while (true) {
- auto [iv, lb, ub, step] = GetLoopBounds(*loop);
-
- if (lb)
- checkExprHasSymbols(ivs, lb);
- if (ub)
- checkExprHasSymbols(ivs, ub);
- if (step)
- checkExprHasSymbols(ivs, step);
- if (iv) {
- if (auto *symbol{currScope().FindSymbol(iv->source)})
- ivs.push_back(symbol);
- }
-
- // Stop after processing all affected loops
- if (curLevel + 1 >= dirDepth)
- break;
-
- // Recurse into nested loop
- const auto &block{std::get<parser::Block>(loop->t)};
- if (block.empty()) {
- break;
- }
-
- loop = GetDoConstructIf(block.front());
- if (!loop) {
- break;
- }
-
- ++curLevel;
- }
- }
- }
-}
-
// 2.15.1.1 Data-sharing Attribute Rules - Predetermined
// - The loop iteration variable(s) in the associated do-loop(s) of a do,
// parallel do, taskloop, or distribute construct is (are) private.
diff --git a/flang/test/Semantics/OpenMP/do22.f90 b/flang/test/Semantics/OpenMP/do22.f90
index a0502aee748ae..2ced881a2af8b 100644
--- a/flang/test/Semantics/OpenMP/do22.f90
+++ b/flang/test/Semantics/OpenMP/do22.f90
@@ -38,9 +38,11 @@ subroutine do_imperfectly_nested_behind
subroutine do_nonrectangular_lb
integer i, j
- !ERROR: Trip count must be computable and invariant
- !$omp do collapse(2)
+ !ERROR: This construct requires a rectangular loop nest, but the associated nest is not
+ !BECAUSE: When SCHEDULE clause is present, none of the loops affected by DO can be non-rectangular
+ !$omp do collapse(2) schedule(auto)
do i = 1, 10
+ !BECAUSE: The lower bound of the affected loop uses iteration variables of enclosing loops: 'i'
do j = i, 10
print *, i, j
end do
@@ -52,9 +54,11 @@ subroutine do_nonrectangular_lb
subroutine do_nonrectangular_ub
integer i, j
- !ERROR: Trip count must be computable and invariant
- !$omp do collapse(2)
+ !ERROR: This construct requires a rectangular loop nest, but the associated nest is not
+ !BECAUSE: When SCHEDULE clause is present, none of the loops affected by DO can be non-rectangular
+ !$omp do collapse(2) schedule(auto)
do i = 1, 10
+ !BECAUSE: The upper bound of the affected loop uses iteration variables of enclosing loops: 'i'
do j = 0, i
print *, i, j
end do
@@ -66,9 +70,11 @@ subroutine do_nonrectangular_ub
subroutine do_nonrectangular_step
integer i, j
- !ERROR: Trip count must be computable and invariant
- !$omp do collapse(2)
+ !ERROR: This construct requires a rectangular loop nest, but the associated nest is not
+ !BECAUSE: When SCHEDULE clause is present, none of the loops affected by DO can be non-rectangular
+ !$omp do collapse(2) schedule(auto)
do i = 1, 10
+ !BECAUSE: The iteration step of the affected loop uses iteration variables of enclosing loops: 'i'
do j = 1, 10, i
print *, i, j
end do
diff --git a/flang/test/Semantics/OpenMP/tile06.f90 b/flang/test/Semantics/OpenMP/tile06.f90
index 52518d43f0554..dfe0594922fc6 100644
--- a/flang/test/Semantics/OpenMP/tile06.f90
+++ b/flang/test/Semantics/OpenMP/tile06.f90
@@ -6,9 +6,11 @@ subroutine nonrectangular_loop_lb
implicit none
integer i, j
- !ERROR: Trip count must be computable and invariant
+ !ERROR: This construct requires a rectangular loop nest, but the associated nest is not
+ !BECAUSE: None of the loops affected by TILE can be non-rectangular
!$omp tile sizes(2,2)
do i = 1, 5
+ !BECAUSE: The upper bound of the affected loop uses iteration variables of enclosing loops: 'i'
do j = 1, i
print *, i, j
end do
@@ -20,9 +22,11 @@ subroutine nonrectangular_loop_ub
implicit none
integer i, j
- !ERROR: Trip count must be computable and invariant
+ !ERROR: This construct requires a rectangular loop nest, but the associated nest is not
+ !BECAUSE: None of the loops affected by TILE can be non-rectangular
!$omp tile sizes(2,2)
do i = 1, 5
+ !BECAUSE: The upper bound of the affected loop uses iteration variables of enclosing loops: 'i'
do j = 1, i
print *, i, j
end do
@@ -34,9 +38,11 @@ subroutine nonrectangular_loop_step
implicit none
integer i, j
- !ERROR: Trip count must be computable and invariant
+ !ERROR: This construct requires a rectangular loop nest, but the associated nest is not
+ !BECAUSE: None of the loops affected by TILE can be non-rectangular
!$omp tile sizes(2,2)
do i = 1, 5
+ !BECAUSE: The iteration step of the affected loop uses iteration variables of enclosing loops: 'i'
do j = 1, 42, i
print *, i, j
end do
>From 2d3fc475416cf44298f29ce5fada8203d952a442 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 6 Apr 2026 13:59:18 -0500
Subject: [PATCH 2/2] format
---
flang/lib/Semantics/openmp-utils.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 18a10be3276a5..a8c2c11823ba7 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -756,8 +756,7 @@ WithReason<int64_t> GetHeightWithReason(
} else {
Reason reason;
reason.Say(spec.DirName().source, MsgClauseAbsentAssume,
- GetUpperName(llvm::omp::Clause::OMPC_depth, version),
- "a depth of 2");
+ GetUpperName(llvm::omp::Clause::OMPC_depth, version), "a depth of 2");
return {-1, std::move(reason)};
}
case llvm::omp::Directive::OMPD_fuse:
More information about the llvm-branch-commits
mailing list