blob: bff2e041047082e1690b8cd0acc4e3e7c5627273 [file] [edit]
! REQUIRES: openmp_runtime
! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags -fopenmp-version=52
! OpenMP Version 5.2, Section 6.8: uses_allocators clause.
module uses_allocators_traits_module
use omp_lib
type(omp_alloctrait), parameter :: module_tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
end module
subroutine uses_allocators_ok
use omp_lib
integer(omp_allocator_handle_kind) :: my_alloc
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: x
! A predefined allocator without modifiers.
!$omp target uses_allocators(omp_default_mem_alloc)
x = 1
!$omp end target
! Since 5.2, a non-predefined allocator may omit its traits.
!$omp target uses_allocators(my_alloc)
x = 2
!$omp end target
!$omp target uses_allocators(traits(tr): my_alloc)
x = 3
!$omp end target
!$omp target uses_allocators(memspace(omp_high_bw_mem_space): my_alloc)
x = 4
!$omp end target
!$omp target uses_allocators(memspace(omp_const_mem_space), traits(tr): my_alloc)
x = 5
!$omp end target
! The clause is repeatable on TARGET.
!$omp target uses_allocators(my_alloc) uses_allocators(omp_const_mem_alloc)
x = 6
!$omp end target
! The clause reaches the TARGET leaf of a combined construct.
!$omp target teams uses_allocators(traits(tr): my_alloc)
x = 7
!$omp end target teams
end subroutine
subroutine uses_allocators_renamed_type
use omp_lib, only: renamed_alloctrait => omp_alloctrait, &
omp_allocator_handle_kind, omp_atk_alignment
integer(omp_allocator_handle_kind) :: my_alloc
type(renamed_alloctrait), parameter :: tr(1) = &
[renamed_alloctrait(omp_atk_alignment, 64)]
integer :: x
!$omp target uses_allocators(traits(tr): my_alloc)
x = 1
!$omp end target
end subroutine
subroutine uses_allocators_loop_construct
use omp_lib
integer(omp_allocator_handle_kind) :: my_alloc
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: i, x(10)
! USES_ALLOCATORS is a data-sharing attribute clause that carries allocator
! specifications rather than an object list, so the loop-construct checks
! must not treat it as an object-list clause.
!$omp target teams distribute parallel do uses_allocators(traits(tr): my_alloc)
do i = 1, 10
x(i) = i
end do
!$omp target simd uses_allocators(my_alloc)
do i = 1, 10
x(i) = i
end do
end subroutine
subroutine uses_allocators_errors
use omp_lib
integer(omp_allocator_handle_kind) :: my_alloc, other_alloc
integer(omp_memspace_handle_kind) :: my_space
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
type(omp_alloctrait) :: nonconst(1)
type(omp_alloctrait), parameter :: tr2(1,1) = &
reshape([omp_alloctrait(omp_atk_alignment, 64)], [1,1])
real, parameter :: notatrait(1) = [1.0]
real :: notaninteger
integer :: x
! The allocator must be a base language identifier.
!ERROR: The allocator in a USES_ALLOCATORS clause must be a base language identifier
!$omp target uses_allocators(traits(tr): my_alloc + 1)
x = 1
!$omp end target
! A predefined allocator cannot have modifiers.
!ERROR: A predefined allocator 'omp_default_mem_alloc' in a USES_ALLOCATORS clause cannot have modifiers or traits specified
!$omp target uses_allocators(traits(tr): omp_default_mem_alloc)
x = 2
!$omp end target
!ERROR: A predefined allocator 'omp_const_mem_alloc' in a USES_ALLOCATORS clause cannot have modifiers or traits specified
!$omp target uses_allocators(memspace(omp_const_mem_space): omp_const_mem_alloc)
x = 3
!$omp end target
! omp_null_allocator is a named constant and is not a predefined allocator.
!ERROR: A non-predefined allocator 'omp_null_allocator' in a USES_ALLOCATORS clause must be a variable
!$omp target uses_allocators(omp_null_allocator)
x = 4
!$omp end target
! The allocator must be a scalar integer.
!ERROR: Must have INTEGER type, but is REAL(4)
!$omp target uses_allocators(notaninteger)
x = 5
!$omp end target
! The memspace-handle must name a predefined memory space.
!ERROR: The 'mem-space' modifier must name a predefined memory space
!$omp target uses_allocators(memspace(omp_null_mem_space): my_alloc)
x = 6
!$omp end target
!ERROR: The 'mem-space' modifier must name a predefined memory space
!$omp target uses_allocators(memspace(my_space): my_alloc)
x = 7
!$omp end target
! The traits array must be a constant array of OMP_ALLOCTRAIT.
!ERROR: The traits array 'nonconst' must be a constant array with constant values
!$omp target uses_allocators(traits(nonconst): my_alloc)
x = 8
!$omp end target
!ERROR: The traits array 'tr2' must be a rank-one array
!$omp target uses_allocators(traits(tr2): my_alloc)
x = 9
!$omp end target
!ERROR: The traits array 'notatrait' must be of type OMP_ALLOCTRAIT
!$omp target uses_allocators(traits(notatrait): my_alloc)
x = 10
!$omp end target
! The allocator must not appear in a data-sharing or data-mapping clause.
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the PRIVATE clause on the same construct
!ERROR: Variable 'my_alloc' may not appear on both MAP and PRIVATE clauses on a TARGET construct
!$omp target uses_allocators(traits(tr): my_alloc) private(my_alloc)
x = 11
!$omp end target
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the MAP clause on the same construct
!$omp target map(tofrom: my_alloc) uses_allocators(traits(tr): my_alloc)
x = 12
!$omp end target
! A modifier may appear at most once in one allocator specification.
!ERROR: 'traits-array' modifier cannot occur multiple times
!$omp target uses_allocators(traits(tr), traits(tr): my_alloc)
x = 13
!$omp end target
!ERROR: 'mem-space' modifier cannot occur multiple times
!$omp target uses_allocators(memspace(omp_const_mem_space), memspace(omp_high_bw_mem_space): my_alloc)
x = 131
!$omp end target
! OpenMP 5.2 allows a single allocator specification.
!ERROR: The USES_ALLOCATORS clause accepts a single allocator specification in OpenMP v5.2
!$omp target uses_allocators(traits(tr): my_alloc, traits(tr): other_alloc)
x = 14
!$omp end target
! The clause is not allowed on a non-TARGET construct.
!ERROR: USES_ALLOCATORS clause is not allowed on PARALLEL directive
!$omp parallel uses_allocators(my_alloc)
x = 15
!$omp end parallel
end subroutine
subroutine uses_allocators_deprecated
use omp_lib
integer(omp_allocator_handle_kind) :: my_alloc, other_alloc
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: x
! [5.2:181] The "allocator[(traits)]" list syntax is deprecated, but it is
! still accepted.
!PORTABILITY: The comma-separated list syntax for the USES_ALLOCATORS clause has been deprecated in OpenMP 5.2, use 'USES_ALLOCATORS([TRAITS(traits):] allocator)' instead
!$omp target uses_allocators(my_alloc(tr))
x = 1
!$omp end target
!PORTABILITY: The comma-separated list syntax for the USES_ALLOCATORS clause has been deprecated in OpenMP 5.2, use 'USES_ALLOCATORS([TRAITS(traits):] allocator)' instead
!$omp target uses_allocators(my_alloc(tr), other_alloc(tr))
x = 2
!$omp end target
! A bare comma list is also the deprecated syntax.
!PORTABILITY: The comma-separated list syntax for the USES_ALLOCATORS clause has been deprecated in OpenMP 5.2, use 'USES_ALLOCATORS([TRAITS(traits):] allocator)' instead
!$omp target uses_allocators(my_alloc, other_alloc)
x = 3
!$omp end target
! A single bare allocator is the canonical 5.2 syntax and is not deprecated.
!$omp target uses_allocators(my_alloc)
x = 4
!$omp end target
end subroutine
subroutine uses_allocators_traits_association
use omp_lib
use uses_allocators_traits_module
integer(omp_allocator_handle_kind) :: my_alloc
type(omp_alloctrait), parameter :: host_tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: x
! [5.2:182] requires the traits array to be defined in the construct scope.
!ERROR: The traits array 'module_tr' must be defined in the same scope as the construct
!$omp target uses_allocators(traits(module_tr): my_alloc)
x = 1
!$omp end target
call inner
contains
subroutine inner
!ERROR: The traits array 'host_tr' must be defined in the same scope as the construct
!$omp target uses_allocators(traits(host_tr): my_alloc)
x = 2
!$omp end target
end subroutine
end subroutine
subroutine uses_allocators_impostor_type
use omp_lib, only: omp_allocator_handle_kind
type omp_alloctrait
integer :: key
integer :: value
end type
integer(omp_allocator_handle_kind) :: my_alloc
type(omp_alloctrait), parameter :: tr(1) = [omp_alloctrait(1, 64)]
integer :: x
!ERROR: The traits array 'tr' must be of type OMP_ALLOCTRAIT
!$omp target uses_allocators(traits(tr): my_alloc)
x = 1
!$omp end target
end subroutine
subroutine uses_allocators_combined_conflicts
use omp_lib
integer(omp_allocator_handle_kind) :: private_alloc, shared_alloc, fp_alloc
integer(omp_allocator_handle_kind) :: map_alloc, last_alloc, reduction_alloc
integer :: i, x(10)
!$omp target teams distribute parallel do uses_allocators(private_alloc) private(private_alloc)
do i = 1, 10
x(i) = i
end do
!$omp target teams distribute parallel do uses_allocators(shared_alloc) shared(shared_alloc)
do i = 1, 10
x(i) = i
end do
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the FIRSTPRIVATE clause on the same construct
!$omp target teams distribute parallel do uses_allocators(fp_alloc) firstprivate(fp_alloc)
do i = 1, 10
x(i) = i
end do
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the MAP clause on the same construct
!$omp target teams distribute parallel do uses_allocators(map_alloc) map(tofrom: map_alloc)
do i = 1, 10
x(i) = i
end do
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the LASTPRIVATE clause on the same construct
!$omp target teams distribute parallel do uses_allocators(last_alloc) lastprivate(last_alloc)
do i = 1, 10
x(i) = i
end do
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the REDUCTION clause on the same construct
!$omp target teams distribute parallel do uses_allocators(reduction_alloc) reduction(+: reduction_alloc)
do i = 1, 10
x(i) = i
end do
end subroutine
subroutine uses_allocators_conflicting_clauses
use omp_lib
! Each case uses its own allocator so that the once-per-symbol
! "both MAP and ..." diagnostic of TARGET does not interleave with them.
integer(omp_allocator_handle_kind) :: fp_alloc, idp_alloc, hda_alloc
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: x
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the FIRSTPRIVATE clause on the same construct
!$omp target uses_allocators(traits(tr): fp_alloc) firstprivate(fp_alloc)
x = 1
!$omp end target
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the IS_DEVICE_PTR clause on the same construct
!ERROR: Variable 'idp_alloc' in IS_DEVICE_PTR clause must be of type C_PTR
!$omp target uses_allocators(traits(tr): idp_alloc) is_device_ptr(idp_alloc)
x = 2
!$omp end target
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the HAS_DEVICE_ADDR clause on the same construct
!$omp target uses_allocators(traits(tr): hda_alloc) has_device_addr(hda_alloc)
x = 3
!$omp end target
end subroutine
subroutine uses_allocators_predefined_identity
use omp_lib
use omp_lib, only: renamed_predef => omp_default_mem_alloc
use omp_lib, only: renamed_space => omp_const_mem_space
integer(omp_allocator_handle_kind) :: my_alloc
integer(omp_allocator_handle_kind), parameter :: same_value_as_predef = 1
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: x
! Before 6.0 predefined recognition follows the entity, so a rename of the
! intrinsic omp_lib allocator still denotes it and is accepted bare. At 6.0
! the clause identifier is what matters and the rename is rejected; see
! uses-allocators-version60.f90.
!$omp target uses_allocators(renamed_predef)
x = 1
!$omp end target
! ... and, being predefined, it still rejects modifiers.
!ERROR: A predefined allocator 'renamed_predef' in a USES_ALLOCATORS clause cannot have modifiers or traits specified
!$omp target uses_allocators(traits(tr): renamed_predef)
x = 2
!$omp end target
! A named constant that merely shares a predefined allocator's numeric value
! is neither the predefined entity nor a predefined name, so the variable
! rule applies to it at every version.
!ERROR: A non-predefined allocator 'same_value_as_predef' in a USES_ALLOCATORS clause must be a variable
!$omp target uses_allocators(same_value_as_predef)
x = 3
!$omp end target
! A memory space must use the written name of a predefined memory space.
!ERROR: The 'mem-space' modifier must name a predefined memory space
!$omp target uses_allocators(memspace(renamed_space): my_alloc)
x = 4
!$omp end target
end subroutine
subroutine uses_allocators_predefined_shadow
use omp_lib, only: omp_allocator_handle_kind
! A local named constant of the correct handle kind that shadows the spelling
! of a predefined allocator. [5.2:182] asks whether the allocator *is* a
! predefined allocator, which this is not, so the variable rule applies.
! [6.0:315] matches the name instead and accepts it; see
! uses-allocators-version60.f90.
integer(omp_allocator_handle_kind), parameter :: omp_const_mem_alloc = 999
integer :: x
!ERROR: A non-predefined allocator 'omp_const_mem_alloc' in a USES_ALLOCATORS clause must be a variable
!$omp target uses_allocators(omp_const_mem_alloc)
x = 1
!$omp end target
end subroutine
subroutine uses_allocators_repeated_clauses
use omp_lib
! As above, each case uses its own allocator.
integer(omp_allocator_handle_kind) :: map_alloc, priv_alloc, ir_alloc
type(omp_alloctrait), parameter :: tr(1) = &
[omp_alloctrait(omp_atk_alignment, 64)]
integer :: x, y
! The conflict is in the second MAP clause, which is invisible to a scan
! that inspects only the first occurrence of each clause id.
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the MAP clause on the same construct
!$omp target map(to: y) map(tofrom: map_alloc) uses_allocators(traits(tr): map_alloc)
x = 1
!$omp end target
! The same, for a repeated PRIVATE clause.
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the PRIVATE clause on the same construct
!ERROR: Variable 'y' may not appear on both MAP and PRIVATE clauses on a TARGET construct
!$omp target private(y) private(priv_alloc) uses_allocators(traits(tr): priv_alloc)
x = 2
!$omp end target
! IN_REDUCTION is a data-sharing attribute clause allowed on TARGET, but it
! is not one of the privatizing clauses.
!$omp taskgroup task_reduction(+: ir_alloc)
!ERROR: An allocator in a USES_ALLOCATORS clause cannot also appear in the IN_REDUCTION clause on the same construct
!$omp target in_reduction(+: ir_alloc) uses_allocators(traits(tr): ir_alloc)
x = 3
!$omp end target
!$omp end taskgroup
end subroutine