[flang-commits] [flang] [flang][cuda] Back `ALLOCATABLE` components with managed memory under `-gpu=mem:managed` (PR #223087)
Kareem Ergawy via flang-commits
flang-commits at lists.llvm.org
Mon Sep 14 03:37:46 PDT 2026
ergawy wrote:
> For managed we implicitly add the attribute in semantic. We should do the same for components.
Thanks for taking a look Valentin. I tried that in this experimental branch: https://github.com/llvm/llvm-project/commits/users/ergawy/managed-components-semantic-experiment/.
To test these changes, I added logs to the compiler to see how it behaves when one component is allocatable and one is not. The test is the following:
```probe.c
#include <cuda_runtime.h>
#include <stdio.h>
void probe_ptr(const void *p, const char *tag) {
struct cudaPointerAttributes a;
cudaError_t e = cudaPointerGetAttributes(&a, p);
if (e != cudaSuccess) {
printf(" %-10s ptr=%p cudaPointerGetAttributes FAILED: %d (%s)\n", tag, p,
(int)e, cudaGetErrorString(e));
/* Clear the sticky error so later CUDA calls still work. */
cudaGetLastError();
return;
}
const char *k = "?";
switch (a.type) {
case cudaMemoryTypeUnregistered:
k = "UNREGISTERED (plain host malloc)";
break;
case cudaMemoryTypeHost:
k = "HOST (pinned)";
break;
case cudaMemoryTypeDevice:
k = "DEVICE";
break;
case cudaMemoryTypeManaged:
k = "MANAGED";
break;
}
printf(" %-10s ptr=%p type=%d %-34s device=%d devPtr=%p hostPtr=%p\n", tag,
p, (int)a.type, k, a.device, a.devicePointer, a.hostPointer);
}
```
```probe.f90
module m
implicit none
type :: t
real :: fixed(4) ! must stay UNREGISTERED (plain host)
real, allocatable :: alc(:) ! its data must be MANAGED
end type t
end module m
program p
use iso_c_binding
use m
implicit none
interface
subroutine probe_ptr(ptr, tag) bind(C, name="probe_ptr")
import :: c_ptr, c_char
type(c_ptr), value :: ptr
character(kind=c_char), dimension(*) :: tag
end subroutine probe_ptr
end interface
type(t), target :: obj
allocate(obj%alc(64))
call probe_ptr(c_loc(obj%fixed), "fixed -> want UNREGISTERED"//c_null_char)
call probe_ptr(c_loc(obj%alc), "alc -> want MANAGED"//c_null_char)
end program p
```
---
Compiler output:
```shell
>>>> ComponentDecl type='t' comp='fixed' allocatable=0 pointer=0 existingAttr=<none> ==> left alone
>>>> ComponentDecl type='t' comp='alc' allocatable=1 pointer=0 existingAttr=<none> ==> SET Managed
>>>> needCUDAAlloc object='obj' objectAttr=<none> type='t'
==> true, because component 'alc' is device-allocatable.
The WHOLE object goes to cuf.alloc, including its non-allocatable components.
```
So eventually the whole object is marked for managed memory even though we only attribute `alc` in semantics.
And runtime logs show this is actually the case too:
```shell
fixed -> want UNREGISTERED ptr=0x7ff46e000000 type=3 MANAGED device=0 devPtr=0x7ff46e000000 hostPtr=0x7ff46e000000
alc -> want MANAGED ptr=0x7ff442000080 type=3 MANAGED device=0 devPtr=0x7ff442000080 hostPtr=0x7ff442000080
```
---
I think this incorrect behavior. Therefore, I think the "allocatable-local" approach taken in this PR is a more proper one. Let me know if I missed something or misunderstood your suggestion.
https://github.com/llvm/llvm-project/pull/223087
More information about the flang-commits
mailing list