]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
openmp: Add support for inoutset depend-kind
authorJakub Jelinek <jakub@redhat.com>
Mon, 4 Jul 2022 19:32:48 +0000 (21:32 +0200)
committerTobias Burnus <tobias@codesourcery.com>
Mon, 4 Jul 2022 19:39:11 +0000 (21:39 +0200)
This patch adds support for inoutset depend-kind in depend
clauses.  It is very similar to the in depend-kind in that
a task with a dependency with that depend-kind is dependent
on all previously created sibling tasks with matching address
unless they have the same depend-kind.
In the in depend-kind case everything is dependent except
for in -> in dependency, for inoutset everything is
dependent except for inoutset -> inoutset dependency.
mutexinoutset is also similar (everything is dependent except
for mutexinoutset -> mutexinoutset dependency), but there is
also the additional restriction that only one task with
mutexinoutset for each address can be scheduled at once (i.e.
mutual exclusitivty).  For now we support mutexinoutset
the same as inout/out, but the inoutset support is full.

In order not to bump the ABI for dependencies each time
(we've bumped it already once, the old ABI supports only
inout/out and in depend-kind, the new ABI supports
inout/out, mutexinoutset, in and depobj), this patch arranges
for inoutset to be at least for the time being always handled
as if it was specified through depobj even when it is not.
So it uses the new ABI for that and inoutset are represented
like depobj - pointer to a pair of pointers where the first one
will be the actual address of the object mentioned in depend
clause and second pointer will be (void *) GOMP_DEPEND_INOUTSET.

2022-05-17  Jakub Jelinek  <jakub@redhat.com>

gcc/
* tree-core.h (enum omp_clause_depend_kind): Add
OMP_CLAUSE_DEPEND_INOUTSET.
* tree-pretty-print.cc (dump_omp_clause): Handle
OMP_CLAUSE_DEPEND_INOUTSET.
* gimplify.cc (gimplify_omp_depend): Likewise.
* omp-low.cc (lower_depend_clauses): Likewise.
gcc/c-family/
* c-omp.cc (c_finish_omp_depobj): Handle
OMP_CLAUSE_DEPEND_INOUTSET.
gcc/c/
* c-parser.cc (c_parser_omp_clause_depend): Parse
inoutset depend-kind.
(c_parser_omp_depobj): Likewise.
gcc/cp/
* parser.cc (cp_parser_omp_clause_depend): Parse
inoutset depend-kind.
(cp_parser_omp_depobj): Likewise.
* cxx-pretty-print.cc (cxx_pretty_printer::statement): Handle
OMP_CLAUSE_DEPEND_INOUTSET.
gcc/testsuite/
* c-c++-common/gomp/all-memory-1.c (boo): Add test with
inoutset depend-kind.
* c-c++-common/gomp/all-memory-2.c (boo): Likewise.
* c-c++-common/gomp/depobj-1.c (f1): Likewise.
(f2): Adjusted expected diagnostics.
* g++.dg/gomp/depobj-1.C (f4): Adjust expected diagnostics.
include/
* gomp-constants.h (GOMP_DEPEND_INOUTSET): Define.
libgomp/
* libgomp.h (struct gomp_task_depend_entry): Change is_in type
from bool to unsigned char.
* task.c (gomp_task_handle_depend): Handle GOMP_DEPEND_INOUTSET.
Ignore dependencies where
task->depend[i].is_in && task->depend[i].is_in == ent->is_in
rather than just task->depend[i].is_in && ent->is_in.  Remember
whether GOMP_DEPEND_IN loop is needed and guard the loop with that
conditional.
(gomp_task_maybe_wait_for_dependencies): Handle GOMP_DEPEND_INOUTSET.
Ignore dependencies where elem.is_in && elem.is_in == ent->is_in
rather than just elem.is_in && ent->is_in.
* testsuite/libgomp.c-c++-common/depend-1.c (test): Add task with
inoutset depend-kind.
* testsuite/libgomp.c-c++-common/depend-2.c (test): Likewise.
* testsuite/libgomp.c-c++-common/depend-3.c (test): Likewise.
* testsuite/libgomp.c-c++-common/depend-inoutset-1.c: New test.

(cherry picked from commit 2c16eb3157f86ae561468c540caf8eb326106b5f)

26 files changed:
gcc/ChangeLog.omp
gcc/c-family/ChangeLog.omp
gcc/c-family/c-omp.cc
gcc/c/ChangeLog.omp
gcc/c/c-parser.cc
gcc/cp/ChangeLog.omp
gcc/cp/cxx-pretty-print.cc
gcc/cp/parser.cc
gcc/gimplify.cc
gcc/omp-low.cc
gcc/testsuite/ChangeLog.omp
gcc/testsuite/c-c++-common/gomp/all-memory-1.c
gcc/testsuite/c-c++-common/gomp/all-memory-2.c
gcc/testsuite/c-c++-common/gomp/depobj-1.c
gcc/testsuite/g++.dg/gomp/depobj-1.C
gcc/tree-core.h
gcc/tree-pretty-print.cc
include/ChangeLog.omp
include/gomp-constants.h
libgomp/ChangeLog.omp
libgomp/libgomp.h
libgomp/task.c
libgomp/testsuite/libgomp.c-c++-common/depend-1.c
libgomp/testsuite/libgomp.c-c++-common/depend-2.c
libgomp/testsuite/libgomp.c-c++-common/depend-3.c
libgomp/testsuite/libgomp.c-c++-common/depend-inoutset-1.c [new file with mode: 0644]

