[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