[Mlir-commits] [mlir] [mlir][acc] Run acc-specialize-for-host rewrite to convergence (PR #205727)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed Jun 24 22:47:55 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-openacc
Author: khaki3
<details>
<summary>Changes</summary>
Example:
```fortran
!$acc routine worker
subroutine transform(p, n)
real*8 p(*); integer n
!$acc loop seq
do i1 = 1, n
!$acc loop seq
do i2 = 1, n
! ... a dozen+ levels of nested acc loops ...
!$acc loop vector
do i = 1, n
p(i) = p(i) + 1.0d0
end do
end do
end do
end subroutine
```
In this code, the routine becomes a `func.func` with deeply nested orphan `acc.loop` ops. `acc-specialize-for-host` lowers them (e.g. `acc.loop` → `scf.for`) via `applyPatternsGreedily`, but leaves `GreedyRewriteConfig::maxIterations` at its default of 10. Since inner loops only become rewritable after their parents convert, a nest deeper than 10 isn't at a fixed point when the cap is hit, so the driver returns `failure()` and the pass calls `signalPassFailure()` — a spurious, diagnostic-less failure even though the conversion was progressing correctly.
Fix:
Run the rewrite to convergence instead of stopping at the default cap:
```cpp
config.setMaxIterations(GreedyRewriteConfig::kNoLimit);
```
The patterns are strictly reductive (ops are lowered/erased, never regenerated), so this is safe. Adds a regression test with a 16-deep orphan `acc.loop` nest.
---
Full diff: https://github.com/llvm/llvm-project/pull/205727.diff
2 Files Affected:
- (modified) mlir/lib/Dialect/OpenACC/Transforms/ACCSpecializeForHost.cpp (+3)
- (added) mlir/test/Dialect/OpenACC/acc-specialize-for-host-deep-nesting.mlir (+65)
``````````diff
diff --git a/mlir/lib/Dialect/OpenACC/Transforms/ACCSpecializeForHost.cpp b/mlir/lib/Dialect/OpenACC/Transforms/ACCSpecializeForHost.cpp
index 633538069c268..aab03b31ae70b 100644
--- a/mlir/lib/Dialect/OpenACC/Transforms/ACCSpecializeForHost.cpp
+++ b/mlir/lib/Dialect/OpenACC/Transforms/ACCSpecializeForHost.cpp
@@ -344,6 +344,9 @@ class ACCSpecializeForHost
populateACCOrphanToHostPatterns(patterns, accSupport);
GreedyRewriteConfig config;
config.setUseTopDownTraversal(true);
+ // Deeply nested orphan acc routines can need more than the default
+ // iteration cap to converge; lift it to avoid spurious pass failure.
+ config.setMaxIterations(GreedyRewriteConfig::kNoLimit);
if (failed(applyPatternsGreedily(funcOp, std::move(patterns), config)))
signalPassFailure();
}
diff --git a/mlir/test/Dialect/OpenACC/acc-specialize-for-host-deep-nesting.mlir b/mlir/test/Dialect/OpenACC/acc-specialize-for-host-deep-nesting.mlir
new file mode 100644
index 0000000000000..4d7940dbda462
--- /dev/null
+++ b/mlir/test/Dialect/OpenACC/acc-specialize-for-host-deep-nesting.mlir
@@ -0,0 +1,65 @@
+// RUN: mlir-opt %s -acc-specialize-for-host | FileCheck %s
+
+// Deeply nested orphan acc.loops in a seq routine require more than the
+// greedy rewriter's default iteration cap to fully lower to scf.for. The
+// pass must run the rewrite to convergence rather than bailing out.
+
+acc.routine @acc_routine_deep func(@deeply_nested_orphan_loops) seq
+// CHECK-LABEL: func.func @deeply_nested_orphan_loops
+// CHECK-NOT: acc.loop
+// CHECK-COUNT-16: scf.for
+func.func @deeply_nested_orphan_loops(%arg0 : memref<i32>) attributes {acc.routine_info = #acc.routine_info<[@acc_routine_deep]>} {
+ %c0 = arith.constant 0 : i32
+ %c10 = arith.constant 10 : i32
+ %c1 = arith.constant 1 : i32
+ acc.loop control(%iv0 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv1 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv2 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv3 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv4 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv5 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv6 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv7 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv8 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv9 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv10 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv11 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv12 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv13 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv14 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ acc.loop control(%iv15 : i32) = (%c0 : i32) to (%c10 : i32) step (%c1 : i32) {
+ memref.store %iv15, %arg0[] : memref<i32>
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ acc.yield
+ } attributes {inclusiveUpperbound = array<i1: true>, seq = [#acc.device_type<none>]}
+ return
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/205727
More information about the Mlir-commits
mailing list