index 6e059579a8131ed3a8cf1b16cab8a6313df9a3ee..1c4634d09abeb31dfb39af6081c17b60c57b63af 100644 (file)
@@ -1,3 +1,15 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree-core.h (enum omp_clause_depend_kind): Add
+       OMP_CLAUSE_DEPEND_INOUTSET.
+       * tree-pretty-print.cc (dump_omp_clause): Handle
+       OMP_CLAUSE_DEPEND_INOUTSET.
+       * gimplify.cc (gimplify_omp_depend): Likewise.
+       * omp-low.cc (lower_depend_clauses): Likewise.
+
 2022-06-17  Andrew Stubbs  <ams@codesourcery.com>
 
        * config/gcn/gcn.c (unified_shared_memory_enabled): New variable.
index e46a556ada5cdf38b7224c1aacc9b83c449315e4..f4d2dce3f45b6f73087d828b676a3cc9e32ff63d 100644 (file)
@@ -1,3 +1,11 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-omp.cc (c_finish_omp_depobj): Handle
+       OMP_CLAUSE_DEPEND_INOUTSET.
+
 2022-04-15  Kwok Cheung Yeung  <kcy@codesourcery.com>
 
        gcc/c-family/
@@ -44,7 +52,7 @@
        (check_and_annotate_for_loop): Use the new helper function.
 
 2020-08-30  Sandra Loosemore  <sandra@codesourcery.com>
-    
+
        * c-omp.cc (annotate_for_loop): Move initializer processing...
        (check_and_annotate_for_loop): ... to here.  Allow the loop
        variable as either operand to the condition.
index a6fea51d46e050cb10c3d001e5dbf9b2bdd56108..d71d5e446be65b70e1ec2606eef2365d2234f806 100644 (file)
@@ -739,6 +739,7 @@ c_finish_omp_depobj (location_t loc, tree depobj,
        case OMP_CLAUSE_DEPEND_OUT:
        case OMP_CLAUSE_DEPEND_INOUT:
        case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+       case OMP_CLAUSE_DEPEND_INOUTSET:
          kind = OMP_CLAUSE_DEPEND_KIND (clause);
          t = OMP_CLAUSE_DECL (clause);
          gcc_assert (t);
@@ -797,6 +798,9 @@ c_finish_omp_depobj (location_t loc, tree depobj,
     case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
       k = GOMP_DEPEND_MUTEXINOUTSET;
       break;
+    case OMP_CLAUSE_DEPEND_INOUTSET:
+      k = GOMP_DEPEND_INOUTSET;
+      break;
     case OMP_CLAUSE_DEPEND_LAST:
       k = -1;
       break;
index 77b7602ad69cd89d6f8d619ab139dac2bc592578..51d735341f26ef491908aa586a9a45c5a90be720 100644 (file)
@@ -1,3 +1,12 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-parser.cc (c_parser_omp_clause_depend): Parse
+       inoutset depend-kind.
+       (c_parser_omp_depobj): Likewise.
+
 2022-06-30  Tobias Burnus  <tobias@codesourcery.com>
 
        * c-parser.cc (c_parser_omp_requires): Add missing %<...%> in error.
index 5cabcb684e9323fade52b2d85c555c68b5570eed..903063d4c1e588d0eedd7ef55ca0705541a9efd4 100644 (file)
@@ -16309,7 +16309,7 @@ c_parser_omp_clause_affinity (c_parser *parser, tree list)
    depend ( depend-modifier , depend-kind: variable-list )
 
    depend-kind:
-     in | out | inout | mutexinoutset | depobj
+     in | out | inout | mutexinoutset | depobj | inoutset
 
    depend-modifier:
      iterator ( iterators-definition )  */
@@ -16341,6 +16341,8 @@ c_parser_omp_clause_depend (c_parser *parser, tree list)
        kind = OMP_CLAUSE_DEPEND_IN;
       else if (strcmp ("inout", p) == 0)
        kind = OMP_CLAUSE_DEPEND_INOUT;
+      else if (strcmp ("inoutset", p) == 0)
+       kind = OMP_CLAUSE_DEPEND_INOUTSET;
       else if (strcmp ("mutexinoutset", p) == 0)
        kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
       else if (strcmp ("out", p) == 0)
@@ -19315,12 +19317,14 @@ c_parser_omp_depobj (c_parser *parser)
                    kind = OMP_CLAUSE_DEPEND_INOUT;
                  else if (!strcmp ("mutexinoutset", p2))
                    kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+                 else if (!strcmp ("inoutset", p2))
+                   kind = OMP_CLAUSE_DEPEND_INOUTSET;
                }
              if (kind == OMP_CLAUSE_DEPEND_SOURCE)
                {
                  clause = error_mark_node;
-                 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
-                                   "%<mutexinoutset%>");
+                 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
+                                   "%<mutexinoutset%> or %<inoutset%>");
                }
              c_parens.skip_until_found_close (parser);
            }
index 5704076ab70c6a854507e298cff3ae3e614d0c9a..924e0a3ec2e965959b41cbbb6337d7bb62d5a6b8 100644 (file)
@@ -1,3 +1,14 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * parser.cc (cp_parser_omp_clause_depend): Parse
+       inoutset depend-kind.
+       (cp_parser_omp_depobj): Likewise.
+       * cxx-pretty-print.cc (cxx_pretty_printer::statement): Handle
+       OMP_CLAUSE_DEPEND_INOUTSET.
+
 2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index 4f9a090e520dc2cdf2e680538612ee64b3442aa3..7e4db2e413b887e08b80a164a5b54c6718bd1ef1 100644 (file)
@@ -2139,6 +2139,9 @@ cxx_pretty_printer::statement (tree t)
              case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
                pp_cxx_ws_string (this, " update(mutexinoutset)");
                break;
