Skip to content

Commit 9da250c

Browse files
authored
[flang][cuda][openacc] Fix OpenACC use_device host association symbol copies (llvm#194705)
When a use_device object comes from host association, the OpenACC construct scope may already contain a HostAssocDetails symbol. Reusing that symbol prevents semantics from applying the CUDA DEVICE attribute, because the copied symbol is not an object entity. The fix materializes the expected host-associated symbol in the containing scope, then replaces the OpenACC-scope symbol with an ObjectEntityDetails copy that can carry the device attribute. This allows generic resolution and lowering to see the device version inside the host_data construct while preserving the host-associated binding needed by lowering.
1 parent 6283dec commit 9da250c

2 files changed

Lines changed: 53 additions & 11 deletions

File tree

flang/lib/Semantics/resolve-names.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,7 @@ class AccVisitor : public virtual DeclarationVisitor {
14801480
llvm::ArrayRef<SourceName> componentPath, parser::Designator &designator);
14811481

14821482
private:
1483+
Symbol *CopyUseDeviceSymbol(const Symbol &symbol);
14831484
SemanticsContext &context_;
14841485
};
14851486

@@ -1617,30 +1618,47 @@ void AccVisitor::CopySymbolWithDevice(const parser::Name *name) {
16171618
// New symbols are created for those appearing in the use_device clause.
16181619
// These new symbols get the CUDA device attribute.
16191620
if (name && name->symbol) {
1620-
Symbol *copy{currScope().CopySymbol(name->symbol->GetUltimate())};
1621+
Symbol *copy{CopyUseDeviceSymbol(*name->symbol)};
16211622
if (copy) {
1622-
if (auto *object{copy->GetUltimate().detailsIf<ObjectEntityDetails>()}) {
1623+
if (auto *object{copy->detailsIf<ObjectEntityDetails>()}) {
16231624
object->set_cudaDataAttr(common::CUDADataAttr::Device);
16241625
}
1625-
} else {
1626-
copy = FindInScope(currScope(), name->symbol->GetUltimate().name());
1627-
}
1628-
if (copy) {
16291626
name->symbol = copy;
16301627
}
16311628
}
16321629
}
16331630

1631+
Symbol *AccVisitor::CopyUseDeviceSymbol(const Symbol &symbol) {
1632+
const Symbol &ultimate{symbol.GetUltimate()};
1633+
Symbol *copy{currScope().CopySymbol(ultimate)};
1634+
if (!copy) {
1635+
copy = FindInScope(currScope(), ultimate.name());
1636+
}
1637+
if (copy && copy->has<HostAssocDetails>()) {
1638+
if (const auto *hostAssoc{copy->detailsIf<HostAssocDetails>()};
1639+
hostAssoc && copy->owner().kind() == Scope::Kind::OpenACCConstruct) {
1640+
Scope &hostScope{currScope().parent()};
1641+
if (!FindInScope(hostScope, ultimate.name())) {
1642+
hostScope.CopySymbol(*copy);
1643+
}
1644+
}
1645+
if (const auto *object{ultimate.detailsIf<ObjectEntityDetails>()}) {
1646+
currScope().erase(copy->name());
1647+
auto pair{currScope().try_emplace(
1648+
ultimate.name(), ultimate.attrs(), ObjectEntityDetails{*object})};
1649+
copy = &*pair.first->second;
1650+
copy->flags() = ultimate.flags();
1651+
}
1652+
}
1653+
return copy;
1654+
}
1655+
16341656
void AccVisitor::CopySymbolWithDeviceStructurePath(const parser::Name *baseName,
16351657
llvm::ArrayRef<SourceName> componentPath, parser::Designator &designator) {
16361658
if (!baseName || !baseName->symbol || componentPath.empty()) {
16371659
return;
16381660
}
1639-
const Symbol &orig{*baseName->symbol};
1640-
Symbol *copy{currScope().CopySymbol(orig)};
1641-
if (!copy) {
1642-
copy = FindInScope(currScope(), baseName->symbol->name());
1643-
}
1661+
Symbol *copy{CopyUseDeviceSymbol(*baseName->symbol)};
16441662
if (!copy) {
16451663
return;
16461664
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
! RUN: bbc -fopenacc -fcuda -emit-hlfir %s -o - | FileCheck %s
2+
3+
interface something
4+
subroutine proc_device(x)
5+
real(4), device :: x(100)
6+
end subroutine
7+
subroutine proc_host(x)
8+
real(4) :: x(100)
9+
end subroutine
10+
end interface
11+
12+
real(4) :: a(100)
13+
!$acc declare copy(a)
14+
15+
call test_simple()
16+
contains
17+
subroutine test_simple
18+
!$acc host_data use_device(a)
19+
call something(a)
20+
!$acc end host_data
21+
end subroutine
22+
end
23+
24+
! CHECK: fir.call @_QPproc_device

0 commit comments

Comments
 (0)