
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.
121 lines
2.7 KiB
C
121 lines
2.7 KiB
C
#include <omp.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
void
|
|
test (int ifval)
|
|
{
|
|
int a[8], b[8], i;
|
|
omp_depend_t d1, d2;
|
|
#pragma omp depobj (d1) depend(inout: omp_all_memory)
|
|
#pragma omp depobj (d2) depend(out: omp_all_memory)
|
|
for (i = 0; i < 8; i++)
|
|
{
|
|
a[i] = i;
|
|
b[i] = 2 * i;
|
|
}
|
|
#pragma omp parallel
|
|
#pragma omp single
|
|
{
|
|
#pragma omp task shared(a) depend(in: a[0])
|
|
{
|
|
usleep (5000);
|
|
a[0] = 42;
|
|
}
|
|
#pragma omp task shared(a) depend(out: a[1])
|
|
{
|
|
usleep (5000);
|
|
a[1] = 43;
|
|
}
|
|
#pragma omp task shared(a) depend(inout: a[2])
|
|
{
|
|
usleep (5000);
|
|
a[2] = 44;
|
|
}
|
|
#pragma omp task shared(a) depend(mutexinoutset: a[3])
|
|
{
|
|
usleep (5000);
|
|
a[3] = 45;
|
|
}
|
|
#pragma omp task shared(a)
|
|
{
|
|
usleep (15000);
|
|
a[4] = 46;
|
|
}
|
|
#pragma omp task shared(b) depend(in: b[0])
|
|
{
|
|
usleep (5000);
|
|
b[0] = 47;
|
|
}
|
|
#pragma omp task shared(b) depend(in: b[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] != 49 || b[6] != 12 || b[7] != 14)
|
|
abort ();
|
|
for (i = 0; i < 8; ++i)
|
|
if (i != 4)
|
|
a[i] = 3 * i + 7;
|
|
for (i = 0; i < 8; ++i)
|
|
b[i] = 4 * i - 7;
|
|
}
|
|
/* 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. */
|
|
#pragma omp task shared(b) depend(inout: b[0])
|
|
{
|
|
usleep (5000);
|
|
b[0] = 49;
|
|
}
|
|
/* 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. */
|
|
#pragma omp task shared(a, b) depend(inout: b[6]) depend(depobj: d2) \
|
|
depend(out: b[7]) private(i) if(ifval)
|
|
{
|
|
for (i = 0; i < 8; ++i)
|
|
if (i != 4)
|
|
{
|
|
if (a[i] != 3 * i + 7)
|
|
abort ();
|
|
a[i] = 5 * i + 50;
|
|
}
|
|
if (b[0] != 49)
|
|
abort ();
|
|
b[0] = 6 * i + 57;
|
|
for (i = 1; i < 8; ++i)
|
|
{
|
|
if (b[i] != 4 * i - 7)
|
|
abort ();
|
|
b[i] = 6 * i + 57;
|
|
}
|
|
}
|
|
#pragma omp taskwait
|
|
if (a[4] != 46)
|
|
abort ();
|
|
}
|
|
#pragma omp depobj (d2) destroy
|
|
#pragma omp depobj (d1) destroy
|
|
}
|
|
|
|
int
|
|
main ()
|
|
{
|
|
test (1);
|
|
test (0);
|
|
return 0;
|
|
}
|