| ! 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 |