Zhen Wang 07542af921
[flang][OpenMP][CUDA] Place privatized device allocatable descriptors in managed memory (#187114)
When an OpenMP private clause privatizes a CUDA Fortran allocatable
device array, the Fortran descriptor for the private copy must be
accessible from both the host and the GPU. Without this change, the
descriptor lives on the host stack (via the OpenMP runtime's
CreateAlloca), which a CUF kernel running on the GPU cannot
dereference—resulting in cudaErrorIllegalAddress.

This patch modifies the omp.private init/dealloc region generation in
PrivateReductionUtils.cpp with three changes:

1. Allocate the descriptor in managed memory
2. Set allocator_idx = 2 on the null fir.embox
3. Free the managed descriptor

Source example:
```
real(8), device, allocatable :: adev(:)

!$omp parallel private(adev)
  allocate(adev(10))
  !$cuf kernel do <<<*,*>>>
  do i = 1, 10
    adev(i) = 1.0d0
  end do
  deallocate(adev)
!$omp end parallel
```
IR before this change:
```
omp.private {type = private} @... : !fir.box<!fir.heap<!fir.array<?xf64>>> init {
^bb0(%arg0: !fir.ref<!fir.box<...>>, %arg1: !fir.ref<!fir.box<...>>):
    ...
    fir.if %3 {
      %5 = fir.embox %1(%4) : (...) -> !fir.box<...>          // no allocator_idx
      fir.store %5 to %arg1                                    // host-stack alloca
    }
    omp.yield(%arg1 : ...)                                     // yields host alloca
  } dealloc {
    ...
    fir.if %3 { fir.freemem %1 }
    omp.yield                                                  // no cuf.free
  }
```
IR after this change:
```
omp.private {type = private} @... : !fir.box<!fir.heap<!fir.array<?xf64>>> init {
^bb0(%arg0: !fir.ref<!fir.box<...>>, %arg1: !fir.ref<!fir.box<...>>):
    %0 = cuf.alloc !fir.box<...> {data_attr = #cuf.cuda<device>}  // managed memory
    ...
    fir.if %4 {
      %6 = fir.embox %2(%5) {allocator_idx = 2 : i32}             // cudaMalloc
      fir.store %6 to %0                                           // managed descriptor
    }
    omp.yield(%0 : ...)                                            // yields managed ptr
  } dealloc {
    ...
    fir.if %3 { fir.freemem %1 }
    cuf.free %arg0 : ... {data_attr = #cuf.cuda<device>}           // free managed desc
    omp.yield
  }
```

---------

Co-authored-by: Valentin Clement (バレンタイン クレメン) <clementval@gmail.com>
2026-03-17 21:24:49 +00:00
..