gcc/libgomp/testsuite/libgomp.c-c++-common/allocate-3.c
Jakub Jelinek f38b20d68f openmp: Add support for firstprivate and allocate clauses on scope construct
OpenMP 5.2 adds support for firstprivate and allocate clauses on the scope
construct and this patch adds that support to GCC.
5.2 unfortunately (IMNSHO mistakenly) marked scope construct as worksharing,
which implies that it isn't possible to nest inside of it other scope,
worksharing loop, sections, explicit barriers, single etc. which would
make scope far less useful.  I'm not implementing that part, keeping the
5.1 behavior here, and will file an issue to revert that for OpenMP 6.0.
But, for firstprivate it keeps the restriction that is now implied from
worksharing construct that listed var can't be private in outer context,
where for reduction 5.1 had similar restriction explicit even for scope
and 5.2 has it implicitly through worksharing construct.

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

gcc/
	* omp-low.cc (build_outer_var_ref): For code == OMP_CLAUSE_ALLOCATE
	allow var to be private in the outer context.
	(lower_private_allocate): Pass OMP_CLAUSE_ALLOCATE as last argument
	to build_outer_var_ref.
gcc/c/
	* c-parser.cc (OMP_SCOPE_CLAUSE_MASK): Add firstprivate and allocate
	clauses.
gcc/cp/
	* parser.cc (OMP_SCOPE_CLAUSE_MASK): Add firstprivate and allocate
	clauses.
gcc/testsuite/
	* c-c++-common/gomp/scope-5.c: New test.
	* c-c++-common/gomp/scope-6.c: New test.
	* g++.dg/gomp/attrs-1.C (bar): Add firstprivate and allocate clauses
	to scope construct.
	* g++.dg/gomp/attrs-2.C (bar): Likewise.
libgomp/
	* testsuite/libgomp.c-c++-common/allocate-1.c (foo): Add testcase for
	scope construct with allocate clause.
	* testsuite/libgomp.c-c++-common/allocate-3.c (foo): Likewise.
	* testsuite/libgomp.c-c++-common/scope-2.c: New test.
2022-05-31 11:41:52 +02:00

438 lines
12 KiB
C

