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)
+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.
+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/
(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.
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;
+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.
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);
}
+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:
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);
+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:
;
#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;
+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
* 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.
#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. */
+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:
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;
+}