[flang-commits] [flang] ef7bfdc - [flang][OpenACC] Resolve associations before testing declare flags (#221346)
via flang-commits
flang-commits at lists.llvm.org
Fri Sep 4 22:34:43 PDT 2026
Author: yebinchon
Date: 2026-09-04T22:34:38-07:00
New Revision: ef7bfdcfd4e3b75db55b5d335e1cfca334d811ca
URL: https://github.com/llvm/llvm-project/commit/ef7bfdcfd4e3b75db55b5d335e1cfca334d811ca
DIFF: https://github.com/llvm/llvm-project/commit/ef7bfdcfd4e3b75db55b5d335e1cfca334d811ca.diff
LOG: [flang][OpenACC] Resolve associations before testing declare flags (#221346)
The OpenACC declare flags are set by semantics on a single symbol: the
one resolved in the scope containing the !$acc declare directive. Any
other scope naming the same entity reaches it through an association
symbol, and those symbols carry their own, empty flag sets.
The allocate and deallocate action helpers tested the symbol taken
straight from the ALLOCATE or DEALLOCATE statement. For an allocatable
declared in a host scope and allocated in an internal subprogram the
AccDeclare test
therefore failed, no acc.declare_action attribute was attached, and
ACCDeclareActionConversion had nothing to convert. The emitted recipes
were never called, so the device copy was neither created on allocation
nor deleted on deallocation.
Resolve to the ultimate symbol and pass it on. Forwarding the resolved
symbol is required because the deallocation attach helpers independently
re-test the data clause flags.
This matches the rest of the OpenACC lowering, which already resolves
before reading these flags. Recipe names are unaffected because
mangleName resolves associations itself before mangling.
---------
Co-authored-by: Yebin Chon <ychon at nvidia.com>
Added:
flang/test/Lower/OpenACC/acc-declare-host-associated-allocatable.f90
Modified:
flang/lib/Lower/Allocatable.cpp
Removed:
################################################################################
diff --git a/flang/lib/Lower/Allocatable.cpp b/flang/lib/Lower/Allocatable.cpp
index 5f79b77592307..5f10319ab0101 100644
--- a/flang/lib/Lower/Allocatable.cpp
+++ b/flang/lib/Lower/Allocatable.cpp
@@ -484,9 +484,9 @@ class AllocateStmtHelper {
void postAllocationAction(const Allocation &alloc,
const fir::MutableBoxValue &box) {
- if (alloc.getSymbol().test(Fortran::semantics::Symbol::Flag::AccDeclare))
- Fortran::lower::attachDeclarePostAllocAction(converter, builder,
- alloc.getSymbol());
+ auto &ult = alloc.getSymbol().GetUltimate();
+ if (ult.test(Fortran::semantics::Symbol::Flag::AccDeclare))
+ Fortran::lower::attachDeclarePostAllocAction(converter, builder, ult);
}
void setPinnedToFalse() {
@@ -929,16 +929,18 @@ static void preDeallocationAction(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder,
mlir::Value beginOpValue,
const Fortran::semantics::Symbol &sym) {
- if (sym.test(Fortran::semantics::Symbol::Flag::AccDeclare))
+ auto &ult = sym.GetUltimate();
+ if (ult.test(Fortran::semantics::Symbol::Flag::AccDeclare))
Fortran::lower::attachDeclarePreDeallocAction(converter, builder,
- beginOpValue, sym);
+ beginOpValue, ult);
}
static void postDeallocationAction(Fortran::lower::AbstractConverter &converter,
fir::FirOpBuilder &builder,
const Fortran::semantics::Symbol &sym) {
- if (sym.test(Fortran::semantics::Symbol::Flag::AccDeclare))
- Fortran::lower::attachDeclarePostDeallocAction(converter, builder, sym);
+ auto &ult = sym.GetUltimate();
+ if (ult.test(Fortran::semantics::Symbol::Flag::AccDeclare))
+ Fortran::lower::attachDeclarePostDeallocAction(converter, builder, ult);
}
static mlir::Value genCudaDeallocate(fir::FirOpBuilder &builder,
diff --git a/flang/test/Lower/OpenACC/acc-declare-host-associated-allocatable.f90 b/flang/test/Lower/OpenACC/acc-declare-host-associated-allocatable.f90
new file mode 100644
index 0000000000000..e3e2d9fbcdc35
--- /dev/null
+++ b/flang/test/Lower/OpenACC/acc-declare-host-associated-allocatable.f90
@@ -0,0 +1,63 @@
+! Test !$acc declare create on an allocatable that is allocated and deallocated
+! from an internal subprogram. The OpenACC flags are set on the host scope
+! symbol, so the host associated symbol seen at the ALLOCATE and DEALLOCATE
+! statements has to be resolved before the declare actions are attached.
+! Covers both the runtime call path (derived type) and the inlined path
+! (intrinsic type).
+
+! RUN: bbc -fopenacc -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc -fopenacc -emit-hlfir %s -o - | fir-opt --acc-declare-action-conversion | \
+! RUN: FileCheck %s --check-prefix=CONV
+
+program acc_declare_host_assoc
+ type domain_type
+ integer :: nvar
+ end type domain_type
+
+ type(domain_type), allocatable :: domains(:)
+ integer, allocatable :: data(:)
+ !$acc declare create(domains, data)
+
+ call init
+ call fini
+
+contains
+
+ subroutine init()
+ allocate(domains(10))
+ allocate(data(10))
+ end subroutine init
+
+ subroutine fini()
+ deallocate(domains)
+ deallocate(data)
+ end subroutine fini
+
+end program acc_declare_host_assoc
+
+! CHECK-LABEL: func.func private @_QFPinit()
+! CHECK: fir.call @_FortranAAllocatableAllocate({{.*}}) fastmath<contract> {acc.declare_action = #acc.declare_action<postAlloc = @_QFEdomains_acc_declare_post_alloc>}
+! CHECK: fir.allocmem !fir.array<?xi32>
+! CHECK: fir.store %{{.*}} to %{{.*}} {acc.declare_action = #acc.declare_action<postAlloc = @_QFEdata_acc_declare_post_alloc>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+
+! CHECK-LABEL: func.func private @_QFPfini()
+! CHECK: fir.call @_FortranAAllocatableDeallocate({{.*}}) fastmath<contract> {acc.declare_action = #acc.declare_action<preDealloc = @_QFEdomains_acc_declare_pre_dealloc, postDealloc = @_QFEdomains_acc_declare_post_dealloc>}
+! CHECK: fir.box_addr %{{.*}} {acc.declare_action = #acc.declare_action<preDealloc = @_QFEdata_acc_declare_pre_dealloc>} : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
+! CHECK: fir.freemem
+! CHECK: fir.store %{{.*}} to %{{.*}} {acc.declare_action = #acc.declare_action<postDealloc = @_QFEdata_acc_declare_post_dealloc>} : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
+
+! The attributes must be actionable: the conversion pass has to find each
+! recipe and insert the call next to the allocation or deallocation.
+
+! CONV-LABEL: func.func private @_QFPinit()
+! CONV: fir.call @_FortranAAllocatableAllocate(
+! CONV: fir.call @_QFEdomains_acc_declare_post_alloc(%{{.*}}) : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QFTdomain_type{nvar:i32}>>>>>) -> ()
+! CONV: fir.call @_QFEdata_acc_declare_post_alloc(%{{.*}}) : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> ()
+
+! CONV-LABEL: func.func private @_QFPfini()
+! CONV: fir.call @_QFEdomains_acc_declare_pre_dealloc(%{{.*}}) : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QFTdomain_type{nvar:i32}>>>>>) -> ()
+! CONV: fir.call @_FortranAAllocatableDeallocate(
+! CONV: fir.call @_QFEdomains_acc_declare_post_dealloc(%{{.*}}) : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.type<_QFTdomain_type{nvar:i32}>>>>>) -> ()
+! CONV: fir.call @_QFEdata_acc_declare_pre_dealloc(%{{.*}}) : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> ()
+! CONV: fir.freemem
+! CONV: fir.call @_QFEdata_acc_declare_post_dealloc(%{{.*}}) : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> ()
More information about the flang-commits
mailing list