+             case OMP_CLAUSE_DEPEND_INOUTSET:
+               pp_cxx_ws_string (this, " update(inoutset)");
+               break;
              case OMP_CLAUSE_DEPEND_LAST:
                pp_cxx_ws_string (this, " destroy");
                break;
index 11193b9d6cdd9aa3294a3d2a574f01e57ea9b3a5..957206cdc0c4f0f5014165d303409357f99f3e71 100644 (file)
@@ -39553,6 +39553,8 @@ cp_parser_omp_clause_depend (cp_parser *parser, tree list, location_t loc)
        kind = OMP_CLAUSE_DEPEND_IN;
       else if (strcmp ("inout", p) == 0)
        kind = OMP_CLAUSE_DEPEND_INOUT;
+      else if (strcmp ("inoutset", p) == 0)
+       kind = OMP_CLAUSE_DEPEND_INOUTSET;
       else if (strcmp ("mutexinoutset", p) == 0)
        kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
       else if (strcmp ("out", p) == 0)
@@ -41856,12 +41858,14 @@ cp_parser_omp_depobj (cp_parser *parser, cp_token *pragma_tok)
                    kind = OMP_CLAUSE_DEPEND_INOUT;
                  else if (!strcmp ("mutexinoutset", p2))
                    kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
+                 else if (!strcmp ("inoutset", p2))
+                   kind = OMP_CLAUSE_DEPEND_INOUTSET;
                }
              if (kind == OMP_CLAUSE_DEPEND_SOURCE)
                {
                  clause = error_mark_node;
-                 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
-                                   "%<mutexinoutset%>");
+                 error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%>, "
+                                   "%<mutexinoutset%> or %<inoutset%>");
                }
              if (!c_parens.require_close (parser))
                cp_parser_skip_to_closing_parenthesis (parser,
index e0af57058d8f12207e30da054dc2bb85338626df..f7614ae6caabadc1dcf9c51e2095bef9161302b3 100644 (file)
@@ -8302,9 +8302,9 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
 {
   tree c;
   gimple *g;
-  size_t n[4] = { 0, 0, 0, 0 };
-  bool unused[4];
-  tree counts[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
+  size_t n[5] = { 0, 0, 0, 0, 0 };
+  bool unused[5];
+  tree counts[5] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
   tree last_iter = NULL_TREE, last_count = NULL_TREE;
   size_t i, j;
   location_t first_loc = UNKNOWN_LOCATION;
@@ -8327,6 +8327,9 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
          case OMP_CLAUSE_DEPEND_DEPOBJ:
            i = 3;
            break;
+         case OMP_CLAUSE_DEPEND_INOUTSET:
+           i = 4;
+           break;
          case OMP_CLAUSE_DEPEND_SOURCE:
          case OMP_CLAUSE_DEPEND_SINK:
            continue;
@@ -8432,14 +8435,14 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
        else
          n[i]++;
       }
-  for (i = 0; i < 4; i++)
+  for (i = 0; i < 5; i++)
     if (counts[i])
       break;
-  if (i == 4)
+  if (i == 5)
     return 0;
 
   tree total = size_zero_node;
-  for (i = 0; i < 4; i++)
+  for (i = 0; i < 5; i++)
     {
       unused[i] = counts[i] == NULL_TREE && n[i] == 0;
       if (counts[i] == NULL_TREE)
@@ -8455,9 +8458,12 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
   if (gimplify_expr (&total, pre_p, NULL, is_gimple_val, fb_rvalue)
       == GS_ERROR)
     return 2;
-  bool is_old = unused[1] && unused[3];
+  bool is_old = unused[1] && unused[3] && unused[4];
   tree totalpx = size_binop (PLUS_EXPR, unshare_expr (total),
                             size_int (is_old ? 1 : 4));
+  if (!unused[4])
+    totalpx = size_binop (PLUS_EXPR, totalpx,
+                         size_binop (MULT_EXPR, counts[4], size_int (2)));
   tree type = build_array_type (ptr_type_node, build_index_type (totalpx));
   tree array = create_tmp_var_raw (type);
   TREE_ADDRESSABLE (array) = 1;
@@ -8503,11 +8509,11 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
       gimplify_and_add (tem, pre_p);
     }
 
-  tree cnts[4];
-  for (j = 4; j; j--)
+  tree cnts[6];
+  for (j = 5; j; j--)
     if (!unused[j - 1])
       break;
-  for (i = 0; i < 4; i++)
+  for (i = 0; i < 5; i++)
     {
       if (i && (i >= j || unused[i - 1]))
        {
@@ -8531,6 +8537,15 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
        }
       gimple_seq_add_stmt (pre_p, g);
     }
+  if (unused[4])
+    cnts[5] = NULL_TREE;
+  else
+    {
+      tree t = size_binop (PLUS_EXPR, total, size_int (5));
+      cnts[5] = create_tmp_var (sizetype);
+      g = gimple_build_assign (cnts[i], t);
+      gimple_seq_add_stmt (pre_p, g);
+    }
 
   last_iter = NULL_TREE;
   tree last_bind = NULL_TREE;
@@ -8553,6 +8568,9 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
          case OMP_CLAUSE_DEPEND_DEPOBJ:
            i = 3;
            break;
+         case OMP_CLAUSE_DEPEND_INOUTSET:
+           i = 4;
+           break;
          case OMP_CLAUSE_DEPEND_SOURCE:
          case OMP_CLAUSE_DEPEND_SINK:
            continue;
@@ -8657,14 +8675,42 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
              return 2;
            if (TREE_VALUE (t) != null_pointer_node)
              TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
+           if (i == 4)
+             {
+               r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
+                           NULL_TREE, NULL_TREE);
+               tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
+                                 NULL_TREE, NULL_TREE);
+               r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
+               tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+                                 void_type_node, r, r2);
+               append_to_statement_list_force (tem, last_body);
+               tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+                                 void_type_node, cnts[i],
+                                 size_binop (PLUS_EXPR, cnts[i],
+                                             size_int (1)));
+               append_to_statement_list_force (tem, last_body);
+               i = 5;
+             }
            r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
                        NULL_TREE, NULL_TREE);
            tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
                              void_type_node, r, TREE_VALUE (t));
            append_to_statement_list_force (tem, last_body);
