Files
gcc-reflection/libgomp/testsuite/libgomp.fortran/map-alloc-comp-8.f90
Tobias Burnus 99cd28c473 Fortran/OpenMP: Support automatic mapping allocatable components (deep mapping)
When mapping an allocatable variable (or derived-type component), explicitly
or implicitly, all its allocated allocatable components will automatically be
mapped. The patch implements the target hooks, added for this feature to
omp-low.cc with commit r15-3895-ge4a58b6f28383c.

Namely, there is a check whether there are allocatable components at all:
gfc_omp_deep_mapping_p. Then gfc_omp_deep_mapping_cnt, counting the number
of required mappings; this is a dynamic value as it depends on array
bounds and whether an allocatable is allocated or not.
And, finally, the actual mapping: gfc_omp_deep_mapping.

Polymorphic variables are partially supported: the mapping of the _data
component is fully supported, but only components of the declared type
are processed for additional allocatables. Additionally, _vptr is not
touched. This means that everything needing _vtab information requires
unified shared memory; in particular, _size data is required when
accessing elements of polymorphic arrays.
However, for scalar arrays, accessing components of the declare type
should work just fine.

As polymorphic variables are not (really) supported and OpenMP 6
explicitly disallows them, there is now a warning (-Wopenmp) when
they are encountered. Unlimited polymorphics are rejected (error).

Additionally, PRIVATE and FIRSTPRIVATE are not quite supported for
allocatable components, polymorphic components and as polymorphic
variable. Thus, those are now rejected as well.

gcc/fortran/ChangeLog:

	* f95-lang.cc (LANG_HOOKS_OMP_DEEP_MAPPING,
	LANG_HOOKS_OMP_DEEP_MAPPING_P, LANG_HOOKS_OMP_DEEP_MAPPING_CNT):
	Define.
	* openmp.cc (gfc_match_omp_clause_reduction): Fix location setting.
	(resolve_omp_clauses): Permit allocatable components, reject
	them and polymorphic variables in PRIVATE/FIRSTPRIVATE.
	* trans-decl.cc (add_clause): Set clause location.
	* trans-openmp.cc (gfc_has_alloc_comps): Add ptr_ok and
	shallow_alloc_only Boolean arguments.
	(gfc_omp_replace_alloc_by_to_mapping): New.
	(gfc_omp_private_outer_ref, gfc_walk_alloc_comps,
	gfc_omp_clause_default_ctor, gfc_omp_clause_copy_ctor,
	gfc_omp_clause_assign_op, gfc_omp_clause_dtor): Update call to it.
	(gfc_omp_finish_clause): Minor cleanups, improve location data,
	handle allocatable components.
	(gfc_omp_deep_mapping_map, gfc_omp_deep_mapping_item,
	gfc_omp_deep_mapping_comps, gfc_omp_gen_simple_loop,
	gfc_omp_get_array_size, gfc_omp_elmental_loop,
	gfc_omp_deep_map_kind_p, gfc_omp_deep_mapping_int_p,
	gfc_omp_deep_mapping_p, gfc_omp_deep_mapping_do,
	gfc_omp_deep_mapping_cnt, gfc_omp_deep_mapping): New.
	(gfc_trans_omp_array_section): Save array descriptor in case
	deep-mapping lang hook will need it.
	(gfc_trans_omp_clauses): Likewise; use better clause location data.
	* trans.h (gfc_omp_deep_mapping_p, gfc_omp_deep_mapping_cnt,
	gfc_omp_deep_mapping): Add function prototypes.

libgomp/ChangeLog:

	* libgomp.texi (5.0 Impl. Status): Mark mapping alloc comps as 'Y'.
	* testsuite/libgomp.fortran/allocatable-comp.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-3.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-4.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-5.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-6.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-7.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-8.f90: New test.
	* testsuite/libgomp.fortran/map-alloc-comp-9.f90: New test.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/map-alloc-comp-1.f90: Remove dg-error.
	* gfortran.dg/gomp/polymorphic-mapping-2.f90: Update warn wording.
	* gfortran.dg/gomp/polymorphic-mapping.f90: Change expected
	diagnostic; some tests moved to ...
	* gfortran.dg/gomp/polymorphic-mapping-1.f90: ... here as new test.
	* gfortran.dg/gomp/polymorphic-mapping-3.f90: New test.
	* gfortran.dg/gomp/polymorphic-mapping-4.f90: New test.
	* gfortran.dg/gomp/polymorphic-mapping-5.f90: New test.
2025-04-15 16:42:42 +02:00

269 lines
8.5 KiB
Fortran