#include <omp.h>
#include <stdlib.h>
#include <stdint.h>
struct S { int a, b; };
void
foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl)
{
int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
int i2, j2, n2 = 9, l4;
int i3, j3, n3 = 10, l5;
int i4, j4, n4 = 11, l6;
int i5, n5;
int v[x], w[x];
int r2[4] = { 0, 0, 0, 0 };
int xo = x;
struct S s = { 27, 29 };
for (i = 0; i < 4; i++)
p[i] = 0;
for (i = 0; i < 3; i++)
q[i] = 0;
for (i = 0; i < x; i++)
w[i] = i;
#pragma omp parallel private (y, v) firstprivate (x) allocate (align (32) : x) allocate (align (128) : y) allocate (v)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
v[0] = 7;
v[41] = 8;
#pragma omp barrier
if (x != 43 || y != 1)
abort ();
if (v[0] != 7 || v[41] != 8)
abort ();
if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2
| (uintptr_t) &v[0]) & 63) != 0)
abort ();
if ((((uintptr_t) p1) & 31) != 0)
abort ();
if ((((uintptr_t) p2) & 127) != 0)
abort ();
}
x = xo;
#pragma omp teams
#pragma omp parallel private (y) firstprivate (x, w) allocate (allocator (h), align (32) : x) allocate (align (128), allocator (h):y) allocate(allocator(h):w)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42 || w[17] != 17 || w[41] != 41)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
w[19]++;
#pragma omp barrier
if (x != 43 || y != 1 || w[19] != 20)
abort ();
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
| (uintptr_t) &w[0]) & 63) != 0)
abort ();
if ((((uintptr_t) p1) & 31) != 0)
abort ();
if ((((uintptr_t) p2) & 127) != 0)
abort ();
}
x = xo;
#pragma omp parallel for private (y) firstprivate (x) allocate (allocator (h), align (32) : x, y, r) allocate (align (128), allocator (h) : l, n) reduction(+: r) lastprivate (l) linear (n: 16)
for (i = 0; i < 64; i++)
{
if (x != 42)
abort ();
y = 1;
l = i;
n += y + 15;
r += i;
if ((fl & 1) && (((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r
| (uintptr_t) &l | (uintptr_t) &n) & 63) != 0)
abort ();
if ((((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r) & 31) != 0)
abort ();
if ((((uintptr_t) &l | (uintptr_t) &n) & 127) != 0)
abort ();
}
x = xo;
#pragma omp parallel
{
#pragma omp for lastprivate (l2) private (i1) allocate (allocator (h): l2, l3) allocate (allocator (h),align(16): i1) lastprivate (conditional: l3)
for (i1 = 0; i1 < 64; i1++)
{
l2[0] = i1;
l2[1] = i1 + 1;
l2[2] = i1 + 2;
l2[3] = i1 + 3;
if (i1 < 37)
l3 = i1;
if ((fl & 1) && (((uintptr_t) &l2[0] | (uintptr_t) &l3 | (uintptr_t) &i1) & 63) != 0)
abort ();
if ((((uintptr_t) &i1) & 15) != 0)
abort ();
}
#pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (allocator (h), align (8): n2, l4, i2, j2)
for (i2 = 3; i2 < 5; i2++)
for (j2 = 17; j2 < 22; j2 += 2)
{
n2 += 17;
l4 = i2 * 31 + j2;
if ((fl & 1) && (((uintptr_t) &l4 | (uintptr_t) &n2
| (uintptr_t) &i2 | (uintptr_t) &j2) & 63) != 0)
abort ();
if ((((uintptr_t) &l4 | (uintptr_t) &n2 | (uintptr_t) &i2 | (uintptr_t) &j2) & 7) != 0)
abort ();
}
#pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (align (16): n3, l5, i3, j3)
for (i3 = 3; i3 < 5; i3++)
for (j3 = 17; j3 < 23; j3 += 2)
{
n3 += 17;
l5 = i3 * 31 + j3;
if ((fl & 2) && (((uintptr_t) &l5 | (uintptr_t) &n3
| (uintptr_t) &i3 | (uintptr_t) &j3) & 63) != 0)
abort ();
if ((((uintptr_t) &l5 | (uintptr_t) &n3 | (uintptr_t) &i3 | (uintptr_t) &j3) & 15) != 0)
abort ();
}
#pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (align (16), allocator (h): n4, l6, i4, j4)
for (i4 = 3; i4 < 5; i4++)
for (j4 = 17; j4 < 22; j4 += 2)
{
n4 += 17;
l6 = i4 * 31 + j4;
if ((fl & 1) && (((uintptr_t) &l6 | (uintptr_t) &n4
| (uintptr_t) &i4 | (uintptr_t) &j4) & 63) != 0)
abort ();
if ((((uintptr_t) &l6 | (uintptr_t) &n4 | (uintptr_t) &i4 | (uintptr_t) &j4) & 15) != 0)
abort ();
}
#pragma omp for lastprivate (i5) allocate (align (32): i5)
for (i5 = 1; i5 < 17; i5 += 3)
{
if ((fl & 2) && (((uintptr_t) &i5) & 63) != 0)
abort ();
if ((((uintptr_t) &i5) & 31) != 0)
abort ();
}
#pragma omp for reduction(+:p[2:px], q[:3], r2) allocate(align (16), allocator (h): p, q, r2)
for (i = 0; i < 32; i++)
{
p[2] += i;
p[3] += 2 * i;
q[0] += 3 * i;
q[2] += 4 * i;
r2[0] += 5 * i;
r2[3] += 6 * i;
/* Can't really rely on alignment of &p[0], the implementation could
allocate the whole array or do what GCC does and allocate only part
of it. */
if ((fl & 1) && (((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 63) != 0)
abort ();
if ((((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 15) != 0)
abort ();
}
#pragma omp task private(y) firstprivate(x) allocate(align (8) : x, y)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42)
abort ();
p1[0]++;
p2[0] = 21;
if (x != 43 || y != 21)
abort ();
if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0)
abort ();
if ((((uintptr_t) p1 | (uintptr_t) p2) & 7) != 0)
abort ();
}
#pragma omp task private(y) firstprivate(x) allocate(allocator (h),align(32): x, y)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42)
abort ();
p1[0]++;
p2[0] = 21;
if (x != 43 || y != 21)
abort ();
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0)
abort ();
if ((((uintptr_t) p1 | (uintptr_t) p2) & 31) != 0)
abort ();
}
#pragma omp task private(y) firstprivate(s) allocate(align(16): s, y)
{
int *volatile p1 = &s.a;
int *volatile p2 = &s.b;
int *volatile p3 = &y;
if (s.a != 27 || s.b != 29)
abort ();
p1[0]++;
p2[0]++;
p3[0] = 21;
if (s.a != 28 || s.b != 30 || y != 21)
abort ();
if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p3) & 63) != 0)
abort ();
if ((((uintptr_t) p1 | (uintptr_t) p3) & 15) != 0)
abort ();
}
#pragma omp task private(y) firstprivate(s) allocate(allocator (h): s, y)
{
int *volatile p1 = &s.a;
int *volatile p2 = &s.b;
int *volatile p3 = &y;
if (s.a != 27 || s.b != 29)
abort ();
p1[0]++;
p2[0]++;
p3[0] = 21;
if (s.a != 28 || s.b != 30 || y != 21)
abort ();
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p3) & 63) != 0)
abort ();
}
}
if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
abort ();
if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
abort ();
if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
abort ();
if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
abort ();
if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
abort ();
if (i5 != 19)
abort ();
if (p[2] != (32 * 31) / 2 || p[3] != 2 * (32 * 31) / 2
|| q[0] != 3 * (32 * 31) / 2 || q[2] != 4 * (32 * 31) / 2
|| r2[0] != 5 * (32 * 31) / 2 || r2[3] != 6 * (32 * 31) / 2)
abort ();
r = 0;
x = xo;
#pragma omp parallel shared (x, y, r, n5) firstprivate (h)
{
#pragma omp masked
n5 = omp_get_num_threads ();
#pragma omp scope private (y) firstprivate (x) reduction(+:r) \
allocate (allocator (h), align (32): x) \
allocate (align (128), allocator (h): y) \
allocate (align (32), allocator (h): r)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
r++;
#pragma omp barrier
if (x != 43 || y != 1 || r != 1)
abort ();
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
| (uintptr_t) &r) & 63) != 0)
abort ();
if ((((uintptr_t) p1 | (uintptr_t) &r) & 31) != 0)
abort ();
if ((((uintptr_t) p2) & 127) != 0)
abort ();
}
}
if (x != 42 || r != n5)
abort ();
}
void
bar (int x, omp_allocator_handle_t h)
{
int y = 0, r = 0, i, i1, l, l2[4], l3, n = 8;
int i2, j2, n2 = 9, l4;
int i3, j3, n3 = 10, l5;
int i4, j4, n4 = 11, l6;
int i5;
struct S s = { 27, 29 };
int xo = x;
#pragma omp parallel private (y) firstprivate (x) allocate (x, y)
{
if (x != 42)
abort ();
#pragma omp barrier
y = 1;
x++;
#pragma omp barrier
if (x != 43 || y != 1)
abort ();
}
x = xo;
#pragma omp teams
#pragma omp parallel private (y) firstprivate (x) allocate (allocator (h): x, y)
{
if (x != 42)
abort ();
#pragma omp barrier
y = 1;
x++;
#pragma omp barrier
if (x != 43 || y != 1)
abort ();
}
x = xo;
#pragma omp parallel for private (y) firstprivate (x) allocate (allocator (h): x, y, r, l, n) reduction(+: r) lastprivate (l) linear (n: 16)
for (i = 0; i < 64; i++)
{
if (x != 42)
abort ();
y = 1;
l = i;
n += y + 15;
r += i;
}
x = xo;
#pragma omp parallel
{
#pragma omp for lastprivate (l2) private (i1) allocate (allocator (h): l2, l3, i1) lastprivate (conditional: l3)
for (i1 = 0; i1 < 64; i1++)
{
l2[0] = i1;
l2[1] = i1 + 1;
l2[2] = i1 + 2;
l2[3] = i1 + 3;
if (i1 < 37)
l3 = i1;
}
#pragma omp for collapse(2) lastprivate(l4, i2, j2) linear (n2:17) allocate (allocator (h): n2, l4, i2, j2)
for (i2 = 3; i2 < 5; i2++)
for (j2 = 17; j2 < 22; j2 += 2)
{
n2 += 17;
l4 = i2 * 31 + j2;
}
#pragma omp for collapse(2) lastprivate(l5, i3, j3) linear (n3:17) schedule (static, 3) allocate (n3, l5, i3, j3)
for (i3 = 3; i3 < 5; i3++)
for (j3 = 17; j3 < 23; j3 += 2)
{
n3 += 17;
l5 = i3 * 31 + j3;
}
#pragma omp for collapse(2) lastprivate(l6, i4, j4) linear (n4:17) schedule (dynamic) allocate (allocator (h): n4, l6, i4, j4)
for (i4 = 3; i4 < 5; i4++)
for (j4 = 17; j4 < 22; j4 += 2)
{
n4 += 17;
l6 = i4 * 31 + j4;
}
#pragma omp for lastprivate (i5) allocate (i5)
for (i5 = 1; i5 < 17; i5 += 3)
;
#pragma omp task private(y) firstprivate(x) allocate(x, y)
{
if (x != 42)
abort ();
x++;
y = 21;
if (x != 43 || y != 21)
abort ();
}
#pragma omp task private(y) firstprivate(x) allocate(allocator (h): x, y)
{
if (x != 42)
abort ();
x++;
y = 21;
if (x != 43 || y != 21)
abort ();
}
#pragma omp task private(y) firstprivate(s) allocate(s, y)
{
if (s.a != 27 || s.b != 29)
abort ();
s.a++;
s.b++;
y = 21;
if (s.a != 28 || s.b != 30 || y != 21)
abort ();
}
#pragma omp task private(y) firstprivate(s) allocate(allocator (h), align (16): s, y)
{
if (s.a != 27 || s.b != 29)
abort ();
s.a++;
s.b++;
y = 21;
if (s.a != 28 || s.b != 30 || y != 21)
abort ();
}
}
if (r != 64 * 63 / 2 || l != 63 || n != 8 + 16 * 64)
abort ();
if (l2[0] != 63 || l2[1] != 63 + 1 || l2[2] != 63 + 2 || l2[3] != 63 + 3 || l3 != 36)
abort ();
if (i2 != 5 || j2 != 23 || n2 != 9 + 6 * 17 || l4 != 4 * 31 + 21)
abort ();
if (i3 != 5 || j3 != 23 || n3 != 10 + 6 * 17 || l5 != 4 * 31 + 21)
abort ();
if (i4 != 5 || j4 != 23 || n4 != 11 + 6 * 17 || l6 != 4 * 31 + 21)
abort ();
if (i5 != 19)
abort ();
}
int
main ()
{
omp_alloctrait_t traits[3]
= { { omp_atk_alignment, 64 },
{ omp_atk_fallback, omp_atv_null_fb } };
omp_allocator_handle_t a
= omp_init_allocator (omp_default_mem_space, 2, traits);
int p[4], q[3];
if (a == omp_null_allocator)
abort ();
omp_set_default_allocator (omp_default_mem_alloc);
foo (42, p, q, 2, omp_null_allocator, 0);
foo (42, p, q, 2, omp_default_mem_alloc, 0);
foo (42, p, q, 2, a, 1);
omp_set_default_allocator (a);
foo (42, p, q, 2, omp_null_allocator, 3);
foo (42, p, q, 2, omp_default_mem_alloc, 2);
bar (42, a);
omp_destroy_allocator (a);
return 0;
}