+           if (i == 5)
+             {
+               r = build4 (ARRAY_REF, ptr_type_node, array,
+                           size_binop (PLUS_EXPR, cnts[i], size_int (1)),
+                           NULL_TREE, NULL_TREE);
+               tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
+               tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
+                                 void_type_node, r, tem);
+               append_to_statement_list_force (tem, last_body);
+             }
            tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
                              void_type_node, cnts[i],
-                             size_binop (PLUS_EXPR, cnts[i], size_int (1)));
+                             size_binop (PLUS_EXPR, cnts[i],
+                                         size_int (1 + (i == 5))));
            append_to_statement_list_force (tem, last_body);
            TREE_VALUE (t) = null_pointer_node;
          }
@@ -8688,12 +8734,38 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
            if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
                               is_gimple_val, fb_rvalue) == GS_ERROR)
              return 2;
+           if (i == 4)
+             {
+               r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
+                           NULL_TREE, NULL_TREE);
+               tree r2 = build4 (ARRAY_REF, ptr_type_node, array, cnts[5],
+                                 NULL_TREE, NULL_TREE);
+               r2 = build_fold_addr_expr_with_type (r2, ptr_type_node);
+               tem = build2 (MODIFY_EXPR, void_type_node, r, r2);
+               gimplify_and_add (tem, pre_p);
+               g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR,
+                                                             cnts[i],
+                                                             size_int (1)));
+               gimple_seq_add_stmt (pre_p, g);
+               i = 5;
+             }
            r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
                        NULL_TREE, NULL_TREE);
            tem = build2 (MODIFY_EXPR, void_type_node, r, OMP_CLAUSE_DECL (c));
            gimplify_and_add (tem, pre_p);
-           g = gimple_build_assign (cnts[i], size_binop (PLUS_EXPR, cnts[i],
-                                                         size_int (1)));
+           if (i == 5)
+             {
+               r = build4 (ARRAY_REF, ptr_type_node, array,
+                           size_binop (PLUS_EXPR, cnts[i], size_int (1)),
+                           NULL_TREE, NULL_TREE);
+               tem = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
+               tem = build2 (MODIFY_EXPR, void_type_node, r, tem);
+               append_to_statement_list_force (tem, last_body);
+               gimplify_and_add (tem, pre_p);
+             }
+           g = gimple_build_assign (cnts[i],
+                                    size_binop (PLUS_EXPR, cnts[i],
+                                                size_int (1 + (i == 5))));
            gimple_seq_add_stmt (pre_p, g);
          }
       }
@@ -8717,7 +8789,7 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
   else
     {
       tree prev = size_int (5);
-      for (i = 0; i < 4; i++)
+      for (i = 0; i < 5; i++)
        {
          if (unused[i])
            continue;
index 04b315d47b6be1441383b0fffe5c5c47e4688828..c366fb55c806b240df8c4d4c3b8099ab3365ca2a 100644 (file)
@@ -13095,7 +13095,7 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
 {
   tree c, clauses;
   gimple *g;
-  size_t cnt[4] = { 0, 0, 0, 0 }, idx = 2, i;
+  size_t cnt[5] = { 0, 0, 0, 0, 0 }, idx = 2, i;
 
   clauses = omp_find_clause (*pclauses, OMP_CLAUSE_DEPEND);
   gcc_assert (clauses);
@@ -13119,16 +13119,20 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
        case OMP_CLAUSE_DEPEND_DEPOBJ:
          cnt[3]++;
          break;
+       case OMP_CLAUSE_DEPEND_INOUTSET:
+         cnt[4]++;
+         break;
        case OMP_CLAUSE_DEPEND_SOURCE:
        case OMP_CLAUSE_DEPEND_SINK:
          /* FALLTHRU */
        default:
          gcc_unreachable ();
        }
-  if (cnt[1] || cnt[3])
+  if (cnt[1] || cnt[3] || cnt[4])
     idx = 5;
-  size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3];
-  tree type = build_array_type_nelts (ptr_type_node, total + idx);
+  size_t total = cnt[0] + cnt[1] + cnt[2] + cnt[3] + cnt[4];
+  size_t inoutidx = total + idx;
+  tree type = build_array_type_nelts (ptr_type_node, total + idx + 2 * cnt[4]);
   tree array = create_tmp_var (type);
   TREE_ADDRESSABLE (array) = 1;
   tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
@@ -13149,7 +13153,7 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
       g = gimple_build_assign (r, build_int_cst (ptr_type_node, cnt[i]));
       gimple_seq_add_stmt (iseq, g);
     }
-  for (i = 0; i < 4; i++)
+  for (i = 0; i < 5; i++)
     {
       if (cnt[i] == 0)
        continue;
@@ -13177,10 +13181,21 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
                if (i != 3)
                  continue;
                break;
+             case OMP_CLAUSE_DEPEND_INOUTSET:
+               if (i != 4)
+                  continue;
+               break;
              default:
                gcc_unreachable ();
              }
            tree t = OMP_CLAUSE_DECL (c);
+           if (i == 4)
+             {
+               t = build4 (ARRAY_REF, ptr_type_node, array,
+                           size_int (inoutidx), NULL_TREE, NULL_TREE);
+               t = build_fold_addr_expr (t);
+               inoutidx += 2;
+             }
            t = fold_convert (ptr_type_node, t);
            gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
            r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
