https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123282

            Bug ID: 123282
           Summary: [OpenACC/Fortran] Illegal memory access with derived
                    type component in repeated alloc/dealloc cycle
                    (order-dependent)
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: albert at tugraz dot at
  Target Milestone: ---

OpenACC produces illegal memory access on iteration 2 of an
allocate/enter_data/exit_data/deallocate cycle when a derived type
with allocatable component is used. Bug is order-dependent: only
triggers when a parallel loop not using the struct runs before
a loop that does use it.

Reproducer:

module m
    use, intrinsic :: iso_fortran_env, only: dp => real64
    type :: t
        real(dp), allocatable :: c(:)
    end type
end module

program p
    use m
    implicit none
    type(t) :: s
    real(dp), allocatable :: w1(:,:,:), w2(:,:,:)
    integer :: i, iter

    do iter = 1, 3
        allocate(s%c(8), w1(8,8,0:1), w2(8,8,0:1))
        !$acc enter data create(s%c, w1, w2)

        !$acc parallel loop present(w1, w2)
        do i = 1, 8
            w2(1,i,0) = w1(1,i,0)
        end do

        !$acc parallel loop present(w1, s%c)
        do i = 1, 8
            s%c(i) = w1(1,i,0)
        end do

        !$acc exit data delete(w1, w2, s%c)
        deallocate(w1, w2, s%c)
    end do
end program

BUILD: gfortran -fopenacc -foffload=nvptx-none mre.f90 -o mre
ERROR: libgomp: cuStreamSynchronize error: an illegal memory access was
encountered



Using -fdump-tree-omplower shows asymmetric struct handling:

  enter data: map(struct:s [len: 1]) map(to:s.c ...) ...
  exit data:  map(release:s.c ...) ...  [NO map(struct:s)]

GOMP_MAP_STRUCT is stripped from OACC_EXIT_DATA in gimplify.cc:15949-15955,
introduced by commit 1afc4672561a (2020-05-20, Thomas Schwinge):

  [OpenACC 'exit data'] Strip 'GOMP_MAP_STRUCT' mappings
  These are not itself necessary for OpenACC 'exit data' directives...

The assumption was GOMP_MAP_STRUCT is a no-op. However, enter_data creates
struct state in the runtime splay tree that isn't cleaned up without the
corresponding struct on exit_data, causing stale state in repeated cycles.

FIX

Remove OACC_EXIT_DATA from the condition that strips GOMP_MAP_STRUCT
(keep stripping for OMP_TARGET_EXIT_DATA as OpenMP requires):

  if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_STRUCT ...)
-     && (code == OMP_TARGET_EXIT_DATA || code == OACC_EXIT_DATA))
+     && code == OMP_TARGET_EXIT_DATA)

TESTED

gfortran 16.0.0 nvptx: FAIL -> PASS with fix
gfortran 16.0.0 host:  PASS
nvfortran 25.1:        PASS

Reply via email to