[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