@@ -13189,6 +13204,25 @@ lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
            gimple_seq_add_stmt (iseq, g);
          }
     }
+  if (cnt[4])
+    for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
+      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+         && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_INOUTSET)
+       {
+         tree t = OMP_CLAUSE_DECL (c);
+         t = fold_convert (ptr_type_node, t);
+         gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
+         r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
+                     NULL_TREE, NULL_TREE);
+         g = gimple_build_assign (r, t);
+         gimple_seq_add_stmt (iseq, g);
+         t = build_int_cst (ptr_type_node, GOMP_DEPEND_INOUTSET);
+         r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
+                     NULL_TREE, NULL_TREE);
+         g = gimple_build_assign (r, t);
+         gimple_seq_add_stmt (iseq, g);
+       }
+
   c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
   OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_LAST;
   OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
index 7260dd0c76b6cd075b66eaa879eeabb43bf2c945..0bfd4f2a3b728c58c0c1e093072be583fc287541 100644 (file)
@@ -1,3 +1,15 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * c-c++-common/gomp/all-memory-1.c (boo): Add test with
+       inoutset depend-kind.
+       * c-c++-common/gomp/all-memory-2.c (boo): Likewise.
+       * c-c++-common/gomp/depobj-1.c (f1): Likewise.
+       (f2): Adjusted expected diagnostics.
+       * g++.dg/gomp/depobj-1.C (f4): Adjust expected diagnostics.
+
 2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index 5d63e0d09394386db69b2cd24c4ddb868cf2b03a..0fb457057c4b208c6da216ea42ff026a50c417ed 100644 (file)
@@ -49,4 +49,6 @@ boo (void)
   ;
   #pragma omp task depend(mutexinoutset: omp_all_memory)       /* { dg-error "'omp_all_memory' used with 'depend' kind other than 'out' or 'inout'" } */
   ;
+  #pragma omp task depend(inoutset: omp_all_memory)            /* { dg-error "'omp_all_memory' used with 'depend' kind other than 'out' or 'inout'" } */
+  ;
 }
index 6f5d31be29ca8bfe969e907d262ba35ee57f7bca..99b5945eac51ac95555afabdcff89e2a2313ee0a 100644 (file)
@@ -52,4 +52,6 @@ boo (void)
   ;
   #pragma omp task depend(mutexinoutset: omp_all_memory)
   ;
+  #pragma omp task depend(inoutset: omp_all_memory)
+  ;
 }
index 688371b623203c0b8c090f46d5043683fa91c978..77fd97159aa61464b9cc99b1aa6e95d3b70acc7e 100644 (file)
@@ -21,6 +21,9 @@ f1 (void)
   ;
   #pragma omp depobj(pdepobj[0]) depend(mutexinoutset:a)
   #pragma omp depobj(*pdepobj) destroy
+  #pragma omp depobj(depobja[0]) depend(inoutset: a)
+  #pragma omp depobj(depobja[0]) update(mutexinoutset)
+  #pragma omp depobj(depobja[0]) update(inoutset)
 }
 
 void
@@ -38,7 +41,7 @@ f2 (void)
   #pragma omp depobj (a) destroy                       /* { dg-error "type of 'depobj' expression is not 'omp_depend_t'" } */
   #pragma omp depobj (depobj) depend(depobj:a)         /* { dg-error "does not have 'omp_depend_t' type in 'depend' clause with 'depobj' dependence type" } */
   #pragma omp depobj (depobj) depend(depobj:*depobjb)  /* { dg-error "'depobj' dependence type specified in 'depend' clause on 'depobj' construct" } */
-  #pragma omp depobj (depobj) update(foobar)           /* { dg-error "expected 'in', 'out', 'inout' or 'mutexinoutset'" } */
+  #pragma omp depobj (depobj) update(foobar)           /* { dg-error "expected 'in', 'out', 'inout', 'mutexinoutset' or 'inoutset'" } */
   #pragma omp depobj (depobj) depend(in: *depobja)     /* { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" } */
   #pragma omp depobj (depobj) depend(in: a) depend(in: b)      /* { dg-error "expected" } */
   #pragma omp depobj (depobj) depend(in: a) update(out)        /* { dg-error "expected" } */
index 6004f1e6e6d6f4933ff26efa595f2060f8ecf57a..cb091a1da2cb7b2129232f5ba75a69ec82d9fcd7 100644 (file)
@@ -83,7 +83,7 @@ f4 (void)
   #pragma omp depobj (a) destroy                       // { dg-error "type of 'depobj' expression is not 'omp_depend_t'" }
   #pragma omp depobj (depobj) depend(depobj:a)         // { dg-error "does not have 'omp_depend_t' type in 'depend' clause with 'depobj' dependence type" }
   #pragma omp depobj (depobj) depend(depobj:*depobjb)  // { dg-error "'depobj' dependence type specified in 'depend' clause on 'depobj' construct" }
-  #pragma omp depobj (depobj) update(foobar)           // { dg-error "expected 'in', 'out', 'inout' or 'mutexinoutset'" }
+  #pragma omp depobj (depobj) update(foobar)           // { dg-error "expected 'in', 'out', 'inout', 'mutexinoutset' or 'inoutset'" }
   #pragma omp depobj (depobj) depend(in: *depobja)     // { dg-error "should not have 'omp_depend_t' type in 'depend' clause with dependence type" }
   #pragma omp depobj (depobj) depend(in: a) depend(in: b)      // { dg-error "expected" }
   #pragma omp depobj (depobj) depend(in: a) update(out)        // { dg-error "expected" }
