[flang-commits] [flang] [OpenACC] Add emit-independent-loops-as-unstructured flag (PR #204080)
Kareem Ergawy via flang-commits
flang-commits at lists.llvm.org
Tue Jun 16 01:06:42 PDT 2026
https://github.com/ergawy created https://github.com/llvm/llvm-project/pull/204080
Add a flag (default true) to bypass the TODOs in `loopWillBeIndependent` that fired for unstructured do loops inside independent OpenACC loop and combined constructs, lowering them as `acc.loop` instead. Existing TODO tests are extended to exercise both the default (lowered) path and the explicit `=false` path that still reports the TODO.
>From 943ccc356b5e97749c7ff771a3050d2e4eec36e9 Mon Sep 17 00:00:00 2001
From: ergawy <kareem.ergawy at gmail.com>
Date: Tue, 16 Jun 2026 01:05:18 -0700
Subject: [PATCH] [OpenACC] Add emit-independent-loops-as-unstructured flag
Add a flag (default true) to bypass the TODOs in `loopWillBeIndependent`
that fired for unstructured do loops inside independent OpenACC loop and
combined constructs, lowering them as `acc.loop` instead. Existing TODO
tests are extended to exercise both the default (lowered) path and the
explicit `=false` path that still reports the TODO.
Co-Authored-By: Claude <noreply at anthropic.com>
---
flang/lib/Lower/OpenACC.cpp | 13 ++++++-
.../acc-unstructured-combined-construct.f90 | 26 +++++++++++--
.../Todo/acc-unstructured-loop-construct.f90 | 37 ++++++++++++++++---
3 files changed, 66 insertions(+), 10 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 51c9356cc8d46..2a4368ffb7400 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -83,6 +83,13 @@ static llvm::cl::opt<bool> enableSymbolRemapping(
llvm::cl::desc("Whether to remap symbols that appears in data clauses."),
llvm::cl::init(true));
+static llvm::cl::opt<bool> emitIndependentLoopsAsUnstructured(
+ "emit-independent-loops-as-unstructured",
+ llvm::cl::desc("Whether to allow lowering unstructured do loops inside "
+ "independent OpenACC loop constructs instead of emitting "
+ "a TODO."),
+ llvm::cl::init(true));
+
// Special value for * passed in device_type or gang clauses.
static constexpr std::int64_t starCst = -1;
@@ -2478,7 +2485,8 @@ genACC(Fortran::lower::AbstractConverter &converter,
std::get<std::optional<Fortran::parser::DoConstruct>>(loopConstruct.t);
if (outerDoConstruct.has_value() && eval.lowerAsUnstructured() &&
- loopWillBeIndependent(converter, accClauseList, loopDirective.v))
+ loopWillBeIndependent(converter, accClauseList, loopDirective.v) &&
+ !emitIndependentLoopsAsUnstructured)
TODO(currentLocation,
"unstructured do loop in independent OpenACC loop construct");
@@ -3252,7 +3260,8 @@ genACC(Fortran::lower::AbstractConverter &converter,
Fortran::lower::StatementContext stmtCtx;
if (outerDoConstruct.has_value() && eval.lowerAsUnstructured() &&
- loopWillBeIndependent(converter, accClauseList, combinedDirective.v))
+ loopWillBeIndependent(converter, accClauseList, combinedDirective.v) &&
+ !emitIndependentLoopsAsUnstructured)
TODO(currentLocation, "unstructured do loop in combined acc construct");
if (combinedDirective.v == llvm::acc::ACCD_kernels_loop) {
diff --git a/flang/test/Lower/OpenACC/Todo/acc-unstructured-combined-construct.f90 b/flang/test/Lower/OpenACC/Todo/acc-unstructured-combined-construct.f90
index da06ce8c2d170..74ba49f0cf5f3 100644
--- a/flang/test/Lower/OpenACC/Todo/acc-unstructured-combined-construct.f90
+++ b/flang/test/Lower/OpenACC/Todo/acc-unstructured-combined-construct.f90
@@ -3,9 +3,17 @@
! `independent`).
! RUN: split-file %s %t
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/stop_collapse1.f90 -o - 2>&1 | FileCheck %s --check-prefix=STOP1
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/cycle_collapse2.f90 -o - 2>&1 | FileCheck %s --check-prefix=CYCLE2
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/stop_collapse3.f90 -o - 2>&1 | FileCheck %s --check-prefix=STOP3
+
+! By default (--emit-independent-loops-as-unstructured=true), the loops are
+! lowered to combined `acc.parallel` + `acc.loop` operations.
+! RUN: bbc -fopenacc -emit-hlfir %t/stop_collapse1.f90 -o - | FileCheck %s --check-prefix=STOP1-OK
+! RUN: bbc -fopenacc -emit-hlfir %t/cycle_collapse2.f90 -o - | FileCheck %s --check-prefix=CYCLE2-OK
+! RUN: bbc -fopenacc -emit-hlfir %t/stop_collapse3.f90 -o - | FileCheck %s --check-prefix=STOP3-OK
+
+! With --emit-independent-loops-as-unstructured=false, the TODO is emitted.
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/stop_collapse1.f90 -o - 2>&1 | FileCheck %s --check-prefix=STOP1
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/cycle_collapse2.f90 -o - 2>&1 | FileCheck %s --check-prefix=CYCLE2
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/stop_collapse3.f90 -o - 2>&1 | FileCheck %s --check-prefix=STOP3
!--- stop_collapse1.f90
@@ -27,6 +35,10 @@ subroutine test_unstructured2(a, b, c)
! STOP1: not yet implemented: unstructured do loop in combined acc construct
+! STOP1-OK-LABEL: func.func @_QPtest_unstructured2
+! STOP1-OK: acc.parallel combined(loop)
+! STOP1-OK: acc.loop combined(parallel)
+
!--- cycle_collapse2.f90
! `acc parallel loop collapse(2)` with an early-exit (CYCLE).
@@ -49,6 +61,10 @@ subroutine test_unstructured_collapse_cycle(a)
! CYCLE2: not yet implemented: unstructured do loop in combined acc construct
+! CYCLE2-OK-LABEL: func.func @_QPtest_unstructured_collapse_cycle
+! CYCLE2-OK: acc.parallel combined(loop)
+! CYCLE2-OK: acc.loop combined(parallel)
+
!--- stop_collapse3.f90
! `acc parallel loop collapse(3)` with STOP - the collapse=3 form of the
@@ -67,3 +83,7 @@ subroutine test_unstructured_collapse_stop(a)
end subroutine
! STOP3: not yet implemented: unstructured do loop in combined acc construct
+
+! STOP3-OK-LABEL: func.func @_QPtest_unstructured_collapse_stop
+! STOP3-OK: acc.parallel combined(loop)
+! STOP3-OK: acc.loop combined(parallel)
diff --git a/flang/test/Lower/OpenACC/Todo/acc-unstructured-loop-construct.f90 b/flang/test/Lower/OpenACC/Todo/acc-unstructured-loop-construct.f90
index 285d970250c09..f26e95d235d04 100644
--- a/flang/test/Lower/OpenACC/Todo/acc-unstructured-loop-construct.f90
+++ b/flang/test/Lower/OpenACC/Todo/acc-unstructured-loop-construct.f90
@@ -2,11 +2,21 @@
! `acc loop` whose default parallelism resolves to `independent`.
! RUN: split-file %s %t
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/goto_one_level.f90 -o - 2>&1 | FileCheck %s --check-prefix=GOTO1
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/goto_with_intermediate.f90 -o - 2>&1 | FileCheck %s --check-prefix=GOTO2
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/collapse_cycle.f90 -o - 2>&1 | FileCheck %s --check-prefix=CCYCLE
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/cache_exit.f90 -o - 2>&1 | FileCheck %s --check-prefix=CEXIT
-! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir %t/cache_select_case.f90 -o - 2>&1 | FileCheck %s --check-prefix=CCASE
+
+! By default (--emit-independent-loops-as-unstructured=true), the loops are
+! lowered to `acc.loop` operations.
+! RUN: bbc -fopenacc -emit-hlfir %t/goto_one_level.f90 -o - | FileCheck %s --check-prefix=GOTO1-OK
+! RUN: bbc -fopenacc -emit-hlfir %t/goto_with_intermediate.f90 -o - | FileCheck %s --check-prefix=GOTO2-OK
+! RUN: bbc -fopenacc -emit-hlfir %t/collapse_cycle.f90 -o - | FileCheck %s --check-prefix=CCYCLE-OK
+! RUN: bbc -fopenacc -emit-hlfir %t/cache_exit.f90 -o - | FileCheck %s --check-prefix=CEXIT-OK
+! RUN: bbc -fopenacc -emit-hlfir %t/cache_select_case.f90 -o - | FileCheck %s --check-prefix=CCASE-OK
+
+! With --emit-independent-loops-as-unstructured=false, the TODO is emitted.
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/goto_one_level.f90 -o - 2>&1 | FileCheck %s --check-prefix=GOTO1
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/goto_with_intermediate.f90 -o - 2>&1 | FileCheck %s --check-prefix=GOTO2
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/collapse_cycle.f90 -o - 2>&1 | FileCheck %s --check-prefix=CCYCLE
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/cache_exit.f90 -o - 2>&1 | FileCheck %s --check-prefix=CEXIT
+! RUN: %not_todo_cmd bbc -fopenacc -emit-hlfir --emit-independent-loops-as-unstructured=false %t/cache_select_case.f90 -o - 2>&1 | FileCheck %s --check-prefix=CCASE
!--- goto_one_level.f90
@@ -28,6 +38,10 @@ subroutine test_unstructured6(N, A, B)
! GOTO1: not yet implemented: unstructured do loop in independent OpenACC loop construct
+! GOTO1-OK-LABEL: func.func @_QPtest_unstructured6
+! GOTO1-OK: acc.loop {{.*}}gang vector
+! GOTO1-OK: acc.loop
+
!--- goto_with_intermediate.f90
! Same as above but with intermediate code between the inner loop end and
@@ -49,6 +63,10 @@ subroutine test_unstructured7(A, B, C, N)
! GOTO2: not yet implemented: unstructured do loop in independent OpenACC loop construct
+! GOTO2-OK-LABEL: func.func @_QPtest_unstructured7
+! GOTO2-OK: acc.loop {{.*}}gang vector
+! GOTO2-OK: acc.loop
+
!--- collapse_cycle.f90
! Orphan `acc loop collapse(2)` with an early-exit (CYCLE) - defaults to
@@ -72,6 +90,9 @@ subroutine test_unstructured_collapse_loop_only(a)
! CCYCLE: not yet implemented: unstructured do loop in independent OpenACC loop construct
+! CCYCLE-OK-LABEL: func.func @_QPtest_unstructured_collapse_loop_only
+! CCYCLE-OK: acc.loop
+
!--- cache_exit.f90
! `acc loop` with `cache` directive and EXIT inside the body - the EXIT
@@ -93,6 +114,9 @@ subroutine test_cache_single_element()
! CEXIT: not yet implemented: unstructured do loop in independent OpenACC loop construct
+! CEXIT-OK-LABEL: func.func @_QPtest_cache_single_element
+! CEXIT-OK: acc.loop
+
!--- cache_select_case.f90
! `acc loop` with `cache` directive and SELECT CASE inside the body - the
@@ -118,3 +142,6 @@ subroutine test_cache_nonunit_lb()
end subroutine
! CCASE: not yet implemented: unstructured do loop in independent OpenACC loop construct
+
+! CCASE-OK-LABEL: func.func @_QPtest_cache_nonunit_lb
+! CCASE-OK: acc.loop
More information about the flang-commits
mailing list