OpenMP: Add omp_all_memory support to Fortran Fortran part to the C/C++/backend implementation r13-337-g7f78783dbedca0183d193e475262ca3c489fd365 gcc/fortran/ChangeLog: * dump-parse-tree.cc (show_omp_namelist): Handle omp_all_memory. * openmp.cc (gfc_match_omp_variable_list, gfc_match_omp_depend_sink, gfc_match_omp_clauses, resolve_omp_clauses): Likewise. * trans-openmp.cc (gfc_trans_omp_clauses, gfc_trans_omp_depobj): Likewise. * resolve.cc (resolve_symbol): Reject it as symbol. libgomp/ChangeLog: * libgomp.texi (OpenMP 5.1): Set omp_all_memory to 'Y'. * testsuite/libgomp.fortran/depend-5.f90: New test. * testsuite/libgomp.fortran/depend-6.f90: New test. * testsuite/libgomp.fortran/depend-7.f90: New test. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/all-memory-1.f90: New test. * gfortran.dg/gomp/all-memory-2.f90: New test. * gfortran.dg/gomp/all-memory-3.f90: New test. gcc/fortran/dump-parse-tree.cc | 2 +- gcc/fortran/openmp.cc | 79 ++++++++++++--- gcc/fortran/resolve.cc | 7 ++ gcc/fortran/trans-openmp.cc | 10 +- gcc/testsuite/gfortran.dg/gomp/all-memory-1.f90 | 51 ++++++++++ gcc/testsuite/gfortran.dg/gomp/all-memory-2.f90 | 52 ++++++++++ gcc/testsuite/gfortran.dg/gomp/all-memory-3.f90 | 24 +++++ libgomp/libgomp.texi | 4 +- libgomp/testsuite/libgomp.fortran/depend-5.f90 | 121 +++++++++++++++++++++++ libgomp/testsuite/libgomp.fortran/depend-6.f90 | 126 ++++++++++++++++++++++++ libgomp/testsuite/libgomp.fortran/depend-7.f90 | 113 +++++++++++++++++++++ 11 files changed, 567 insertions(+), 22 deletions(-) diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index 3635460bffd..a32992035a2 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -1423,7 +1423,7 @@ show_omp_namelist (int list_type, gfc_omp_namelist *n) case OMP_LINEAR_UVAL: fputs ("uval(", dumpfile); break; default: break; } - fprintf (dumpfile, "%s", n->sym->name); + fprintf (dumpfile, "%s", n->sym ? n->sym->name : "omp_all_memory"); if (list_type == OMP_LIST_LINEAR && n->u.linear_op != OMP_LINEAR_DEFAULT) fputc (')', dumpfile); if (n->expr) diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 4d3fcc8bb78..4df1f761c5a 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -296,14 +296,17 @@ gfc_find_omp_udr (gfc_namespace *ns, const char *name, gfc_typespec *ts) } -/* Match a variable/common block list and construct a namelist from it. */ +/* Match a variable/common block list and construct a namelist from it; + if has_all_memory != NULL, *has_all_memory is set and omp_all_memory + yields a list->sym NULL entry. */ static match gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list, bool allow_common, bool *end_colon = NULL, gfc_omp_namelist ***headp = NULL, bool allow_sections = false, - bool allow_derived = false) + bool allow_derived = false, + bool *has_all_memory = NULL) { gfc_omp_namelist *head, *tail, *p; locus old_loc, cur_loc; @@ -315,7 +318,8 @@ gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list, head = tail = NULL; old_loc = gfc_current_locus; - + if (has_all_memory) + *has_all_memory = false; m = gfc_match (str); if (m != MATCH_YES) return m; @@ -323,7 +327,35 @@ gfc_match_omp_variable_list (const char *str, gfc_omp_namelist **list, for (;;) { cur_loc = gfc_current_locus; - m = gfc_match_symbol (&sym, 1); + + m = gfc_match_name (n); + if (m == MATCH_YES && strcmp (n, "omp_all_memory") == 0) + { + if (!has_all_memory) + { + gfc_error ("% at %C not permitted in this " + "clause"); + goto cleanup; + } + *has_all_memory = true; + p = gfc_get_omp_namelist (); + if (head == NULL) + head = tail = p; + else + { + tail->next = p; + tail = tail->next; + } + tail->where = cur_loc; + goto next_item; + } + if (m == MATCH_YES) + { + gfc_symtree *st; + if ((m = gfc_get_ha_sym_tree (n, &st) ? MATCH_ERROR : MATCH_YES) + == MATCH_YES) + sym = st->n.sym; + } switch (m) { case MATCH_YES: @@ -578,6 +610,12 @@ gfc_match_omp_depend_sink (gfc_omp_namelist **list) tail->sym = sym; tail->expr = NULL; tail->where = cur_loc; + if (UNLIKELY (strcmp (sym->name, "omp_all_memory") == 0)) + { + gfc_error ("% used with DEPEND kind " + "other than OUT or INOUT at %C"); + goto cleanup; + } if (gfc_match_char ('+') == MATCH_YES) { if (gfc_match_literal_constant (&tail->expr, 0) != MATCH_YES) @@ -1868,6 +1906,7 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, if ((mask & OMP_CLAUSE_DEPEND) && gfc_match ("depend ( ") == MATCH_YES) { + bool has_omp_all_memory; gfc_namespace *ns_iter = NULL, *ns_curr = gfc_current_ns; match m_it = gfc_match_iterator (&ns_iter, false); if (m_it == MATCH_ERROR) @@ -1920,21 +1959,27 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask, if (m == MATCH_YES) m = gfc_match_omp_variable_list (" : ", &c->lists[OMP_LIST_DEPEND], - false, NULL, &head, true); + false, NULL, &head, true, + false, &has_omp_all_memory); + if (m != MATCH_YES) + goto error; gfc_current_ns = ns_curr; - if (m == MATCH_YES) + if (has_omp_all_memory && depend_op != OMP_DEPEND_INOUT + && depend_op != OMP_DEPEND_OUT) { - gfc_omp_namelist *n; - for (n = *head; n; n = n->next) - { - n->u.depend_op = depend_op; - n->u2.ns = ns_iter; - if (ns_iter) - ns_iter->refs++; - } - continue; + gfc_error ("% used with DEPEND kind " + "other than OUT or INOUT at %C"); + goto error; } - break; + gfc_omp_namelist *n; + for (n = *head; n; n = n->next) + { + n->u.depend_op = depend_op; + n->u2.ns = ns_iter; + if (ns_iter) + ns_iter->refs++; + } + continue; } if ((mask & OMP_CLAUSE_DETACH) && !openacc @@ -6491,6 +6536,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, for (list = 0; list < OMP_LIST_NUM; list++) for (n = omp_clauses->lists[list]; n; n = n->next) { + if (!n->sym) /* omp_all_memory. */ + continue; n->sym->mark = 0; n->sym->comp_mark = 0; if (n->sym->attr.flavor == FL_VARIABLE diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc index c8335f939a9..2ebf076f730 100644 --- a/gcc/fortran/resolve.cc +++ b/gcc/fortran/resolve.cc @@ -15505,6 +15505,13 @@ resolve_symbol (gfc_symbol *sym) if (sym->attr.unlimited_polymorphic) return; + if (UNLIKELY (flag_openmp && strcmp (sym->name, "omp_all_memory") == 0)) + { + gfc_error ("%, declared at %L, may only be used in " + "the OpenMP DEPEND clause", &sym->declared_at); + return; + } + if (sym->attr.flavor == FL_UNKNOWN || (sym->attr.flavor == FL_PROCEDURE && !sym->attr.intrinsic && !sym->attr.generic && !sym->attr.external diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index eb5870c3bc5..7633aee755c 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2880,14 +2880,16 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, continue; } - if (!n->sym->attr.referenced) + if (n->sym && !n->sym->attr.referenced) continue; tree node = build_omp_clause (input_location, list == OMP_LIST_DEPEND ? OMP_CLAUSE_DEPEND : OMP_CLAUSE_AFFINITY); - if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL) + if (n->sym == NULL) /* omp_all_memory */ + OMP_CLAUSE_DECL (node) = null_pointer_node; + else if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL) { tree decl = gfc_trans_omp_variable (n->sym, false); if (gfc_omp_privatize_by_reference (decl)) @@ -5531,7 +5533,9 @@ gfc_trans_omp_depobj (gfc_code *code) if (n) { tree var; - if (n->expr && n->expr->ref->u.ar.type != AR_FULL) + if (!n->sym) /* omp_all_memory. */ + var = null_pointer_node; + else if (n->expr && n->expr->ref->u.ar.type != AR_FULL) { gfc_init_se (&se, NULL); if (n->expr->ref->u.ar.type == AR_ELEMENT) diff --git a/gcc/testsuite/gfortran.dg/gomp/all-memory-1.f90 b/gcc/testsuite/gfortran.dg/gomp/all-memory-1.f90 new file mode 100644 index 00000000000..6d56473b1f3 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/all-memory-1.f90 @@ -0,0 +1,51 @@ +module m + integer :: omp_all_memory ! { dg-error "'omp_all_memory', declared at .1., may only be used in the OpenMP DEPEND clause" } +end module m + +subroutine f1 + integer :: omp_all_memory ! { dg-error "'omp_all_memory', declared at .1., may only be used in the OpenMP DEPEND clause" } + !$omp target depend(out: omp_all_memory) + !$omp end target +end + +subroutine f2 + dimension :: omp_all_memory(5) ! { dg-error "'omp_all_memory', declared at .1., may only be used in the OpenMP DEPEND clause" } + !$omp target depend(out: omp_all_memory) + !$omp end target +end + +subroutine f3 + integer :: A + !$omp target depend(out: omp_all_memory) ! OK + omp_all_memory = 5 ! { dg-error "'omp_all_memory', declared at .1., may only be used in the OpenMP DEPEND clause" } + !$omp end target +end + +subroutine f4 + !$omp target map(to: omp_all_memory) ! { dg-error "'omp_all_memory' at .1. not permitted in this clause" } + ! !$omp end target + + !$omp task private (omp_all_memory) ! { dg-error "'omp_all_memory' at .1. not permitted in this clause" } + ! !$omp end task +end + +subroutine f5 ! OK + !$omp target depend(inout : omp_all_memory ) + !$omp end target + + !$omp target depend ( out : omp_all_memory) + !$omp end target +end + +subroutine f6 + !$omp target depend(in : omp_all_memory ) ! { dg-error "'omp_all_memory' used with DEPEND kind other than OUT or INOUT" } + ! !$omp end target + + !$omp target depend(mutexinoutset : omp_all_memory ) ! { dg-error "'omp_all_memory' used with DEPEND kind other than OUT or INOUT" } + ! !$omp end target + + !$omp target depend ( depobj : omp_all_memory) ! { dg-error "'omp_all_memory' used with DEPEND kind other than OUT or INOUT" } + !!$omp end target + + !$omp ordered depend ( sink : omp_all_memory) ! { dg-error "'omp_all_memory' used with DEPEND kind other than OUT or INOUT" } +end diff --git a/gcc/testsuite/gfortran.dg/gomp/all-memory-2.f90 b/gcc/testsuite/gfortran.dg/gomp/all-memory-2.f90 new file mode 100644 index 00000000000..f7ee34fedc8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/all-memory-2.f90 @@ -0,0 +1,52 @@ +! { dg-additional-options "-fno-openmp" } +module m + integer :: omp_all_memory +end module m + +subroutine f1 + integer :: omp_all_memory + !$omp target depend(out: omp_all_memory) + !$omp end target +end + +subroutine f2 + dimension :: omp_all_memory(5) + !$omp target depend(out: omp_all_memory) + !$omp end target +end + +subroutine f3 + integer :: A + !$omp target depend(out: omp_all_memory) + omp_all_memory = 5 + !$omp end target +end + +subroutine f4 + !$omp target map(to: omp_all_memory) + ! !$omp end target + + !$omp task private (omp_all_memory) + ! !$omp end task +end + +subroutine f5 + !$omp target depend(inout : omp_all_memory ) + !$omp end target + + !$omp target depend ( out : omp_all_memory) + !$omp end target +end + +subroutine f6 + !$omp target depend(in : omp_all_memory ) + ! !$omp end target + + !$omp target depend(mutexinoutset : omp_all_memory ) + ! !$omp end target + + !$omp target depend ( depobj : omp_all_memory) + !$omp end target + + !$omp ordered depend ( sink : omp_all_memory) +end diff --git a/gcc/testsuite/gfortran.dg/gomp/all-memory-3.f90 b/gcc/testsuite/gfortran.dg/gomp/all-memory-3.f90 new file mode 100644 index 00000000000..dc95e086ee6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/all-memory-3.f90 @@ -0,0 +1,24 @@ +module m + use iso_c_binding + implicit none + integer, parameter :: omp_depend_kind = 2*c_size_t + + integer(omp_depend_kind) :: z +contains + +subroutine foo + integer :: x, y + x = 0; y = 0 + !$omp task depend(out: omp_all_memory) + block; end block + !$omp task depend(inout: omp_all_memory) + block; end block + !$omp task depend(out: x, omp_all_memory, y) + block; end block + !$omp task depend(inout: omp_all_memory, y) + block; end block + !$omp task depend(out: x, omp_all_memory) + block; end block + !$omp depobj (z) depend (inout: omp_all_memory) +end +end diff --git a/libgomp/libgomp.texi b/libgomp/libgomp.texi index b5e5fbb8cca..d9d86f36a50 100644 --- a/libgomp/libgomp.texi +++ b/libgomp/libgomp.texi @@ -274,7 +274,7 @@ The OpenMP 4.5 specification is fully supported. @multitable @columnfractions .60 .10 .25 @headitem Description @tab Status @tab Comments @item OpenMP directive as C++ attribute specifiers @tab Y @tab -@item @code{omp_all_memory} reserved locator @tab N @tab +@item @code{omp_all_memory} reserved locator @tab Y @tab @item @emph{target_device trait} in OpenMP Context @tab N @tab @item @code{target_device} selector set in context selectors @tab N @tab @item C/C++'s @code{declare variant} directive: elision support of @@ -283,7 +283,7 @@ The OpenMP 4.5 specification is fully supported. @code{append_args} @tab N @tab @item @code{dispatch} construct @tab N @tab @item device-specific ICV settings the environment variables @tab N @tab -@item assume directive @tab N @tab +@item @code{assume} directive @tab N @tab @item @code{nothing} directive @tab Y @tab @item @code{error} directive @tab Y @tab @item @code{masked} construct @tab Y @tab diff --git a/libgomp/testsuite/libgomp.fortran/depend-5.f90 b/libgomp/testsuite/libgomp.fortran/depend-5.f90 new file mode 100644 index 00000000000..a350e793623 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/depend-5.f90 @@ -0,0 +1,121 @@ +! { dg-additional-sources my-usleep.c } +! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" } + +module m + implicit none + + interface + subroutine usleep(t) bind(C, name="my_usleep") + use iso_c_binding + integer(c_int), value :: t + end subroutine + end interface + +contains +subroutine test (ifval) + logical, value :: ifval + integer :: a(0:7), b(0:7), i + + do i = 0, 7 + a(i) = i + b(i) = 2 * i + end do + !$omp parallel + block + !$omp single + block + !$omp task shared(a) depend(in: a(0)) + block + call usleep (5000) + a(0) = 42 + end block + !$omp task shared(a) depend(out: a(1)) + block + call usleep (5000) + a(1) = 43 + end block + !$omp task shared(a) depend(inout: a(2)) + block + call usleep (5000) + a(2) = 44 + end block + !$omp task shared(a) depend(mutexinoutset: a(3)) + block + call usleep (5000) + a(3) = 45 + end block + !$omp task shared(a) + block + call usleep (15000) + a(4) = 46 + end block + !$omp task shared(b) depend(in: b(0)) + block + call usleep (5000) + b(0) = 47 + end block + !$omp task shared(b) depend(in: b(4)) + block + call usleep (5000) + b(4) = 48 + end block + ! None of the above tasks depend on each other. + ! The following task depends on all but the a(4) = 46; one. + !$omp task shared(a, b) depend(out: omp_all_memory) private(i) if(ifval) + block + if (a(0) /= 42 .or. a(1) /= 43 .or. a(2) /= 44 .or. a(3) /= 45 & + .or. a(5) /= 5 .or. a(6) /= 6 .or. a(7) /= 7 & + .or. b(0) /= 47 .or. b(1) /= 2 .or. b(2) /= 4 .or. b(3) /= 6 & + .or. b(4) /= 48 .or. b(5) /= 10 .or. b(6) /= 12 .or. b(7) /= 14) & + error stop + do i = 0, 7 + if (i /= 4) & + a(i) = 3 * i + 7 + end do + do i = 0, 7 + b(i) = 4 * i - 7 + end do + end block + ! The following task depends on both b(0) = 47; and + ! above omp_all_memory tasks, but as the latter depends on + ! the former, effectively it is dependent just on the omp_all_memory + ! task. + !$omp task shared(b) depend(inout: b(0)) + block + call usleep (5000) + b(0) = 49 + end block + ! The following task depends on all the above except a(4) = 46; one, + ! but it can be reduced to dependency on the above omp_all_memory + ! one and b(0) = 49; one. + !$omp task shared(a, b) depend(inout: b(7), omp_all_memory, b(6)) & + !$omp& private(i) if(ifval) + block + do i = 0, 7 + if (i /= 4) then + if (a(i) /= 3 * i + 7) & + error stop + a(i) = 5 * i + 50 + end if + end do + if (b(0) /= 49) & + error stop + b(0) = 6 * i + 57 + do i = 1, 7 + if (b(i) /= 4 * i - 7) & + error stop + b(i) = 6 * i + 57 + end do + end block + !$omp taskwait + if (a(4) /= 46) & + error stop + end block ! end single + end block ! end parallel +end +end module m + +use m +call test(.true.) +call test(.false.) +end diff --git a/libgomp/testsuite/libgomp.fortran/depend-6.f90 b/libgomp/testsuite/libgomp.fortran/depend-6.f90 new file mode 100644 index 00000000000..edea8571bba --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/depend-6.f90 @@ -0,0 +1,126 @@ +! { dg-additional-sources my-usleep.c } +! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" } + +module m + use omp_lib + implicit none + + interface + subroutine usleep(t) bind(C, name="my_usleep") + use iso_c_binding + integer(c_int), value :: t + end subroutine + end interface + +contains +subroutine test (ifval) + logical, value :: ifval + integer :: a(0:7), b(0:7), i + integer(omp_depend_kind) d1, d2 + !$omp depobj (d1) depend(inout: omp_all_memory) + !$omp depobj (d2) depend(out: omp_all_memory) + do i = 0, 7 + a(i) = i + b(i) = 2 * i + end do + !$omp parallel + block + !$omp single + block + !$omp task shared(a) depend(in: a(0)) + block + call usleep (5000) + a(0) = 42 + end block + !$omp task shared(a) depend(out: a(1)) + block + call usleep (5000) + a(1) = 43 + end block + !$omp task shared(a) depend(inout: a(2)) + block + call usleep (5000) + a(2) = 44 + end block + !$omp task shared(a) depend(mutexinoutset: a(3)) + block + call usleep (5000) + a(3) = 45 + end block + !$omp task shared(a) + block + call usleep (15000) + a(4) = 46 + end block + !$omp task shared(b) depend(in: b(0)) + block + call usleep (5000) + b(0) = 47 + end block + !$omp task shared(b) depend(in: b(4)) + block + call usleep (5000) + b(4) = 48 + end block + ! None of the above tasks depend on each other. + ! The following task depends on all but the a(4) = 46; one. + !$omp task shared(a, b) depend(depobj: d1) private(i) if(ifval) + block + if (a(0) /= 42 .or. a(1) /= 43 .or. a(2) /= 44 .or. a(3) /= 45 & + .or. a(5) /= 5 .or. a(6) /= 6 .or. a(7) /= 7 & + .or. b(0) /= 47 .or. b(1) /= 2 .or. b(2) /= 4 .or. b(3) /= 6 & + .or. b(4) /= 48 .or. b(5) /= 10 .or. b(6) /= 12 .or. b(7) /= 14) & + error stop + do i = 0, 7 + if (i /= 4) & + a(i) = 3 * i + 7 + end do + do i = 0, 7 + b(i) = 4 * i - 7 + end do + end block + ! The following task depends on both b(0) = 47; and + ! above omp_all_memory tasks, but as the latter depends on + ! the former, effectively it is dependent just on the omp_all_memory + ! task. + !$omp task shared(b) depend(inout: b(0)) + block + call usleep (5000) + b(0) = 49 + end block + ! The following task depends on all the above except a(4) = 46; one, + ! but it can be reduced to dependency on the above omp_all_memory + ! one and b(0) = 49; one. + !$omp task shared(a, b) depend(inout: b(6)) depend(depobj: d2) & + !$omp& depend(out: b(7)) private(i) if(ifval) + block + do i = 0, 7 + if (i /= 4) then + if (a(i) /= 3 * i + 7) & + error stop + a(i) = 5 * i + 50 + end if + end do + if (b(0) /= 49) & + error stop + b(0) = 6 * i + 57 + do i = 1, 7 + if (b(i) /= 4 * i - 7) & + error stop + b(i) = 6 * i + 57 + end do + end block + !$omp taskwait + if (a(4) /= 46) & + error stop + end block + end block + !$omp depobj (d2) destroy + !$omp depobj (d1) destroy +end +end module m + +use m +call test (.true.) +call test (.false.) +end diff --git a/libgomp/testsuite/libgomp.fortran/depend-7.f90 b/libgomp/testsuite/libgomp.fortran/depend-7.f90 new file mode 100644 index 00000000000..d3f3988f0da --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/depend-7.f90 @@ -0,0 +1,113 @@ +! { dg-additional-sources my-usleep.c } +! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" } + +program main + implicit none + + interface + subroutine usleep(t) bind(C, name="my_usleep") + use iso_c_binding + integer(c_int), value :: t + end subroutine + end interface + + integer :: a(0:7), b(0:7), i + + do i = 0, 7 + a(i) = i + b(i) = 2 * i + end do + + !$omp parallel + block + !$omp single + block + !$omp task shared(a) depend(in: a(0)) + block + call usleep (5000) + a(0) = 42 + end block + !$omp task shared(a) depend(out: a(1)) + block + call usleep (5000) + a(1) = 43 + end block + !$omp task shared(a) depend(inout: a(2)) + block + call usleep (5000) + a(2) = 44 + end block + !$omp task shared(a) depend(mutexinoutset: a(3)) + block + call usleep (5000) + a(3) = 45 + end block + !$omp task shared(a) + block + call usleep (15000) + a(4) = 46 + end block + !$omp task shared(b) depend(in: b(0)) + block + call usleep (5000) + b(0) = 47 + end block + !$omp task shared(b) depend(in: b(4)) + block + call usleep (5000) + b(4) = 48 + end block + ! None of the above tasks depend on each other. + ! The following task depends on all but the a(4) = 46; one. + !$omp task shared(a, b) depend(iterator (j=0:7), inout: omp_all_memory) private(i) + block + if (a(0) /= 42 .or. a(1) /= 43 .or. a(2) /= 44 .or. a(3) /= 45 & + .or. a(5) /= 5 .or. a(6) /= 6 .or. a(7) /= 7 & + .or. b(0) /= 47 .or. b(1) /= 2 .or. b(2) /= 4 .or. b(3) /= 6 & + .or. b(4) /= 48 .or. b(5) /= 10 .or. b(6) /= 12 .or. b(7) /= 14) & + error stop + do i = 0, 7 + if (i /= 4) & + a(i) = 3 * i + 7 + end do + do i = 0, 7 + b(i) = 4 * i - 7 + end do + end block + ! The following task depends on both b(0) = 47; and + ! above omp_all_memory tasks, but as the latter depends on + ! the former, effectively it is dependent just on the omp_all_memory + ! task. + !$omp task shared(b) depend(inout: b(0)) + block + call usleep (5000) + b(0) = 49 + end block + ! The following task depends on all the above except a(4) = 46; one, + ! but it can be reduced to dependency on the above omp_all_memory + ! one and b(0) = 49; one. + !$omp task shared(a, b) depend(inout: b(7)) depend(iterator(j=4:5), out: omp_all_memory) & + !$omp& depend(inout: b(6)) private(i) + block + do i = 0, 7 + if (i /= 4) then + if (a(i) /= 3 * i + 7) & + error stop + a(i) = 5 * i + 50 + end if + end do + if (b(0) /= 49) & + error stop + b(0) = 6 * i + 57 + do i = 1, 7 + if (b(i) /= 4 * i - 7) & + error stop + b(i) = 6 * i + 57 + end do + end block + !$omp taskwait + if (a(4) /= 46) & + error stop + end block + end block +end program