index d0020405cc646af977947ea66ad61c6f4ab101f6..3013db3df7518df21eaa944b4f6c6ccda5eef8cc 100644 (file)
@@ -1541,6 +1541,7 @@ enum omp_clause_depend_kind
   OMP_CLAUSE_DEPEND_OUT,
   OMP_CLAUSE_DEPEND_INOUT,
   OMP_CLAUSE_DEPEND_MUTEXINOUTSET,
+  OMP_CLAUSE_DEPEND_INOUTSET,
   OMP_CLAUSE_DEPEND_SOURCE,
   OMP_CLAUSE_DEPEND_SINK,
   OMP_CLAUSE_DEPEND_DEPOBJ,
index b200be3b34d0698152eab152943125ece44bbe5f..23672082ad6ffefad97caec6298b37b381681399 100644 (file)
@@ -832,6 +832,9 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
        case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
          name = "mutexinoutset";
          break;
+       case OMP_CLAUSE_DEPEND_INOUTSET:
+         name = "inoutset";
+         break;
        case OMP_CLAUSE_DEPEND_SOURCE:
          pp_string (pp, "source)");
          return;
index 4c63f1107eefe87dd47bbdbe1ce88ffbd3eb4dab..6c3b73b44a9f1c743b5ae33717737ed0b1bcdc2e 100644 (file)
@@ -1,3 +1,10 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * gomp-constants.h (GOMP_DEPEND_INOUTSET): Define.
+
 2022-06-21  Kwok Cheung Yeung  <kcy@codesourcery.com>
 
        * cuda/cuda.h (CUdevice_attribute): Add definitions for
@@ -19,7 +26,7 @@
        * dwarf2.def (DW_OP_LLVM_piece_end): New extension operator.
 
 2018-10-04  Cesar Philippidis  <cesar@codesourcery.com>
-            Julian Brown  <julian@codesourcery.com>
+           Julian Brown  <julian@codesourcery.com>
 
        * gomp-constants.h (enum gomp_map_kind): Define
        GOMP_MAP_DECLARE_{ALLOCATE,DEALLOCATE} and GOMP_MAP_FLAG_SPECIAL_4.
index 04e7c08db4767887b6119fbce422c9b404dd17f1..011d2de091dd9b1564b07e42d27c9b9203515278 100644 (file)
@@ -355,6 +355,7 @@ enum gomp_map_kind
 #define GOMP_DEPEND_OUT                        2
 #define GOMP_DEPEND_INOUT              3
 #define GOMP_DEPEND_MUTEXINOUTSET      4
+#define GOMP_DEPEND_INOUTSET           5
 
 /* Flag values for requires-directive features, must match corresponding
    OMP_REQUIRES_* values in gcc/omp-general.h.  */
index ff5d52f87e7da7e8edcb036cbf5c35b7d4fb221b..5e1997de255801ff9181e7c05bfdcd9c7981ec8a 100644 (file)
@@ -1,3 +1,25 @@
+2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
+
+       Backport from mainline:
+       2022-05-17  Jakub Jelinek  <jakub@redhat.com>
+
+       * libgomp.h (struct gomp_task_depend_entry): Change is_in type
+       from bool to unsigned char.
+       * task.c (gomp_task_handle_depend): Handle GOMP_DEPEND_INOUTSET.
+       Ignore dependencies where
+       task->depend[i].is_in && task->depend[i].is_in == ent->is_in
+       rather than just task->depend[i].is_in && ent->is_in.  Remember
+       whether GOMP_DEPEND_IN loop is needed and guard the loop with that
+       conditional.
+       (gomp_task_maybe_wait_for_dependencies): Handle GOMP_DEPEND_INOUTSET.
+       Ignore dependencies where elem.is_in && elem.is_in == ent->is_in
+       rather than just elem.is_in && ent->is_in.
+       * testsuite/libgomp.c-c++-common/depend-1.c (test): Add task with
+       inoutset depend-kind.
+       * testsuite/libgomp.c-c++-common/depend-2.c (test): Likewise.
+       * testsuite/libgomp.c-c++-common/depend-3.c (test): Likewise.
+       * testsuite/libgomp.c-c++-common/depend-inoutset-1.c: New test.
+
 2022-07-04  Tobias Burnus  <tobias@codesourcery.com>
 
        Backport from mainline:
index 53a0244d58c5f894585f9ccb8931bb836aee24f6..77669ed95b03fed3f901b9a4383d66e162737e9d 100644 (file)
@@ -535,8 +535,8 @@ struct gomp_task_depend_entry
   struct gomp_task_depend_entry *prev;
   /* Task that provides the dependency in ADDR.  */
   struct gomp_task *task;
-  /* Depend entry is of type "IN".  */
-  bool is_in;
+  /* Depend entry is of type "IN" (1) or "INOUTSET" (2).  */
+  unsigned char is_in;
   bool redundant;
   bool redundant_out;
 };
index db4a6f71fb76512121192e504f52f89f7ae00b79..e9a28bf71cba9c25689ab9d11937514958c92a7f 100644 (file)
@@ -197,6 +197,7 @@ gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
       /* ndepend - nout - nmutexinoutset - nin is # of depobjs */
       size_t normal = nout + nmutexinoutset + nin;
       size_t n = 0;
