https://gcc.gnu.org/g:0861d9c3e63cdc8cb0fd08b06dbfd3ea6b999ddf
commit 0861d9c3e63cdc8cb0fd08b06dbfd3ea6b999ddf Author: Kwok Cheung Yeung <kcye...@baylibre.com> Date: Wed Nov 27 21:56:08 2024 +0000 openmp, fortran: Add support for iterators in OpenMP 'target update' constructs (Fortran) This adds Fortran support for iterators in 'to' and 'from' clauses in the 'target update' OpenMP directive. gcc/fortran/ * dump-parse-tree.cc (show_omp_namelist): Add iterator support for OMP_LIST_TO and OMP_LIST_FROM. * match.cc (gfc_free_namelist): Free namespace for OMP_LIST_TO and OMP_LIST_FROM. * openmp.cc (gfc_free_omp_clauses): Free namespace for OMP_LIST_TO and OMP_LIST_FROM. (gfc_match_motion_var_list): Parse 'iterator' modifier. (resolve_omp_clauses): Resolve iterators for OMP_LIST_TO and OMP_LIST_FROM. * trans-openmp.cc (gfc_trans_omp_clauses): Handle iterators in OMP_LIST_TO and OMP_LIST_FROM clauses. Add expressions to iter_block rather than block. gcc/testsuite/ * gfortran.dg/gomp/target-update-iterators-1.f90: New. * gfortran.dg/gomp/target-update-iterators-2.f90: New. * gfortran.dg/gomp/target-update-iterators-3.f90: New. libgomp/ * testsuite/libgomp.fortran/target-update-iterators-1.f90: New. * testsuite/libgomp.fortran/target-update-iterators-2.f90: New. * testsuite/libgomp.fortran/target-update-iterators-3.f90: New. Co-authored-by: Andrew Stubbs <a...@baylibre.com> Diff: --- gcc/fortran/ChangeLog.omp | 15 +++++ gcc/fortran/dump-parse-tree.cc | 7 +- gcc/fortran/match.cc | 3 +- gcc/fortran/openmp.cc | 28 +++++++- gcc/fortran/trans-openmp.cc | 50 ++++++++++++-- gcc/testsuite/ChangeLog.omp | 6 ++ .../gfortran.dg/gomp/target-update-iterators-1.f90 | 25 +++++++ .../gfortran.dg/gomp/target-update-iterators-2.f90 | 28 ++++++++ .../gfortran.dg/gomp/target-update-iterators-3.f90 | 23 +++++++ libgomp/ChangeLog.omp | 6 ++ .../libgomp.fortran/target-update-iterators-1.f90 | 68 +++++++++++++++++++ .../libgomp.fortran/target-update-iterators-2.f90 | 63 +++++++++++++++++ .../libgomp.fortran/target-update-iterators-3.f90 | 78 ++++++++++++++++++++++ 13 files changed, 392 insertions(+), 8 deletions(-) diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp index c652ec1775a9..ebbdf3d149e7 100644 --- a/gcc/fortran/ChangeLog.omp +++ b/gcc/fortran/ChangeLog.omp @@ -1,3 +1,18 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * dump-parse-tree.cc (show_omp_namelist): Add iterator support for + OMP_LIST_TO and OMP_LIST_FROM. + * match.cc (gfc_free_namelist): Free namespace for OMP_LIST_TO and + OMP_LIST_FROM. + * openmp.cc (gfc_free_omp_clauses): Free namespace for OMP_LIST_TO + and OMP_LIST_FROM. + (gfc_match_motion_var_list): Parse 'iterator' modifier. + (resolve_omp_clauses): Resolve iterators for OMP_LIST_TO and + OMP_LIST_FROM. + * trans-openmp.cc (gfc_trans_omp_clauses): Handle iterators in + OMP_LIST_TO and OMP_LIST_FROM clauses. Add expressions to + iter_block rather than block. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * dump-parse-tree.cc (show_omp_namelist): Add iterator support for diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 9fce015598e2..1ac1d632031a 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -1354,7 +1354,8 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) { gfc_current_ns = ns_curr; if (list_type == OMP_LIST_AFFINITY || list_type == OMP_LIST_DEPEND - || list_type == OMP_LIST_MAP) + || list_type == OMP_LIST_MAP + || list_type == OMP_LIST_TO || list_type == OMP_LIST_FROM) { gfc_current_ns = n->u2.ns ? n->u2.ns : ns_curr; if (n->u2.ns != ns_iter) @@ -1370,6 +1371,10 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) fputs ("DEPEND (", dumpfile); else if (list_type == OMP_LIST_MAP) fputs ("MAP (", dumpfile); + else if (list_type == OMP_LIST_TO) + fputs ("TO (", dumpfile); + else if (list_type == OMP_LIST_FROM) + fputs ("FROM (", dumpfile); else gcc_unreachable (); } diff --git a/gcc/fortran/match.cc b/gcc/fortran/match.cc index 2bf1a7f583b2..1986803bbeac 100644 --- a/gcc/fortran/match.cc +++ b/gcc/fortran/match.cc @@ -5540,7 +5540,8 @@ void gfc_free_omp_namelist (gfc_omp_namelist *name, int list) { bool free_ns = (list == OMP_LIST_AFFINITY || list == OMP_LIST_DEPEND - || list == OMP_LIST_MAP); + || list == OMP_LIST_MAP + || list == OMP_LIST_TO || list == OMP_LIST_FROM); bool free_mapper = (list == OMP_LIST_MAP || list == OMP_LIST_TO || list == OMP_LIST_FROM); diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index bb67ee8a2b69..99029d63059d 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -1415,11 +1415,14 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list, if (m != MATCH_YES) return m; + gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns; locus old_loc = gfc_current_locus; int present_modifier = 0; int mapper_modifier = 0; + int iterator_modifier = 0; locus second_mapper_locus = old_loc; locus second_present_locus = old_loc; + locus second_iterator_locus = old_loc; char mapper_id[GFC_MAX_SYMBOL_LEN + 1] = { '\0' }; for (;;) @@ -1440,6 +1443,11 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list, if (strcmp (mapper_id, "default") == 0) mapper_id[0] = '\0'; } + else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES) + { + if (iterator_modifier++ == 1) + second_iterator_locus = current_locus; + } else break; gfc_match (", "); @@ -1450,6 +1458,7 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list, gfc_current_locus = old_loc; present_modifier = 0; mapper_modifier = 0; + iterator_modifier = 0; } if (present_modifier > 1) @@ -1462,8 +1471,18 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list, gfc_error ("too many %<mapper%> modifiers at %L", &second_mapper_locus); return MATCH_ERROR; } + if (iterator_modifier > 1) + { + gfc_error ("too many %<iterator%> modifiers at %L", + &second_iterator_locus); + return MATCH_ERROR; + } + + if (ns_iter) + gfc_current_ns = ns_iter; m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true); + gfc_current_ns = ns_curr; if (m != MATCH_YES) return m; gfc_omp_namelist *n; @@ -1477,6 +1496,12 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list, n->u3.udm = gfc_get_omp_namelist_udm (); n->u3.udm->mapper_id = gfc_get_string ("%s", mapper_id); } + + if (iterator_modifier) + { + n->u2.ns = ns_iter; + ns_iter->refs++; + } } return MATCH_YES; } @@ -10112,7 +10137,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, } } if ((list == OMP_LIST_DEPEND || list == OMP_LIST_AFFINITY - || list == OMP_LIST_MAP) + || list == OMP_LIST_MAP + || list == OMP_LIST_TO || list == OMP_LIST_FROM) && n->u2.ns && !n->u2.ns->resolved) { n->u2.ns->resolved = 1; diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 974092c4ebad..5d62ea396df3 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -6411,11 +6411,39 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, case OMP_LIST_TO: case OMP_LIST_FROM: case OMP_LIST_CACHE: + iterator = NULL_TREE; + prev = NULL; + prev_clauses = omp_clauses; for (; n != NULL; n = n->next) { if (!n->sym->attr.referenced) continue; + if (iterator && prev->u2.ns != n->u2.ns) + { + /* Finish previous iterator group. */ + BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block); + TREE_VEC_ELT (iterator, 5) = tree_block; + for (tree c = omp_clauses; c != prev_clauses; + c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterator; + prev_clauses = omp_clauses; + iterator = NULL_TREE; + } + if (n->u2.ns && (!prev || prev->u2.ns != n->u2.ns)) + { + /* Start a new iterator group. */ + gfc_init_block (&iter_block); + tree_block = make_node (BLOCK); + TREE_USED (tree_block) = 1; + BLOCK_VARS (tree_block) = NULL_TREE; + prev_clauses = omp_clauses; + iterator = handle_iterator (n->u2.ns, block, tree_block); + } + if (!iterator) + gfc_init_block (&iter_block); + prev = n; + switch (list) { case OMP_LIST_TO: @@ -6612,7 +6640,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, ptr = build_fold_indirect_ref (ptr); OMP_CLAUSE_DECL (node) = ptr; OMP_CLAUSE_SIZE (node) - = gfc_full_array_size (block, decl, + = gfc_full_array_size (&iter_block, decl, GFC_TYPE_ARRAY_RANK (type)); tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type)); @@ -6637,7 +6665,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, { gfc_conv_expr_reference (&se, n->expr); ptr = se.expr; - gfc_add_block_to_block (block, &se.pre); + gfc_add_block_to_block (&iter_block, &se.pre); OMP_CLAUSE_SIZE (node) = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ptr))); } @@ -6646,9 +6674,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, gfc_conv_expr_descriptor (&se, n->expr); ptr = gfc_conv_array_data (se.expr); tree type = TREE_TYPE (se.expr); - gfc_add_block_to_block (block, &se.pre); + gfc_add_block_to_block (&iter_block, &se.pre); OMP_CLAUSE_SIZE (node) - = gfc_full_array_size (block, se.expr, + = gfc_full_array_size (&iter_block, se.expr, GFC_TYPE_ARRAY_RANK (type)); tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type)); @@ -6657,7 +6685,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, = fold_build2 (MULT_EXPR, gfc_array_index_type, OMP_CLAUSE_SIZE (node), elemsz); } - gfc_add_block_to_block (block, &se.post); + gfc_add_block_to_block (&iter_block, &se.post); gcc_assert (POINTER_TYPE_P (TREE_TYPE (ptr))); OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr); } @@ -6665,8 +6693,20 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, OMP_CLAUSE_MOTION_PRESENT (node) = 1; if (list == OMP_LIST_CACHE && n->u.map.readonly) OMP_CLAUSE__CACHE__READONLY (node) = 1; + + if (!iterator) + gfc_add_block_to_block (block, &iter_block); omp_clauses = gfc_trans_add_clause (node, omp_clauses); } + if (iterator) + { + /* Finish last iterator group. */ + BLOCK_SUBBLOCKS (tree_block) = gfc_finish_block (&iter_block); + TREE_VEC_ELT (iterator, 5) = tree_block; + for (tree c = omp_clauses; c != prev_clauses; + c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterator; + } break; case OMP_LIST_USES_ALLOCATORS: for (; n != NULL; n = n->next) diff --git a/gcc/testsuite/ChangeLog.omp b/gcc/testsuite/ChangeLog.omp index e25ef2000693..08a3f26046ef 100644 --- a/gcc/testsuite/ChangeLog.omp +++ b/gcc/testsuite/ChangeLog.omp @@ -1,3 +1,9 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * gfortran.dg/gomp/target-update-iterators-1.f90: New. + * gfortran.dg/gomp/target-update-iterators-2.f90: New. + * gfortran.dg/gomp/target-update-iterators-3.f90: New. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * gfortran.dg/gomp/target-map-iterators-1.f90: New. diff --git a/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-1.f90 b/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-1.f90 new file mode 100644 index 000000000000..d3acd844998a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-1.f90 @@ -0,0 +1,25 @@ +! { dg-do compile } +! { dg-options "-fopenmp" } + +program test + implicit none + + integer, parameter :: DIM1 = 17 + integer, parameter :: DIM2 = 39 + + type :: array_ptr + integer, pointer :: ptr(:) + end type + + type (array_ptr) :: x(DIM1), y(DIM1) + + !$omp target update to (iterator(i=1:DIM1): x(i)%ptr(:)) + + !$omp target update to (iterator(i=1:DIM1): x(i)%ptr(:DIM2), y(i)%ptr(:)) + + !$omp target update to (iterator(i=1:DIM1), present: x(i)%ptr(:)) + + !$omp target update to (iterator(i=1:DIM1), iterator(j=i:DIM2): x(i)%ptr(j)) ! { dg-error "too many 'iterator' modifiers at .1." } + + !$omp target update to (iterator(i=1:DIM1), something: x(i, j)) ! { dg-error "Syntax error in OpenMP variable list at .1." } +end program diff --git a/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-2.f90 b/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-2.f90 new file mode 100644 index 000000000000..c57b87c6af8d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-2.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-fopenmp -fdump-tree-gimple" } + +program test + implicit none + + integer, parameter :: DIM1 = 100 + + type :: array_ptr + integer, pointer :: ptr(:) + end type + + type (array_ptr) :: x(DIM1), y(DIM1), z(DIM1) + + !$omp target update to(iterator(i=1:10): x) ! { dg-warning "iterator variable .i. not used in clause expression" } + !$omp target update from(iterator(i2=1:10, j2=1:20): x(i2)) ! { dg-warning "iterator variable .j2. not used in clause expression" } + !$omp target update to(iterator(i3=1:10, j3=1:20, k3=1:30): x(i3+j3), y(j3+k3), z(k3+i3)) + ! { dg-warning "iterator variable .i3. not used in clause expression" "" { target *-*-* } .-1 } + ! { dg-warning "iterator variable .j3. not used in clause expression" "" { target *-*-* } .-2 } + ! { dg-warning "iterator variable .k3. not used in clause expression" "" { target *-*-* } .-3 } +end program + +! { dg-final { scan-tree-dump-times "update to\\\(x " 1 "gimple" } } +! { dg-final { scan-tree-dump-times "update from\\\(iterator\\\(integer\\\(kind=4\\\) i2=1:10:1, loop_label=" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "to\\\(iterator\\\(integer\\\(kind=4\\\) j3=1:20:1, integer\\\(kind=4\\\) i3=1:10:1, loop_label=" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "to\\\(iterator\\\(integer\\\(kind=4\\\) k3=1:30:1, integer\\\(kind=4\\\) j3=1:20:1, loop_label=" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "to\\\(iterator\\\(integer\\\(kind=4\\\) k3=1:30:1, integer\\\(kind=4\\\) i3=1:10:1, loop_label=" 1 "gimple" } } + \ No newline at end of file diff --git a/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-3.f90 b/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-3.f90 new file mode 100644 index 000000000000..d9c92cf46790 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/target-update-iterators-3.f90 @@ -0,0 +1,23 @@ +! { dg-do compile } +! { dg-options "-fopenmp -fdump-tree-gimple" } + +program test + implicit none + + integer, parameter :: DIM1 = 17 + integer, parameter :: DIM2 = 39 + + type :: array_ptr + integer, pointer :: ptr(:) + end type + + type (array_ptr) :: x(DIM1, DIM2), y(DIM1, DIM2), z(DIM1) + + !$omp target update to (iterator(i=1:DIM1, j=1:DIM2): x(i, j)%ptr(:), y(i, j)%ptr(:)) + !$omp target update from (iterator(i=1:DIM1): z(i)%ptr(:)) +end program + +! { dg-final { scan-tree-dump-times "if \\(i <= 17\\) goto <D\\\.\[0-9\]+>; else goto <D\\\.\[0-9\]+>;" 2 "gimple" } } +! { dg-final { scan-tree-dump-times "if \\(j <= 39\\) goto <D\\\.\[0-9\]+>; else goto <D\\\.\[0-9\]+>;" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "to\\(iterator\\(integer\\(kind=4\\) j=1:39:1, integer\\(kind=4\\) i=1:17:1, loop_label=<D\\\.\[0-9\]+>, elems=omp_iter_data\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):MEM <\[^>\]+> \\\[\\\(\[^ \]+ \\\*\\\)D\\\.\[0-9\]+\\\]" 2 "gimple" } } +! { dg-final { scan-tree-dump-times "from\\(iterator\\(integer\\(kind=4\\) i=1:17:1, loop_label=<D\\\.\[0-9\]+>, elems=omp_iter_data\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):MEM <\[^>\]+> \\\[\\\(\[^ \]+ \\\*\\\)D\\\.\[0-9\]+\\\]" 1 "gimple" } } diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp index 82ae5f876663..3d6163db85ed 100644 --- a/libgomp/ChangeLog.omp +++ b/libgomp/ChangeLog.omp @@ -1,3 +1,9 @@ +2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> + + * testsuite/libgomp.fortran/target-update-iterators-1.f90: New. + * testsuite/libgomp.fortran/target-update-iterators-2.f90: New. + * testsuite/libgomp.fortran/target-update-iterators-3.f90: New. + 2025-04-17 Kwok Cheung Yeung <kcye...@baylibre.com> * target.c (kind_to_name): Handle GOMP_MAP_STRUCT and diff --git a/libgomp/testsuite/libgomp.fortran/target-update-iterators-1.f90 b/libgomp/testsuite/libgomp.fortran/target-update-iterators-1.f90 new file mode 100644 index 000000000000..e9a13a3c737d --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-update-iterators-1.f90 @@ -0,0 +1,68 @@ +! { dg-do run } + +! Test target enter data and target update to the target using map +! iterators. + +program test + integer, parameter :: DIM1 = 8 + integer, parameter :: DIM2 = 15 + + type :: array_ptr + integer, pointer :: arr(:) + end type + + type (array_ptr) :: x(DIM1) + integer :: expected, sum, i, j + + expected = mkarray (x) + + !$omp target enter data map(to: x) + !$omp target enter data map(iterator(i=1:DIM1), to: x(i)%arr(:)) + !$omp target map(from: sum) + sum = 0 + do i = 1, DIM1 + do j = 1, DIM2 + sum = sum + x(i)%arr(j) + end do + end do + !$omp end target + + print *, sum, expected + if (sum .ne. expected) stop 1 + + expected = 0 + do i = 1, DIM1 + do j = 1, DIM2 + x(i)%arr(j) = x(i)%arr(j) * i * j + expected = expected + x(i)%arr(j) + end do + end do + + !$omp target update to(iterator(i=1:DIM1): x(i)%arr(:)) + + !$omp target map(from: sum) + sum = 0 + do i = 1, DIM1 + do j = 1, DIM2 + sum = sum + x(i)%arr(j) + end do + end do + !$omp end target + + if (sum .ne. expected) stop 2 +contains + integer function mkarray (x) + type (array_ptr), intent(inout) :: x(DIM1) + integer :: exp = 0 + + do i = 1, DIM1 + allocate (x(i)%arr(DIM2)) + do j = 1, DIM2 + x(i)%arr(j) = i * j + exp = exp + x(i)%arr(j) + end do + end do + + mkarray = exp + end function +end program diff --git a/libgomp/testsuite/libgomp.fortran/target-update-iterators-2.f90 b/libgomp/testsuite/libgomp.fortran/target-update-iterators-2.f90 new file mode 100644 index 000000000000..2e982bc032c9 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-update-iterators-2.f90 @@ -0,0 +1,63 @@ +! { dg-do run } +! { dg-require-effective-target offload_device_nonshared_as } + +! Test target enter data and target update from the target using map +! iterators. + +program test + integer, parameter :: DIM1 = 8 + integer, parameter :: DIM2 = 15 + + type :: array_ptr + integer, pointer :: arr(:) + end type + + type (array_ptr) :: x(DIM1) + integer :: sum, expected + + call mkarray (x) + + !$omp target enter data map(to: x(:DIM1)) + !$omp target enter data map(iterator(i=1:DIM1), to: x(i)%arr(:)) + !$omp target map(from: expected) + expected = 0 + do i = 1, DIM1 + do j = 1, DIM2 + x(i)%arr(j) = (i + 1) * (j + 2) + expected = expected + x(i)%arr(j) + end do + end do + !$omp end target + + ! Host copy of x should remain unchanged. + sum = 0 + do i = 1, DIM1 + do j = 1, DIM2 + sum = sum + x(i)%arr(j) + end do + end do + if (sum .ne. 0) stop 1 + + !$omp target update from(iterator(i=1:DIM1): x(i)%arr(:)) + + ! Host copy should now be updated. + sum = 0 + do i = 1, DIM1 + do j = 1, DIM2 + sum = sum + x(i)%arr(j) + end do + end do + + if (sum .ne. expected) stop 2 +contains + subroutine mkarray (x) + type (array_ptr), intent(inout) :: x(DIM1) + + do i = 1, DIM1 + allocate (x(i)%arr(DIM2)) + do j = 1, DIM2 + x(i)%arr(j) = 0 + end do + end do + end subroutine +end program diff --git a/libgomp/testsuite/libgomp.fortran/target-update-iterators-3.f90 b/libgomp/testsuite/libgomp.fortran/target-update-iterators-3.f90 new file mode 100644 index 000000000000..54b2a6c37c18 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/target-update-iterators-3.f90 @@ -0,0 +1,78 @@ +! { dg-do run } +! { dg-require-effective-target offload_device_nonshared_as } + +! Test target enter data and target update to the target using map +! iterators with a function. + +program test + implicit none + + integer, parameter :: DIM1 = 8 + integer, parameter :: DIM2 = 15 + + type :: array_ptr + integer, pointer :: arr(:) + end type + + type (array_ptr) :: x(DIM1) + integer :: x_new(DIM1, DIM2) + integer :: expected, sum, i, j + + call mkarray (x) + + !$omp target enter data map(to: x(:DIM1)) + !$omp target enter data map(iterator(i=1:DIM1), to: x(i)%arr(:)) + + ! Update x on host. + do i = 1, DIM1 + do j = 1, DIM2 + x_new(i, j) = x(i)%arr(j) + x(i)%arr(j) = (i + 1) * (j + 2); + end do + end do + + ! Update a subset of x on target. + !$omp target update to(iterator(i=1:DIM1/2): x(f (i))%arr(:)) + + !$omp target map(from: sum) + sum = 0 + do i = 1, DIM1 + do j = 1, DIM2 + sum = sum + x(i)%arr(j) + end do + end do + !$omp end target + + ! Calculate expected value on host. + do i = 1, DIM1/2 + do j = 1, DIM2 + x_new(f (i), j) = x(f (i))%arr(j) + end do + end do + + expected = 0 + do i = 1, DIM1 + do j = 1, DIM2 + expected = expected + x_new(i, j) + end do + end do + + if (sum .ne. expected) stop 1 +contains + subroutine mkarray (x) + type (array_ptr), intent(inout) :: x(DIM1) + + do i = 1, DIM1 + allocate (x(i)%arr(DIM2)) + do j = 1, DIM2 + x(i)%arr(j) = i * j + end do + end do + end subroutine + + integer function f (i) + integer, intent(in) :: i + + f = i * 2 + end function +end program