[flang-commits] [flang] [flang][openacc] Fix nested labeled DO loops sharing a terminator (PR #217705)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Thu Aug 20 11:21:47 PDT 2026
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/217705
>From 576cfb06037540887fc57a924ac0a17573faaf61 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Thu, 20 Aug 2026 10:30:09 -0700
Subject: [PATCH] [flang][openacc] Fix nested labeled DO loops sharing a
terminator
---
flang/lib/Parser/tools.cpp | 19 ++++++++++++
flang/test/Parser/acc-label-do.f90 | 50 ++++++++++++++++++++++++++++++
2 files changed, 69 insertions(+)
diff --git a/flang/lib/Parser/tools.cpp b/flang/lib/Parser/tools.cpp
index ff8ab11352a72..d0c919d07f917 100644
--- a/flang/lib/Parser/tools.cpp
+++ b/flang/lib/Parser/tools.cpp
@@ -256,12 +256,31 @@ std::optional<Label> GetFinalLabel(const OpenMPConstruct &x) {
x.u);
}
+// The DO loop associated with a loop or combined construct is only terminated
+// by a labeled statement when the construct has no end directive.
+template <typename END, typename C>
+static std::optional<Label> GetFinalLabelOfAssociatedLoop(const C &x) {
+ if (std::get<std::optional<END>>(x.t)) {
+ return std::nullopt;
+ }
+ if (const auto &doLoop{std::get<std::optional<DoConstruct>>(x.t)}) {
+ return GetFinalLabel(std::get<Block>(doLoop->t));
+ }
+ return std::nullopt;
+}
+
std::optional<Label> GetFinalLabel(const OpenACCConstruct &x) {
return common::visit(
common::visitors{
[](const OpenACCBlockConstruct &x) -> std::optional<Label> {
return GetFinalLabel(std::get<Block>(x.t));
},
+ [](const OpenACCLoopConstruct &x) -> std::optional<Label> {
+ return GetFinalLabelOfAssociatedLoop<AccEndLoop>(x);
+ },
+ [](const OpenACCCombinedConstruct &x) -> std::optional<Label> {
+ return GetFinalLabelOfAssociatedLoop<AccEndCombinedDirective>(x);
+ },
[](const OpenACCAtomicConstruct &x) -> std::optional<Label> {
return common::visit(
common::visitors{
diff --git a/flang/test/Parser/acc-label-do.f90 b/flang/test/Parser/acc-label-do.f90
index 5bfe1f3de7ca2..e9de2fe59d9b2 100644
--- a/flang/test/Parser/acc-label-do.f90
+++ b/flang/test/Parser/acc-label-do.f90
@@ -31,3 +31,53 @@ subroutine s
!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> ContinueStmt
!PARSE-TREE: | | EndDoStmt ->
!PARSE-TREE: | AccEndCombinedDirective -> AccCombinedDirective -> llvm::acc::Directive = parallel loop
+
+! Nested labeled DO loops that share a terminating label, with an OpenACC LOOP
+! construct associated with the inner loop. The shared label must still close
+! both loops.
+
+subroutine nested_shared_label(a, n)
+ integer :: i, j, n
+ real :: a(n)
+!$acc kernels
+!$acc loop independent
+ do 10 j = 1, n
+!$acc loop gang vector
+ do 10 i = 1, n
+10 a(i) = 0.
+!$acc end kernels
+end
+
+!UNPARSE: SUBROUTINE nested_shared_label (a, n)
+!UNPARSE: !$ACC KERNELS
+!UNPARSE: !$ACC LOOP INDEPENDENT
+!UNPARSE: DO j=1_4,n
+!UNPARSE: !$ACC LOOP GANG VECTOR
+!UNPARSE: DO i=1_4,n
+!UNPARSE: 10
+!UNPARSE: END DO
+!UNPARSE: END DO
+!UNPARSE: !$ACC END KERNELS
+!UNPARSE: END SUBROUTINE
+
+!PARSE-TREE: OpenACCBlockConstruct
+!PARSE-TREE: | AccBeginBlockDirective
+!PARSE-TREE: | | AccBlockDirective -> llvm::acc::Directive = kernels
+!PARSE-TREE: | Block
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenACCConstruct -> OpenACCLoopConstruct
+!PARSE-TREE: | | | AccBeginLoopDirective
+!PARSE-TREE: | | | | AccLoopDirective -> llvm::acc::Directive = loop
+!PARSE-TREE: | | | | AccClauseList -> AccClause -> Independent
+!PARSE-TREE: | | | DoConstruct
+!PARSE-TREE: | | | | NonLabelDoStmt
+!PARSE-TREE: | | | | Block
+!PARSE-TREE: | | | | | ExecutionPartConstruct -> ExecutableConstruct -> OpenACCConstruct -> OpenACCLoopConstruct
+!PARSE-TREE: | | | | | | AccBeginLoopDirective
+!PARSE-TREE: | | | | | | | AccLoopDirective -> llvm::acc::Directive = loop
+!PARSE-TREE: | | | | | | DoConstruct
+!PARSE-TREE: | | | | | | | NonLabelDoStmt
+!PARSE-TREE: | | | | | | | Block
+!PARSE-TREE: | | | | | | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt
+!PARSE-TREE: | | | | | | | EndDoStmt ->
+!PARSE-TREE: | | | | EndDoStmt ->
+!PARSE-TREE: | AccEndBlockDirective -> AccBlockDirective -> llvm::acc::Directive = kernels
More information about the flang-commits
mailing list