[flang-commits] [flang] [flang][cuda][acc] Fix use_device device attribute for USE-renamed variables (PR #205902)
via flang-commits
flang-commits at lists.llvm.org
Thu Jun 25 13:05:27 PDT 2026
https://github.com/khaki3 created https://github.com/llvm/llvm-project/pull/205902
Example:
```fortran
module m
complex(8), allocatable, pinned :: v(:,:)
interface callee
subroutine callee_x(x, n)
complex(8), device :: x(:,:)
integer :: n
end subroutine
end interface
end module
subroutine driver(n)
use m, only : callee, v_renamed => v
integer :: n
!$acc host_data use_device(v_renamed)
call callee(v_renamed, n)
!$acc end host_data
end subroutine
```
In this code, the `use_device` device copy was keyed under the ultimate name (`v`), so `v_renamed` resolved to the host (PINNED) symbol and generic resolution failed.
Fix: key the device copy under the local renamed name, and resolve its host binding in lowering via the enclosing scope's ultimate.
>From 0554afddc85603f254ee21fc40d01a58ba1dc6b2 Mon Sep 17 00:00:00 2001
From: Kazuaki Matsumura <kmatsumura at nvidia.com>
Date: Thu, 25 Jun 2026 12:01:15 -0700
Subject: [PATCH] [flang][cuda][openacc] Propagate device attribute through
host_data use_device for USE-renamed variables
When a USE-renamed variable appears in an OpenACC host_data use_device
clause, semantics created the device copy keyed under the ultimate
symbol's name instead of the local (renamed) name. References at the call
site used the renamed name and therefore resolved to the host symbol,
causing generic resolution to fail (e.g. DEVICE dummy vs PINNED actual).
Key the use_device device copy under the as-referenced local name, and in
lowering resolve the host symbol via the enclosing scope's ultimate
(module) name so the binding is found for USE-renamed variables.
---
flang/lib/Lower/OpenACC.cpp | 9 ++++++-
flang/lib/Semantics/resolve-names.cpp | 26 ++++++++++++++++---
.../OpenACC/acc-host-data-cuda-device.f90 | 16 ++++++++++++
3 files changed, 46 insertions(+), 5 deletions(-)
diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp
index 5fbc678e6d0ae..9ce58e8b1662c 100644
--- a/flang/lib/Lower/OpenACC.cpp
+++ b/flang/lib/Lower/OpenACC.cpp
@@ -3169,7 +3169,14 @@ genACCHostDataOp(Fortran::lower::AbstractConverter &converter,
if (newSym) {
const Fortran::semantics::Symbol *origSym =
localSymbols.lookupSymbolByName(newSym->name().ToString());
- if (origSym)
+ if (!origSym) {
+ // For a USE-renamed variable the host symbol is mapped under its
+ // ultimate (module) name, so resolve it via the enclosing scope.
+ if (const Fortran::semantics::Symbol *hostSym =
+ newSym->owner().parent().FindSymbol(newSym->name()))
+ origSym = &hostSym->GetUltimate();
+ }
+ if (origSym && localSymbols.lookupSymbol(*origSym))
localSymbols.copySymbolBinding(*origSym, *newSym);
}
}
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 11e24a5e1cccb..c3286035c8641 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1635,22 +1635,40 @@ void AccVisitor::CopySymbolWithDevice(const parser::Name *name) {
Symbol *AccVisitor::CopyUseDeviceSymbol(const Symbol &symbol) {
const Symbol &ultimate{symbol.GetUltimate()};
- Symbol *copy{currScope().CopySymbol(ultimate)};
+ // Key the device copy under the name as referenced here, which differs from
+ // the ultimate symbol's name for a USE-renamed variable, so that references
+ // inside the construct resolve to this copy rather than the host symbol.
+ const SourceName localName{symbol.name()};
+ Symbol *copy{nullptr};
+ // CopySymbol would key the copy under the ultimate's name; only use it when
+ // that matches the local name, otherwise reuse the host-associated symbol.
+ if (localName == ultimate.name()) {
+ copy = currScope().CopySymbol(ultimate);
+ }
if (!copy) {
- copy = FindInScope(currScope(), ultimate.name());
+ copy = FindInScope(currScope(), localName);
}
if (copy && copy->has<HostAssocDetails>()) {
if (const auto *hostAssoc{copy->detailsIf<HostAssocDetails>()};
hostAssoc && copy->owner().kind() == Scope::Kind::OpenACCConstruct) {
Scope &hostScope{currScope().parent()};
- if (!FindInScope(hostScope, ultimate.name())) {
+ if (!FindInScope(hostScope, localName)) {
hostScope.CopySymbol(*copy);
}
}
if (const auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
currScope().erase(copy->name());
auto pair{currScope().try_emplace(
- ultimate.name(), ultimate.attrs(), ObjectEntityDetails{*object})};
+ localName, ultimate.attrs(), ObjectEntityDetails{*object})};
+ copy = &*pair.first->second;
+ copy->flags() = ultimate.flags();
+ }
+ } else if (!copy) {
+ // USE-renamed object with no host-association symbol in this scope: key an
+ // object-entity copy under the local name (CopySymbol cannot rename).
+ if (const auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
+ auto pair{currScope().try_emplace(
+ localName, ultimate.attrs(), ObjectEntityDetails{*object})};
copy = &*pair.first->second;
copy->flags() = ultimate.flags();
}
diff --git a/flang/test/Lower/OpenACC/acc-host-data-cuda-device.f90 b/flang/test/Lower/OpenACC/acc-host-data-cuda-device.f90
index 445de76bd8a94..fb06a4eda6d77 100644
--- a/flang/test/Lower/OpenACC/acc-host-data-cuda-device.f90
+++ b/flang/test/Lower/OpenACC/acc-host-data-cuda-device.f90
@@ -157,3 +157,19 @@ subroutine test_use_details()
! CHECK: fir.address_of(@_QP__host_sub)
! CHECK: fir.address_of(@_QP__device_sub)
! CHECK: fir.address_of(@_QP__host_sub)
+
+! The device attribute must propagate through use_device for a USE-renamed
+! variable, so generic resolution selects the device-specific procedure.
+subroutine test_use_rename()
+ use m, only: doit, renamed => pinned_real
+ call doit(renamed)
+ !$acc host_data use_device(renamed)
+ call doit(renamed)
+ !$acc end host_data
+ call doit(renamed)
+end subroutine
+
+! CHECK-LABEL: func.func @_QPtest_use_rename
+! CHECK: fir.address_of(@_QP__host_sub)
+! CHECK: fir.address_of(@_QP__device_sub)
+! CHECK: fir.address_of(@_QP__host_sub)
More information about the flang-commits
mailing list