[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:06:06 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-semantics

Author: khaki3

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/205902.diff


3 Files Affected:

- (modified) flang/lib/Lower/OpenACC.cpp (+8-1) 
- (modified) flang/lib/Semantics/resolve-names.cpp (+22-4) 
- (modified) flang/test/Lower/OpenACC/acc-host-data-cuda-device.f90 (+16) 


``````````diff
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)

``````````

</details>


https://github.com/llvm/llvm-project/pull/205902


More information about the flang-commits mailing list