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