+      bool has_in = false;
       for (i = normal; i < ndepend; i++)
        {
          void **d = (void **) (uintptr_t) depend[5 + i];
@@ -209,6 +210,8 @@ gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
            case GOMP_DEPEND_MUTEXINOUTSET:
              break;
            case GOMP_DEPEND_IN:
+           case GOMP_DEPEND_INOUTSET:
+             has_in = true;
              continue;
            default:
              gomp_fatal ("unknown omp_depend_t dependence type %d",
@@ -222,14 +225,17 @@ gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
          task->depend[n].addr = depend[5 + i];
          task->depend[n++].is_in = i >= nout + nmutexinoutset;
        }
-      for (i = normal; i < ndepend; i++)
-       {
-         void **d = (void **) (uintptr_t) depend[5 + i];
-         if ((uintptr_t) d[1] != GOMP_DEPEND_IN)
-           continue;
-         task->depend[n].addr = d[0];
-         task->depend[n++].is_in = 1;
-       }
+      if (has_in)
+       for (i = normal; i < ndepend; i++)
+         {
+           void **d = (void **) (uintptr_t) depend[5 + i];
+           if ((uintptr_t) d[1] != GOMP_DEPEND_IN
+               && (uintptr_t) d[1] != GOMP_DEPEND_INOUTSET)
+             continue;
+           task->depend[n].addr = d[0];
+           task->depend[n++].is_in
+             = 1 + ((uintptr_t) d[1] == GOMP_DEPEND_INOUTSET);
+         }
     }
   task->num_dependees = 0;
   if (__builtin_expect (parent->depend_all_memory && ndepend, false))
@@ -381,8 +387,10 @@ gomp_task_handle_depend (struct gomp_task *task, struct gomp_task *parent,
 
              last = ent;
 
-             /* depend(in:...) doesn't depend on earlier depend(in:...).  */
-             if (task->depend[i].is_in && ent->is_in)
+             /* depend(in:...) doesn't depend on earlier depend(in:...).
+                Similarly depend(inoutset:...) doesn't depend on earlier
+                depend(inoutset:...).  */
+             if (task->depend[i].is_in && task->depend[i].is_in == ent->is_in)
                continue;
 
              if (!ent->is_in)
@@ -1890,6 +1898,9 @@ gomp_task_maybe_wait_for_dependencies (void **depend)
            case GOMP_DEPEND_MUTEXINOUTSET:
              elem.is_in = 0;
              break;
+           case GOMP_DEPEND_INOUTSET:
+             elem.is_in = 2;
+             break;
            default:
              gomp_fatal ("unknown omp_depend_t dependence type %d",
                          (int) (uintptr_t) d[1]);
@@ -1928,7 +1939,7 @@ gomp_task_maybe_wait_for_dependencies (void **depend)
        }
       ent = htab_find (task->depend_hash, &elem);
       for (; ent; ent = ent->next)
-       if (elem.is_in && ent->is_in)
+       if (elem.is_in && elem.is_in == ent->is_in)
          continue;
        else
          {
index 3376b99b18c3db7f52fa785cf483f0b3deda1ced..47d7570a196314bfe2b94feb5273fd5bc86192c2 100644 (file)
@@ -48,6 +48,11 @@ test (int ifval)
       usleep (5000);
       b[4] = 48;
     }
+    #pragma omp task shared(b) depend(inoutset: b[5])
+    {
+      usleep (5000);
+      b[5] = 49;
+    }
     /* None of the above tasks depend on each other.
        The following task depends on all but the a[4] = 46; one.  */
     #pragma omp task shared(a, b) depend(out: omp_all_memory) private(i) if(ifval)
@@ -55,7 +60,7 @@ test (int ifval)
       if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45
          || a[5] != 5 || a[6] != 6 || a[7] != 7
          || b[0] != 47 || b[1] != 2 || b[2] != 4 || b[3] != 6
-         || b[4] != 48 || b[5] != 10 || b[6] != 12 || b[7] != 14)
+         || b[4] != 48 || b[5] != 49 || b[6] != 12 || b[7] != 14)
        abort ();
       for (i = 0; i < 8; ++i)
        if (i != 4)
index d7b533555c43a4df8d181f6740349fc67786e010..2fe867e2c83f0aa11f8435c560c1df94506f982e 100644 (file)
@@ -52,6 +52,11 @@ test (int ifval)
       usleep (5000);
       b[4] = 48;
     }
+    #pragma omp task shared(b) depend(inoutset: b[5])
+    {
+      usleep (5000);
+      b[5] = 49;
+    }
     /* None of the above tasks depend on each other.
        The following task depends on all but the a[4] = 46; one.  */
     #pragma omp task shared(a, b) depend(depobj: d1) private(i) if(ifval)
@@ -59,7 +64,7 @@ test (int ifval)
       if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45
          || a[5] != 5 || a[6] != 6 || a[7] != 7
          || b[0] != 47 || b[1] != 2 || b[2] != 4 || b[3] != 6
-         || b[4] != 48 || b[5] != 10 || b[6] != 12 || b[7] != 14)
+         || b[4] != 48 || b[5] != 49 || b[6] != 12 || b[7] != 14)
        abort ();
       for (i = 0; i < 8; ++i)
        if (i != 4)
index 052e77c81e12e0137c2ea193717d09037db205db..7cfda67318c22870f0e916ba20fd6824b7c664e1 100644 (file)
@@ -48,6 +48,11 @@ main ()
       usleep (5000);
       b[4] = 48;
     }
+    #pragma omp task shared(b) depend(inoutset: b[5])
+    {
+      usleep (5000);
+      b[5] = 49;
+    }
     /* None of the above tasks depend on each other.
        The following task depends on all but the a[4] = 46; one.  */
     #pragma omp task shared(a, b) depend(iterator (j=0:7), inout: omp_all_memory) private(i)
@@ -55,7 +60,7 @@ main ()
       if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45
          || a[5] != 5 || a[6] != 6 || a[7] != 7
          || b[0] != 47 || b[1] != 2 || b[2] != 4 || b[3] != 6
-         || b[4] != 48 || b[5] != 10 || b[6] != 12 || b[7] != 14)
+         || b[4] != 48 || b[5] != 49 || b[6] != 12 || b[7] != 14)
        abort ();
       for (i = 0; i < 8; ++i)
        if (i != 4)
