@@ -1360,7 +1360,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)
@@ -1376,6 +1377,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 ();
}
@@ -194,7 +194,8 @@ gfc_free_omp_clauses (gfc_omp_clauses *c)
for (i = 0; i < OMP_LIST_NUM; i++)
gfc_free_omp_namelist (c->lists[i],
i == OMP_LIST_AFFINITY || i == OMP_LIST_DEPEND
- || i == OMP_LIST_MAP,
+ || i == OMP_LIST_MAP
+ || i == OMP_LIST_TO || i == OMP_LIST_FROM,
i == OMP_LIST_ALLOCATE,
i == OMP_LIST_USES_ALLOCATORS,
i == OMP_LIST_INIT);
@@ -1378,17 +1379,65 @@ gfc_match_motion_var_list (const char *str, gfc_omp_namelist **list,
if (m != MATCH_YES)
return m;
- match m_present = gfc_match (" present : ");
+ gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns;
+ int present_modifier = 0, iterator_modifier = 0;
+ locus present_locus = gfc_current_locus, iterator_locus = gfc_current_locus;
- m = gfc_match_omp_variable_list ("", list, false, NULL, headp, true, true);
+ for (;;)
+ {
+ locus current_locus = gfc_current_locus;
+ if (gfc_match ("present ") == MATCH_YES)
+ {
+ if (present_modifier++ == 1)
+ present_locus = current_locus;
+ }
+ else if (gfc_match_iterator (&ns_iter, true) == MATCH_YES)
+ {
+ if (iterator_modifier++ == 1)
+ iterator_locus = current_locus;
+ }
+ else
+ break;
+ gfc_match (", ");
+ }
+
+ if (present_modifier > 1)
+ {
+ gfc_error ("too many %<present%> modifiers at %L",
+ &present_locus);
+ return MATCH_ERROR;
+ }
+ if (iterator_modifier > 1)
+ {
+ gfc_error ("too many %<iterator%> modifiers at %L",
+ &iterator_locus);
+ return MATCH_ERROR;
+ }
+
+ if (ns_iter)
+ gfc_current_ns = ns_iter;
+
+ const char *exp = (present_modifier || iterator_modifier) ? " :" : "";
+ m = gfc_match_omp_variable_list (exp, list, false, NULL, headp, true, true);
+ gfc_current_ns = ns_curr;
if (m != MATCH_YES)
return m;
- if (m_present == MATCH_YES)
+
+ if (present_modifier || iterator_modifier)
{
gfc_omp_namelist *n;
for (n = **headp; n; n = n->next)
- n->u.present_modifier = true;
+ {
+ if (present_modifier)
+ n->u.present_modifier = true;
+ if (iterator_modifier)
+ {
+ n->u2.ns = ns_iter;
+ ns_iter->refs++;
+ }
+ }
}
+
return MATCH_YES;
}
@@ -8894,7 +8943,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
for (; n != NULL; n = n->next)
{
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;
@@ -4099,11 +4099,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:
@@ -4141,7 +4169,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));
@@ -4166,7 +4194,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)));
}
@@ -4175,9 +4203,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));
@@ -4186,7 +4214,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);
}
@@ -4194,8 +4222,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:
/* Ignore pre-defined allocators as no special treatment is needed. */
new file mode 100644
@@ -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 "Failed to match clause at .1." }
+end program
new file mode 100644
@@ -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
new file mode 100644
@@ -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=D\\\.\[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=D\\\.\[0-9\]+, index=D\\\.\[0-9\]+\\):MEM <\[^>\]+> \\\[\\\(\[^ \]+ \\\*\\\)D\\\.\[0-9\]+\\\]" 1 "gimple" } }
new file mode 100644
@@ -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
new file mode 100644
@@ -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
new file mode 100644
@@ -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