[flang-commits] [flang] c9ab97f - [flang][acc] Fix cache directive with mapped component (#179335)
via flang-commits
flang-commits at lists.llvm.org
Tue Feb 3 02:05:36 PST 2026
Author: khaki3
Date: 2026-02-03T10:05:31Z
New Revision: c9ab97ff9569842c2bc91e140e6ab24a5fda0351
URL: https://github.com/llvm/llvm-project/commit/c9ab97ff9569842c2bc91e140e6ab24a5fda0351
DIFF: https://github.com/llvm/llvm-project/commit/c9ab97ff9569842c2bc91e140e6ab24a5fda0351.diff
LOG: [flang][acc] Fix cache directive with mapped component (#179335)
When a derived type component is mapped via a data clause (e.g.,
`copyin(data%A(...))`), the base address inside the parallel region
comes from an `hlfir.declare` op (for the mapped address) instead of
an `hlfir.designate` op. Use `FortranVariableOpInterface` to extract
shape/typeparams/attrs, which works for both cases since both ops
implement this interface.
Added:
Modified:
flang/lib/Lower/OpenACC.cpp
flang/test/Lower/OpenACC/acc-cache.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 133cc973897af..45420a1b720c9 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -4297,20 +4297,26 @@ genACC(Fortran::lower::AbstractConverter &converter,
fir::substBase(hostExv, cacheOp.getAccVar());
converter.bindSymbol(symbol, cacheExv);
} else {
- // Must be a derived type component reference.
+ // Derived type component reference.
assert(designator && "expected designator for non-symbol cache operand");
std::optional<Fortran::evaluate::Component> componentRef =
extractComponentFromDesignator(designator);
assert(componentRef &&
"expected component reference for derived type cache operand");
- // Component references are lowered to designate operations.
- auto designate = base.getDefiningOp<hlfir::DesignateOp>();
- assert(designate && "expected designate op for component reference");
+ // When component is mapped via a data clause, base may be a declare op
+ // instead of a designate op.
+ auto varIface = base.getDefiningOp<fir::FortranVariableOpInterface>();
+ assert(varIface &&
+ "expected FortranVariableOpInterface for component reference");
+ fir::FortranVariableFlagsAttr attrs;
+ if (auto fortranAttrs = varIface.getFortranAttrs())
+ attrs = fir::FortranVariableFlagsAttr::get(builder.getContext(),
+ *fortranAttrs);
auto declareOp = hlfir::DeclareOp::create(
builder, operandLocation, cacheOp.getAccVar(), asFortran.str(),
- designate.getShape(), designate.getTypeparams(),
+ varIface.getShape(), varIface.getExplicitTypeParams(),
/*dummyScope=*/nullptr, /*storage=*/nullptr,
- /*storageOffset=*/0, designate.getFortranAttrsAttr());
+ /*storageOffset=*/0, attrs);
converter.getSymbolMap().addComponentOverride(*componentRef, declareOp);
}
}
diff --git a/flang/test/Lower/OpenACC/acc-cache.f90 b/flang/test/Lower/OpenACC/acc-cache.f90
index 22dd0a84aee8a..36874d3c21cdb 100644
--- a/flang/test/Lower/OpenACC/acc-cache.f90
+++ b/flang/test/Lower/OpenACC/acc-cache.f90
@@ -638,6 +638,110 @@ subroutine test_cache_nested_derived_type()
! CHECK: acc.yield
end subroutine
+! Test cache with allocatable component in combined construct
+! CHECK-LABEL: func.func @_QPtest_cache_combined_allocatable(
+subroutine test_cache_combined_allocatable(data, C, M)
+ type :: dt
+ real, dimension(:), allocatable :: A
+ end type
+
+ type(dt), intent(inout) :: data
+ real, dimension(:), intent(out) :: C
+ integer, intent(in) :: M
+ integer :: i
+
+ !$acc parallel loop gang vector copyin(data, data%A(-3:M+4)) copyout(C(1:M))
+ do i = 1, M
+ !$acc cache(data%A(i-4:i+4))
+ C(i) = data%A(i)
+ end do
+
+! CHECK: acc.parallel {{.*}} {
+! CHECK: acc.loop
+! CHECK: acc.cache varPtr(%{{.*}}) bounds(%{{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {name = "data%a(i-4_4:i+4_4)", structured = false}
+! CHECK: hlfir.declare %{{.*}} {{{.*}}uniq_name = "data%a(i-4_4:i+4_4)"}
+! CHECK: acc.yield
+end subroutine
+
+! Test cache with copy of whole struct (not explicit component copyin)
+! CHECK-LABEL: func.func @_QPtest_cache_parallel_copy_struct(
+subroutine test_cache_parallel_copy_struct(data, M)
+ type :: dt
+ real, dimension(:), allocatable :: A
+ end type
+
+ type(dt), intent(inout) :: data
+ integer, intent(in) :: M
+ real :: r
+ integer :: i
+
+ !$acc parallel loop copy(data)
+ do i = 1, M
+ !$acc cache(data%A(i))
+ r = data%A(i)
+ end do
+
+! CHECK: acc.parallel {{.*}} {
+! CHECK: acc.loop
+! CHECK: acc.cache varPtr(%{{.*}}) bounds(%{{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {name = "data%a(i)", structured = false}
+! CHECK: hlfir.declare %{{.*}} {{{.*}}uniq_name = "data%a(i)"}
+! CHECK: acc.yield
+end subroutine
+
+! Test cache with nested derived type in parallel loop with copyin
+! CHECK-LABEL: func.func @_QPtest_cache_nested_parallel(
+subroutine test_cache_nested_parallel(obj, N)
+ type :: inner
+ real, dimension(:), allocatable :: arr
+ end type
+
+ type :: outer
+ type(inner) :: in
+ end type
+
+ type(outer), intent(inout) :: obj
+ integer, intent(in) :: N
+ real :: r
+ integer :: i
+
+ !$acc parallel loop copyin(obj%in%arr(1:N))
+ do i = 1, N
+ !$acc cache(obj%in%arr(i))
+ r = obj%in%arr(i)
+ end do
+
+! CHECK: acc.parallel {{.*}} {
+! CHECK: acc.loop
+! CHECK: acc.cache varPtr(%{{.*}}) bounds(%{{.*}}) -> !fir.ref<!fir.box<!fir.heap<!fir.array<?xf32>>>> {name = "obj%in%arr(i)", structured = false}
+! CHECK: hlfir.declare %{{.*}} {{{.*}}uniq_name = "obj%in%arr(i)"}
+! CHECK: acc.yield
+end subroutine
+
+! Test cache with explicit shape component in parallel loop with copyin
+! CHECK-LABEL: func.func @_QPtest_cache_explicit_shape_comp(
+subroutine test_cache_explicit_shape_comp(data, C, M)
+ type :: dt
+ real, dimension(10) :: A
+ end type
+
+ type(dt), intent(inout) :: data
+ real, dimension(:), intent(out) :: C
+ integer, intent(in) :: M
+ integer :: i
+
+ !$acc parallel loop gang vector copyin(data, data%A(1:M)) copyout(C(1:M))
+ do i = 1, M
+ !$acc cache(data%A(i:i+4))
+ C(i) = data%A(i)
+ end do
+
+! CHECK: acc.parallel {{.*}} {
+! CHECK: acc.loop
+! CHECK: acc.cache varPtr(%{{.*}}) bounds(%{{.*}}) -> !fir.ref<!fir.array<10xf32>> {name = "data%a(i:i+4_4)", structured = false}
+! CHECK: hlfir.declare %{{.*}}(%{{.*}}) {uniq_name = "data%a(i:i+4_4)"}
+! CHECK: acc.yield
+end subroutine
+
! Test cache with temporary in designator bounds - verifies local statement context
! doesn't cause issues with temporary cleanup
! CHECK-LABEL: func.func @_QPtest_cache_temp_in_designator(
More information about the flang-commits
mailing list