[flang-commits] [flang] [mlir][OpenACC] Do not give an initial-value map a descriptor's section bounds (PR #220321)

via flang-commits flang-commits at lists.llvm.org
Mon Sep 14 16:46:00 PDT 2026


https://github.com/khaki3 updated https://github.com/llvm/llvm-project/pull/220321

>From a63efb787e65c995c7f78bcb3bd96ae14f6ca687 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Mon, 14 Sep 2026 16:45:35 -0700
Subject: [PATCH] [flang][OpenACC] Do not hoist a firstprivate map over bounds
 defined in the region

Example:
```fortran
subroutine s(np, x)
  real :: x(np), cwp(np,3)
!$acc parallel
!$acc loop gang private(cwp(:,:))
  do k = 1, np
     cwp(k,1) = x(k)
  end do
!$acc end parallel
end subroutine
```

In this code the section bounds for `cwp(:,:)` are computed inside the compute
region while the variable itself is defined outside it. acc-optimize-firstprivate-map
only checked the variable before moving `acc.firstprivate_map` ahead of the
region, so the operation ended up above its own bounds operands and verification
failed with "operand #1 does not dominate this use".

Fix: skip the hoist when any bounds operand is defined inside the region.
---
 .../Transforms/ACCOptimizeFirstprivateMap.cpp |  7 ++++++
 .../OpenACC/acc-optimize-firstprivate-map.fir | 24 +++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/flang/lib/Optimizer/OpenACC/Transforms/ACCOptimizeFirstprivateMap.cpp b/flang/lib/Optimizer/OpenACC/Transforms/ACCOptimizeFirstprivateMap.cpp
index ec40e1209f97a9..e1463f8cca9eff 100644
--- a/flang/lib/Optimizer/OpenACC/Transforms/ACCOptimizeFirstprivateMap.cpp
+++ b/flang/lib/Optimizer/OpenACC/Transforms/ACCOptimizeFirstprivateMap.cpp
@@ -143,6 +143,13 @@ class ACCOptimizeFirstprivateMap
           // uses and erase.
           firstprivateInitOp.getAccVar().replaceAllUsesWith(var);
           opsToErase.push_back(firstprivateInitOp);
+        } else if (llvm::any_of(
+                       firstprivateInitOp.getBounds(), [&](Value bound) {
+                         return isDefinedInsideRegion(bound, offloadOp);
+                       })) {
+          // Bounds computed inside the region would not dominate the hoisted
+          // op, so leave it in place.
+          continue;
         } else {
           // Variable is defined outside - hoist the op out of the region,
           // then apply optimization.
diff --git a/flang/test/Transforms/OpenACC/acc-optimize-firstprivate-map.fir b/flang/test/Transforms/OpenACC/acc-optimize-firstprivate-map.fir
index bce575e752866e..b64150726cd435 100644
--- a/flang/test/Transforms/OpenACC/acc-optimize-firstprivate-map.fir
+++ b/flang/test/Transforms/OpenACC/acc-optimize-firstprivate-map.fir
@@ -239,3 +239,27 @@ func.func @test_block_arg_no_hoist(%arg0: !fir.ref<i32>) {
   }
   return
 }
+
+// -----
+
+// Test: bounds computed inside the offload region - must not be hoisted, as the
+// bounds would no longer dominate the hoisted operation.
+
+// CHECK-LABEL: func.func @test_bounds_defined_inside_region
+func.func @test_bounds_defined_inside_region(%arg0: !fir.ref<!fir.box<!fir.array<?xf32>>>, %n: index) {
+  %c0 = arith.constant 0 : index
+  %c1 = arith.constant 1 : index
+  // CHECK: acc.parallel
+  acc.parallel {
+    %box = fir.load %arg0 : !fir.ref<!fir.box<!fir.array<?xf32>>>
+    %dims:3 = fir.box_dims %box, %c0 : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
+    %ub = arith.subi %n, %c1 : index
+    // CHECK: %[[BOUNDS:.*]] = acc.bounds
+    %b = acc.bounds lowerbound(%c0 : index) upperbound(%ub : index) extent(%n : index) stride(%dims#2 : index) startIdx(%c1 : index) strideInBytes(true)
+    // CHECK: acc.firstprivate_map varPtr(%{{.*}}) bounds(%[[BOUNDS]])
+    %fp = acc.firstprivate_map varPtr(%arg0 : !fir.ref<!fir.box<!fir.array<?xf32>>>) bounds(%b) name("a(:)") -> !fir.ref<!fir.box<!fir.array<?xf32>>>
+    %v = fir.load %fp : !fir.ref<!fir.box<!fir.array<?xf32>>>
+    acc.yield
+  }
+  return
+}



More information about the flang-commits mailing list