[flang-commits] [flang] f6f08fa - [flang][cuda] Use managed allocation for saved locals (#210133)

via flang-commits flang-commits at lists.llvm.org
Thu Jul 16 13:53:32 PDT 2026


Author: Matsu
Date: 2026-07-16T20:53:27Z
New Revision: f6f08fa7e5d56aa07f9ebc51500f2c9fd6df8e1b

URL: https://github.com/llvm/llvm-project/commit/f6f08fa7e5d56aa07f9ebc51500f2c9fd6df8e1b
DIFF: https://github.com/llvm/llvm-project/commit/f6f08fa7e5d56aa07f9ebc51500f2c9fd6df8e1b.diff

LOG: [flang][cuda] Use managed allocation for saved locals (#210133)

Example:
```fortran
subroutine work
  real, allocatable, save :: q(:)
  allocate(q(10))
end
```

`SAVE` gives the local allocatable descriptor static storage. Implicitly
attributing it as Unified causes allocation to look it up as a
registered CUDA global, but no device symbol is registered for the
descriptor.

Fix: use Managed attribution for saved subprogram-local allocatables and
pointers, avoiding the invalid CUDA symbol lookup.

Added: 
    

Modified: 
    flang/lib/Semantics/resolve-names.cpp
    flang/test/Lower/CUDA/cuda-implicit-managed-alloc.cuf

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index cdf81e7871f36..e83fc179ecf40 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -10619,7 +10619,9 @@ void DeclarationVisitor::SetImplicitCUDADataAttr(Symbol &symbol) {
   // COMMON objects may not carry managed/unified attributes.
   if (cudaEnabled && (cudaManaged || cudaUnified) && !object->commonBlock()) {
     const Scope &owner{symbol.owner()};
-    const bool unifiedAllowed{!IsCUDADeviceContext(&owner) &&
+    const bool isSavedLocal{
+        owner.kind() == Scope::Kind::Subprogram && IsSaved(symbol)};
+    const bool unifiedAllowed{!isSavedLocal && !IsCUDADeviceContext(&owner) &&
         (owner.IsDerivedType() || owner.kind() == Scope::Kind::MainProgram ||
             owner.kind() == Scope::Kind::Subprogram)};
     object->set_cudaDataAttr(cudaUnified && unifiedAllowed

diff  --git a/flang/test/Lower/CUDA/cuda-implicit-managed-alloc.cuf b/flang/test/Lower/CUDA/cuda-implicit-managed-alloc.cuf
index 378eb8698d3c6..e3185ae81a843 100644
--- a/flang/test/Lower/CUDA/cuda-implicit-managed-alloc.cuf
+++ b/flang/test/Lower/CUDA/cuda-implicit-managed-alloc.cuf
@@ -20,6 +20,8 @@ contains
   subroutine mod_sub()
     real, allocatable :: loc_arr(:)
     real, pointer :: loc_ptr(:)
+    real, allocatable, save :: saved_arr(:)
+    real, pointer, save :: saved_ptr(:)
   end subroutine
   subroutine common_sub()
     real, pointer :: com_ptr(:)
@@ -38,6 +40,13 @@ end program
 ! MAN: hlfir.declare {{.*}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmFmod_subEloc_arr"}
 ! MAN: hlfir.declare {{.*}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFmod_subEloc_ptr"}
 
+! Saved subprogram locals use Managed because their static descriptors cannot
+! be registered as Unified device symbols.
+! UNI: hlfir.declare {{.*}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmFmod_subEsaved_arr"}
+! UNI: hlfir.declare {{.*}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFmod_subEsaved_ptr"}
+! MAN: hlfir.declare {{.*}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QMmFmod_subEsaved_arr"}
+! MAN: hlfir.declare {{.*}} {data_attr = #cuf.cuda<managed>, fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFmod_subEsaved_ptr"}
+
 ! COMMON-block pointer: unattributed, CUDA attributes may not appear in COMMON.
 ! UNI: hlfir.declare {{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFcommon_subEcom_ptr"}
 ! MAN: hlfir.declare {{.*}} {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMmFcommon_subEcom_ptr"}
@@ -54,9 +63,18 @@ end program
 ! MAN: fir.global @_QMmEmod_arr {data_attr = #cuf.cuda<managed>}
 ! MAN: fir.global @_QMmEmod_ptr {data_attr = #cuf.cuda<managed>}
 
+! UNI: fir.global internal @_QMmFmod_subEsaved_arr {data_attr = #cuf.cuda<managed>}
+! UNI: fir.global internal @_QMmFmod_subEsaved_ptr {data_attr = #cuf.cuda<managed>}
+! MAN: fir.global internal @_QMmFmod_subEsaved_arr {data_attr = #cuf.cuda<managed>}
+! MAN: fir.global internal @_QMmFmod_subEsaved_ptr {data_attr = #cuf.cuda<managed>}
+
 ! Derived-type components: Unified under -gpu=unified, Managed under
 ! -gpu=managed. Checked via the symbol table.
 ! UNI-SYM: comp_arr, ALLOCATABLE {{.*}} cudaDataAttr: Unified
 ! UNI-SYM: comp_ptr, POINTER {{.*}} cudaDataAttr: Unified
 ! MAN-SYM: comp_arr, ALLOCATABLE {{.*}} cudaDataAttr: Managed
 ! MAN-SYM: comp_ptr, POINTER {{.*}} cudaDataAttr: Managed
+! UNI-SYM: saved_arr, ALLOCATABLE, SAVE {{.*}} cudaDataAttr: Managed
+! UNI-SYM: saved_ptr, POINTER, SAVE {{.*}} cudaDataAttr: Managed
+! MAN-SYM: saved_arr, ALLOCATABLE, SAVE {{.*}} cudaDataAttr: Managed
+! MAN-SYM: saved_ptr, POINTER, SAVE {{.*}} cudaDataAttr: Managed


        


More information about the flang-commits mailing list