module m
implicit none (type, external)
type t
integer, allocatable :: A(:)
end type t
type t2
type(t), allocatable :: vT
integer, allocatable :: x
end type t2
contains
subroutine test_alloc()
type(t) :: var
type(t), allocatable :: var2
allocate(var2)
allocate(var%A(4), var2%A(5))
!$omp target enter data map(alloc: var, var2)
!$omp target
if (.not. allocated(Var2)) stop 1
if (.not. allocated(Var%A)) stop 2
if (.not. allocated(Var2%A)) stop 3
if (lbound(var%A, 1) /= 1 .or. ubound(var%A, 1) /= 4) stop 4
if (lbound(var2%A, 1) /= 1 .or. ubound(var2%A, 1) /= 5) stop 5
var%A = [1,2,3,4]
var2%A = [11,22,33,44,55]
!$omp end target
!$omp target exit data map(from: var, var2)
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%A)) error stop
if (.not. allocated(Var2%A)) error stop
if (lbound(var%A, 1) /= 1 .or. ubound(var%A, 1) /= 4) error stop
if (lbound(var2%A, 1) /= 1 .or. ubound(var2%A, 1) /= 5) error stop
if (any(var%A /= [1,2,3,4])) error stop
if (any(var2%A /= [11,22,33,44,55])) error stop
end subroutine test_alloc
subroutine test2_alloc()
type(t2) :: var
type(t2), allocatable :: var2
allocate(var2)
allocate(var%x, var2%x)
!$omp target enter data map(alloc: var, var2)
!$omp target
if (.not. allocated(Var2)) stop 6
if (.not. allocated(Var%x)) stop 7
if (.not. allocated(Var2%x)) stop 8
var%x = 42
var2%x = 43
!$omp end target
!$omp target exit data map(from: var, var2)
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%x)) error stop
if (.not. allocated(Var2%x)) error stop
if (var%x /= 42) error stop
if (var2%x /= 43) error stop
allocate(var%vt, var2%vt)
allocate(var%vt%A(-1:3), var2%vt%A(0:4))
!$omp target enter data map(alloc: var, var2)
!$omp target
if (.not. allocated(Var2)) stop 11
if (.not. allocated(Var%x)) stop 12
if (.not. allocated(Var2%x)) stop 13
if (.not. allocated(Var%vt)) stop 14
if (.not. allocated(Var2%vt)) stop 15
if (.not. allocated(Var%vt%a)) stop 16
if (.not. allocated(Var2%vt%a)) stop 17
var%x = 42
var2%x = 43
if (lbound(var%vt%A, 1) /= -1 .or. ubound(var%vt%A, 1) /= 3) stop 4
if (lbound(var2%vt%A, 1) /= 0 .or. ubound(var2%vt%A, 1) /= 4) stop 5
var%vt%A = [1,2,3,4,5]
var2%vt%A = [11,22,33,44,55]
!$omp end target
!$omp target exit data map(from: var, var2)
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%x)) error stop
if (.not. allocated(Var2%x)) error stop
if (.not. allocated(Var%vt)) error stop
if (.not. allocated(Var2%vt)) error stop
if (.not. allocated(Var%vt%a)) error stop
if (.not. allocated(Var2%vt%a)) error stop
if (var%x /= 42) error stop
if (var2%x /= 43) error stop
if (lbound(var%vt%A, 1) /= -1 .or. ubound(var%vt%A, 1) /= 3) error stop
if (lbound(var2%vt%A, 1) /= 0 .or. ubound(var2%vt%A, 1) /= 4) error stop
if (any(var%vt%A /= [1,2,3,4,5])) error stop
if (any(var2%vt%A /= [11,22,33,44,55])) error stop
end subroutine test2_alloc
subroutine test_alloc_target()
type(t) :: var
type(t), allocatable :: var2
allocate(var2)
allocate(var%A(4), var2%A(5))
!$omp target map(alloc: var, var2)
if (.not. allocated(Var2)) stop 1
if (.not. allocated(Var%A)) stop 2
if (.not. allocated(Var2%A)) stop 3
if (lbound(var%A, 1) /= 1 .or. ubound(var%A, 1) /= 4) stop 4
if (lbound(var2%A, 1) /= 1 .or. ubound(var2%A, 1) /= 5) stop 5
var%A = [1,2,3,4]
var2%A = [11,22,33,44,55]
!$omp end target
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%A)) error stop
if (.not. allocated(Var2%A)) error stop
if (lbound(var%A, 1) /= 1 .or. ubound(var%A, 1) /= 4) error stop
if (lbound(var2%A, 1) /= 1 .or. ubound(var2%A, 1) /= 5) error stop
end subroutine test_alloc_target
subroutine test2_alloc_target()
type(t2) :: var
type(t2), allocatable :: var2
allocate(var2)
allocate(var%x, var2%x)
!$omp target map(alloc: var, var2)
if (.not. allocated(Var2)) stop 6
if (.not. allocated(Var%x)) stop 7
if (.not. allocated(Var2%x)) stop 8
var%x = 42
var2%x = 43
!$omp end target
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%x)) error stop
if (.not. allocated(Var2%x)) error stop
allocate(var%vt, var2%vt)
allocate(var%vt%A(-1:3), var2%vt%A(0:4))
!$omp target map(alloc: var, var2)
if (.not. allocated(Var2)) stop 11
if (.not. allocated(Var%x)) stop 12
if (.not. allocated(Var2%x)) stop 13
if (.not. allocated(Var%vt)) stop 14
if (.not. allocated(Var2%vt)) stop 15
if (.not. allocated(Var%vt%a)) stop 16
if (.not. allocated(Var2%vt%a)) stop 17
var%x = 42
var2%x = 43
if (lbound(var%vt%A, 1) /= -1 .or. ubound(var%vt%A, 1) /= 3) stop 4
if (lbound(var2%vt%A, 1) /= 0 .or. ubound(var2%vt%A, 1) /= 4) stop 5
var%vt%A = [1,2,3,4,5]
var2%vt%A = [11,22,33,44,55]
!$omp end target
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%x)) error stop
if (.not. allocated(Var2%x)) error stop
if (.not. allocated(Var%vt)) error stop
if (.not. allocated(Var2%vt)) error stop
if (.not. allocated(Var%vt%a)) error stop
if (.not. allocated(Var2%vt%a)) error stop
if (lbound(var%vt%A, 1) /= -1 .or. ubound(var%vt%A, 1) /= 3) error stop
if (lbound(var2%vt%A, 1) /= 0 .or. ubound(var2%vt%A, 1) /= 4) error stop
end subroutine test2_alloc_target
subroutine test_from()
type(t) :: var
type(t), allocatable :: var2
allocate(var2)
allocate(var%A(4), var2%A(5))
!$omp target map(from: var, var2)
if (.not. allocated(Var2)) stop 1
if (.not. allocated(Var%A)) stop 2
if (.not. allocated(Var2%A)) stop 3
if (lbound(var%A, 1) /= 1 .or. ubound(var%A, 1) /= 4) stop 4
if (lbound(var2%A, 1) /= 1 .or. ubound(var2%A, 1) /= 5) stop 5
var%A = [1,2,3,4]
var2%A = [11,22,33,44,55]
!$omp end target
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%A)) error stop
if (.not. allocated(Var2%A)) error stop
if (lbound(var%A, 1) /= 1 .or. ubound(var%A, 1) /= 4) error stop
if (lbound(var2%A, 1) /= 1 .or. ubound(var2%A, 1) /= 5) error stop
if (any(var%A /= [1,2,3,4])) error stop
if (any(var2%A /= [11,22,33,44,55])) error stop
end subroutine test_from
subroutine test2_from()
type(t2) :: var
type(t2), allocatable :: var2
allocate(var2)
allocate(var%x, var2%x)
!$omp target map(from: var, var2)
if (.not. allocated(Var2)) stop 6
if (.not. allocated(Var%x)) stop 7
if (.not. allocated(Var2%x)) stop 8
var%x = 42
var2%x = 43
!$omp end target
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%x)) error stop
if (.not. allocated(Var2%x)) error stop
if (var%x /= 42) error stop
if (var2%x /= 43) error stop
allocate(var%vt, var2%vt)
allocate(var%vt%A(-1:3), var2%vt%A(0:4))
!$omp target map(from: var, var2)
if (.not. allocated(Var2)) stop 11
if (.not. allocated(Var%x)) stop 12
if (.not. allocated(Var2%x)) stop 13
if (.not. allocated(Var%vt)) stop 14
if (.not. allocated(Var2%vt)) stop 15
if (.not. allocated(Var%vt%a)) stop 16
if (.not. allocated(Var2%vt%a)) stop 17
var%x = 42
var2%x = 43
if (lbound(var%vt%A, 1) /= -1 .or. ubound(var%vt%A, 1) /= 3) stop 4
if (lbound(var2%vt%A, 1) /= 0 .or. ubound(var2%vt%A, 1) /= 4) stop 5
var%vt%A = [1,2,3,4,5]
var2%vt%A = [11,22,33,44,55]
!$omp end target
if (.not. allocated(Var2)) error stop
if (.not. allocated(Var%x)) error stop
if (.not. allocated(Var2%x)) error stop
if (.not. allocated(Var%vt)) error stop
if (.not. allocated(Var2%vt)) error stop
if (.not. allocated(Var%vt%a)) error stop
if (.not. allocated(Var2%vt%a)) error stop
if (var%x /= 42) error stop
if (var2%x /= 43) error stop
if (lbound(var%vt%A, 1) /= -1 .or. ubound(var%vt%A, 1) /= 3) error stop
if (lbound(var2%vt%A, 1) /= 0 .or. ubound(var2%vt%A, 1) /= 4) error stop
if (any(var%vt%A /= [1,2,3,4,5])) error stop
if (any(var2%vt%A /= [11,22,33,44,55])) error stop
end subroutine test2_from
end module m
use m
implicit none (type, external)
call test_alloc
call test2_alloc
call test_alloc_target
call test2_alloc_target
call test_from
call test2_from
end