[flang-commits] [flang] [flang][acc] fix array-section reductions on boxed arrays (PR #211648)
Susan Tan ス-ザン タン via flang-commits
flang-commits at lists.llvm.org
Thu Jul 23 12:46:41 PDT 2026
https://github.com/SusanTan updated https://github.com/llvm/llvm-project/pull/211648
>From 6166df44597b6a091a9c4da779c6962a51cbd2fc Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Thu, 23 Jul 2026 08:02:38 -0700
Subject: [PATCH 1/4] tweak
---
flang/lib/Lower/OpenACC.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 0767511118d4f..d2eb330dbdf20 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -1148,8 +1148,6 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
Fortran::semantics::Symbol &symbol = getSymbolFromAccObject(accObject);
Fortran::semantics::MaybeExpr designator = Fortran::common::visit(
[&](auto &&s) { return ea.Analyze(s); }, accObject.u);
- bool isWholeSymbol =
- !designator || Fortran::evaluate::UnwrapWholeSymbolDataRef(*designator);
fir::factory::AddrAndBoundsInfo info =
Fortran::lower::gatherDataOperandAddrAndBounds<
mlir::acc::DataBoundsOp, mlir::acc::DataBoundsType>(
@@ -1195,7 +1193,10 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
reductionOperands.push_back(op.getAccVar());
// Track the symbol and its corresponding mlir::Value if requested so that
// accesses inside the compute/loop regions use the acc.reduction variable.
- if (dataMap && isWholeSymbol)
+ // Remap even for array-section reductions: otherwise element accesses
+ // inside the region keep referring to the original array instead of the
+ // private reduction copy.
+ if (dataMap)
dataMap->emplaceSymbol(op.getAccVar(),
Fortran::semantics::SymbolRef(symbol));
}
>From dd7e5cfa213ec190dc724a4bb3fff6ca61bd0b30 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Thu, 23 Jul 2026 12:29:53 -0700
Subject: [PATCH 2/4] add test
---
.../Lower/OpenACC/acc-reduction-remapping.f90 | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/flang/test/Lower/OpenACC/acc-reduction-remapping.f90 b/flang/test/Lower/OpenACC/acc-reduction-remapping.f90
index 8c69efe7e8de6..fba244be829c1 100644
--- a/flang/test/Lower/OpenACC/acc-reduction-remapping.f90
+++ b/flang/test/Lower/OpenACC/acc-reduction-remapping.f90
@@ -50,6 +50,22 @@ subroutine array_split(x, y, n)
!$acc end parallel
end subroutine
+! Array-section reduction on a dynamic-extent array: element accesses inside
+! the region must remap to the acc.reduction result rather than to the
+! original (host) declare, otherwise the private reduction copy is silently
+! bypassed and the wrong memory gets updated.
+subroutine array_section_combined(a, mm, nn)
+ integer :: mm, nn
+ real :: a(mm)
+ integer :: i, k
+ !$acc parallel loop reduction(+:a(1:16))
+ do i = 1, nn
+ do k = 1, mm
+ a(k) = a(k) + 1.0
+ end do
+ end do
+end subroutine
+
! CHECK-LABEL: func.func @_QPscalar_combined(
! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[DECLARE_Y:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[DUMMY_SCOPE_0]] arg 2 {uniq_name = "_QFscalar_combinedEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
@@ -158,3 +174,31 @@ subroutine array_split(x, y, n)
! CHECK: }
! CHECK: return
! CHECK: }
+
+
+! CHECK-LABEL: func.func @_QParray_section_combined(
+! CHECK: %[[DECLARE_A:.*]]:2 = hlfir.declare %{{.*}}({{.*}}) dummy_scope {{.*}} arg 1 {uniq_name = "_QFarray_section_combinedEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>)
+! CHECK: %[[BOUND0:.*]] = acc.bounds {{.*}}
+! CHECK: %[[COPYIN:.*]] = acc.copyin var(%[[DECLARE_A]]#0 : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND0]]) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "a(1:16)"}
+! CHECK: acc.parallel combined(loop) dataOperands(%[[COPYIN]] : !fir.box<!fir.array<?xf32>>) {
+! CHECK: %[[BOX_ADDR_PAR:.*]] = fir.box_addr %[[COPYIN]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: %[[DECLARE_A_PAR:.*]]:2 = hlfir.declare %[[BOX_ADDR_PAR]]({{.*}}) dummy_scope {{.*}} arg 1 {uniq_name = "_QFarray_section_combinedEa"}
+! CHECK: %[[BOUND1:.*]] = acc.bounds {{.*}}
+! CHECK: %[[RED:.*]] = acc.reduction var(%[[DECLARE_A_PAR]]#0 : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND1]]) recipe(@reduction_add_section_lb0.ub15_box_Uxf32) -> !fir.box<!fir.array<?xf32>> {name = "a(1:16)"}
+! CHECK: acc.loop combined(parallel) {{.*}} reduction(%[[RED]] : !fir.box<!fir.array<?xf32>>) {{.*}} {
+! CHECK: %[[BOX_ADDR_RED:.*]] = fir.box_addr %[[RED]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: %[[DECLARE_A_RED:.*]]:2 = hlfir.declare %[[BOX_ADDR_RED]]({{.*}}) dummy_scope {{.*}} arg 1 {uniq_name = "_QFarray_section_combinedEa"}
+! CHECK: acc.loop {{.*}} {
+! CHECK: %[[DESIGNATE_READ:.*]] = hlfir.designate %[[DECLARE_A_RED]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: {{.*}} = fir.load %[[DESIGNATE_READ]] : !fir.ref<f32>
+! CHECK: %[[DESIGNATE_WRITE:.*]] = hlfir.designate %[[DECLARE_A_RED]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: hlfir.assign {{.*}} to %[[DESIGNATE_WRITE]] : f32, !fir.ref<f32>
+! CHECK: acc.yield
+! CHECK: }
+! CHECK: acc.yield
+! CHECK: }
+! CHECK: acc.yield
+! CHECK: }
+! CHECK: acc.copyout accVar(%[[COPYIN]] : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND0]]) to var(%[[DECLARE_A]]#0 : !fir.box<!fir.array<?xf32>>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "a(1:16)"}
+! CHECK: return
+! CHECK: }
>From 5a2e8f716dda5cbe87727336c1ab0aebad4c18a1 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Thu, 23 Jul 2026 12:36:43 -0700
Subject: [PATCH 3/4] add test
---
.../Lower/OpenACC/acc-reduction-remapping.f90 | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/flang/test/Lower/OpenACC/acc-reduction-remapping.f90 b/flang/test/Lower/OpenACC/acc-reduction-remapping.f90
index fba244be829c1..659547e8b09f1 100644
--- a/flang/test/Lower/OpenACC/acc-reduction-remapping.f90
+++ b/flang/test/Lower/OpenACC/acc-reduction-remapping.f90
@@ -66,6 +66,21 @@ subroutine array_section_combined(a, mm, nn)
end do
end subroutine
+! Same as above, but the section's lower bound (11) does not coincide with
+! the array's own lower bound (1): a "shift". The reduction recipe absorbs
+! this via a base-pointer offset, so remapping must still work.
+subroutine array_section_shifted(a, mm, nn)
+ integer :: mm, nn
+ real :: a(mm)
+ integer :: i, k
+ !$acc parallel loop reduction(+:a(11:20))
+ do i = 1, nn
+ do k = 11, 20
+ a(k) = a(k) + 1.0
+ end do
+ end do
+end subroutine
+
! CHECK-LABEL: func.func @_QPscalar_combined(
! CHECK: %[[DUMMY_SCOPE_0:.*]] = fir.dummy_scope : !fir.dscope
! CHECK: %[[DECLARE_Y:.*]]:2 = hlfir.declare %{{.*}} dummy_scope %[[DUMMY_SCOPE_0]] arg 2 {uniq_name = "_QFscalar_combinedEy"} : (!fir.ref<f32>, !fir.dscope) -> (!fir.ref<f32>, !fir.ref<f32>)
@@ -202,3 +217,31 @@ subroutine array_section_combined(a, mm, nn)
! CHECK: acc.copyout accVar(%[[COPYIN]] : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND0]]) to var(%[[DECLARE_A]]#0 : !fir.box<!fir.array<?xf32>>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "a(1:16)"}
! CHECK: return
! CHECK: }
+
+
+! CHECK-LABEL: func.func @_QParray_section_shifted(
+! CHECK: %[[DECLARE_A:.*]]:2 = hlfir.declare %{{.*}}({{.*}}) dummy_scope {{.*}} arg 1 {uniq_name = "_QFarray_section_shiftedEa"} : (!fir.ref<!fir.array<?xf32>>, !fir.shape<1>, !fir.dscope) -> (!fir.box<!fir.array<?xf32>>, !fir.ref<!fir.array<?xf32>>)
+! CHECK: %[[BOUND0:.*]] = acc.bounds lowerbound(%c10{{.*}} : index) upperbound(%c19{{.*}} : index) {{.*}}
+! CHECK: %[[COPYIN:.*]] = acc.copyin var(%[[DECLARE_A]]#0 : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND0]]) -> !fir.box<!fir.array<?xf32>> {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "a(11:20)"}
+! CHECK: acc.parallel combined(loop) dataOperands(%[[COPYIN]] : !fir.box<!fir.array<?xf32>>) {
+! CHECK: %[[BOX_ADDR_PAR:.*]] = fir.box_addr %[[COPYIN]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: %[[DECLARE_A_PAR:.*]]:2 = hlfir.declare %[[BOX_ADDR_PAR]]({{.*}}) dummy_scope {{.*}} arg 1 {uniq_name = "_QFarray_section_shiftedEa"}
+! CHECK: %[[BOUND1:.*]] = acc.bounds lowerbound(%c10{{.*}} : index) upperbound(%c19{{.*}} : index) {{.*}}
+! CHECK: %[[RED:.*]] = acc.reduction var(%[[DECLARE_A_PAR]]#0 : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND1]]) recipe(@reduction_add_section_lb10.ub19_box_Uxf32) -> !fir.box<!fir.array<?xf32>> {name = "a(11:20)"}
+! CHECK: acc.loop combined(parallel) {{.*}} reduction(%[[RED]] : !fir.box<!fir.array<?xf32>>) {{.*}} {
+! CHECK: %[[BOX_ADDR_RED:.*]] = fir.box_addr %[[RED]] : (!fir.box<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
+! CHECK: %[[DECLARE_A_RED:.*]]:2 = hlfir.declare %[[BOX_ADDR_RED]]({{.*}}) dummy_scope {{.*}} arg 1 {uniq_name = "_QFarray_section_shiftedEa"}
+! CHECK: acc.loop {{.*}} control(%{{.*}} : i32) = (%c11{{.*}} : i32) to (%c20{{.*}} : i32) {{.*}} {
+! CHECK: %[[DESIGNATE_READ:.*]] = hlfir.designate %[[DECLARE_A_RED]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: {{.*}} = fir.load %[[DESIGNATE_READ]] : !fir.ref<f32>
+! CHECK: %[[DESIGNATE_WRITE:.*]] = hlfir.designate %[[DECLARE_A_RED]]#0 ({{.*}}) : (!fir.box<!fir.array<?xf32>>, i64) -> !fir.ref<f32>
+! CHECK: hlfir.assign {{.*}} to %[[DESIGNATE_WRITE]] : f32, !fir.ref<f32>
+! CHECK: acc.yield
+! CHECK: }
+! CHECK: acc.yield
+! CHECK: }
+! CHECK: acc.yield
+! CHECK: }
+! CHECK: acc.copyout accVar(%[[COPYIN]] : !fir.box<!fir.array<?xf32>>) bounds(%[[BOUND0]]) to var(%[[DECLARE_A]]#0 : !fir.box<!fir.array<?xf32>>) {dataClause = #acc<data_clause acc_reduction>, implicit = true, name = "a(11:20)"}
+! CHECK: return
+! CHECK: }
>From ff59ade8b77629f6af95d1a3d93cfdb2ec7f5734 Mon Sep 17 00:00:00 2001
From: Susan Tan <zujunt at nvidia.com>
Date: Thu, 23 Jul 2026 12:46:26 -0700
Subject: [PATCH 4/4] add nyi
---
flang/lib/Lower/OpenACC.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index d2eb330dbdf20..7b2b6a49e788f 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -1169,13 +1169,13 @@ genReductions(const Fortran::parser::AccObjectListWithReduction &objectList,
mlir::acc::ReductionOperator mlirOp =
getReductionOperator(op, reductionTy, converter);
- if (designator) {
- Fortran::semantics::SomeExpr someExpr = *designator;
- if (Fortran::lower::detail::getRef<Fortran::evaluate::Component>(
- someExpr)) {
- TODO(operandLocation,
- "OpenACC reduction with component reference not yet supported");
- }
+ // getRef<Component> only matches a bare component reference (e.g. x%s).
+ // For a component array section (e.g. x%a(1:16)) the DataRef is an
+ // ArrayRef whose base is the Component, so use the same helper
+ // genDataOperandOperations relies on to detect both shapes.
+ if (extractComponentFromDesignator(designator)) {
+ TODO(operandLocation,
+ "OpenACC reduction with component reference not yet supported");
}
auto op = createDataEntryOp<mlir::acc::ReductionOp>(
More information about the flang-commits
mailing list