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);
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;
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 ) */
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)
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);
}
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;
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)
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,
{
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;
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;
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)
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;
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]))
{
}
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;
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;
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;
}
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);
}
}
else
{
tree prev = size_int (5);
- for (i = 0; i < 4; i++)
+ for (i = 0; i < 5; i++)
{
if (unused[i])
continue;
{
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);
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,
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;
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++),
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);
;
#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'" } */
+ ;
}
;
#pragma omp task depend(mutexinoutset: omp_all_memory)
;
+ #pragma omp task depend(inoutset: omp_all_memory)
+ ;
}
;
#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
#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" } */
#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" }
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,
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;
#define GOMP_DEPEND_OUT 2
#define GOMP_DEPEND_INOUT 3
#define GOMP_DEPEND_MUTEXINOUTSET 4
+#define GOMP_DEPEND_INOUTSET 5
/* HSA specific data structures. */
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;
};
/* 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];
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",
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))
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)
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]);
}
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
{
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)
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)
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)
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)
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)
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)
--- /dev/null
+#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;
+}