diff --git a/libgomp/testsuite/libgomp.c-c++-common/depend-inoutset-1.c b/libgomp/testsuite/libgomp.c-c++-common/depend-inoutset-1.c
new file mode 100644 (file)
index 0000000..77956f2
--- /dev/null
@@ -0,0 +1,164 @@
+#include <omp.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main ()
+{
+  int a[8] = {};
+  omp_depend_t d1, d2;
+  #pragma omp depobj (d1) depend(inoutset: a)
+  #pragma omp depobj (d2) depend(inout: a)
+  #pragma omp depobj (d2) update(inoutset)
+  #pragma omp parallel
+  {
+    #pragma omp barrier
+    #pragma omp master
+    {
+    #pragma omp task shared(a) depend(out: a)
+    {
+      usleep (5000);
+      a[0] = 1; a[1] = 2; a[2] = 3; a[3] = 4;
+    }
+    /* The above task needs to finish first.  */
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 1 || a[1] != 2 || a[2] != 3 || a[3] != 4)
+       abort ();
+      usleep (5000);
+      a[4] = 42;
+    }
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 1 || a[1] != 2 || a[2] != 3 || a[3] != 4)
+       abort ();
+      usleep (5000);
+      a[5] = 43;
+    }
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 1 || a[1] != 2 || a[2] != 3 || a[3] != 4)
+       abort ();
+      usleep (5000);
+      a[6] = 44;
+    }
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 1 || a[1] != 2 || a[2] != 3 || a[3] != 4)
+       abort ();
+      usleep (5000);
+      a[7] = 45;
+    }
+    /* The above 4 tasks can be scheduled in any order but need to wait
+       for the depend(out: a) task.  */
+    #pragma omp task shared(a) depend(inoutset: a)
+    {
+      if (a[4] != 42 || a[5] != 43 || a[6] != 44 || a[7] != 45)
+       abort ();
+      usleep (5000);
+      a[0] = 42;
+    }
+    #pragma omp task shared(a) depend(iterator(i=1:3:2), inoutset: a)
+    {
+      if (a[4] != 42 || a[5] != 43 || a[6] != 44 || a[7] != 45)
+       abort ();
+      usleep (5000);
+      a[1] = 43;
+    }
+    #pragma omp task shared(a) depend(depobj: d1)
+    {
+      if (a[4] != 42 || a[5] != 43 || a[6] != 44 || a[7] != 45)
+       abort ();
+      usleep (5000);
+      a[2] = 44;
+    }
+    #pragma omp task shared(a) depend(depobj: d2)
+    {
+      if (a[4] != 42 || a[5] != 43 || a[6] != 44 || a[7] != 45)
+       abort ();
+      usleep (5000);
+      a[3] = 45;
+    }
+    /* The above 4 tasks can be scheduled in any order but need to wait
+       for all the above depend(in: a) tasks.  */
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45)
+       abort ();
+      usleep (5000);
+      a[4] = 46;
+    }
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45)
+       abort ();
+      usleep (5000);
+      a[5] = 47;
+    }
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45)
+       abort ();
+      usleep (5000);
+      a[6] = 48;
+    }
+    #pragma omp task shared(a) depend(in: a)
+    {
+      if (a[0] != 42 || a[1] != 43 || a[2] != 44 || a[3] != 45)
+       abort ();
+      usleep (5000);
+      a[7] = 49;
+    }
+    /* The above 4 tasks can be scheduled in any order but need to wait
+       for all the above depend(inoutset: a),
+       depend(iterator(i=1:3:2), inoutset: a), depend(depobj: d1) and
+       depend(depobj: d2) tasks.  */
+    #pragma omp task shared(a) depend(inoutset: a)
+    {
+      if (a[4] != 46|| a[5] != 47 || a[6] != 48 || a[7] != 49)
+       abort ();
+      usleep (5000);
+      a[0] = 50;
+    }
+    /* The above task needs to wait for all the above 4 depend(in: a)
+       tasks.  */
+    #pragma omp task shared(a) depend(out: a)
+    {
+      if (a[0] != 50 || a[4] != 46|| a[5] != 47 || a[6] != 48 || a[7] != 49)
+       abort ();
+      usleep (5000);
+      a[0] = 51;
+    }
+    /* The above task needs to wait for the above depend(inoutset: a) task.  */
+    #pragma omp task shared(a) depend(inoutset: a)
+    {
+      if (a[0] != 51 || a[4] != 46|| a[5] != 47 || a[6] != 48 || a[7] != 49)
+       abort ();
+      usleep (5000);
+      a[0] = 52;
+    }
+    /* The above task needs to wait for the above depend(out: a) task.  */
+    #pragma omp task shared(a) depend(mutexinoutset: a)
+    {
+      if (a[0] != 52 || a[4] != 46|| a[5] != 47 || a[6] != 48 || a[7] != 49)
+       abort ();
+      usleep (5000);
+      a[0] = 53;
+    }
+    /* The above task needs to wait for the above depend(inoutset: a) task.  */
+    #pragma omp task shared(a) depend(inoutset: a)
+    {
+      if (a[0] != 53 || a[4] != 46|| a[5] != 47 || a[6] != 48 || a[7] != 49)
+       abort ();
+      usleep (5000);
+      a[0] = 54;
+    }
+    /* The above task needs to wait for the above
+       depend(mutexinoutset: a) task.  */
+    }
+  }
+  if (a[0] != 54 || a[1] != 43 || a[2] != 44 || a[3] != 45
+      || a[4] != 46|| a[5] != 47 || a[6] != 48 || a[7] != 49)
+    abort ();
+  return 0;
+}