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.
(cherry picked from commit
f38b20d68fade5a922b9f68c4c3841e653d1b83c)
+2022-07-05 Tobias Burnus <tobias@codesourcery.com>
+
+ Backport from mainline:
+ 2022-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2022-07-05 Tobias Burnus <tobias@codesourcery.com>
Backport from mainline:
+2022-07-05 Tobias Burnus <tobias@codesourcery.com>
+
+ Backport from mainline:
+ 2022-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.cc (OMP_SCOPE_CLAUSE_MASK): Add firstprivate and allocate
+ clauses.
+
2022-07-05 Tobias Burnus <tobias@codesourcery.com>
Backport from mainline:
#define OMP_SCOPE_CLAUSE_MASK \
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
+2022-07-05 Tobias Burnus <tobias@codesourcery.com>
+
+ Backport from mainline:
+ 2022-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * parser.cc (OMP_SCOPE_CLAUSE_MASK): Add firstprivate and allocate
+ clauses.
+
2022-07-05 Tobias Burnus <tobias@codesourcery.com>
Backport from mainline:
#define OMP_SCOPE_CLAUSE_MASK \
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
else if ((gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
&& gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_SIMD)
|| ctx->loop_p
+ || code == OMP_CLAUSE_ALLOCATE
|| (code == OMP_CLAUSE_PRIVATE
&& (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
|| gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS
if (is_task_ctx (ctx))
allocator = build_receiver_ref (allocator, false, ctx);
else
- allocator = build_outer_var_ref (allocator, ctx);
+ allocator = build_outer_var_ref (allocator, ctx, OMP_CLAUSE_ALLOCATE);
}
allocator = fold_convert (pointer_sized_int_node, allocator);
if (TREE_CODE (allocator) != INTEGER_CST)
+2022-07-05 Tobias Burnus <tobias@codesourcery.com>
+
+ Backport from mainline:
+ 2022-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * 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.
+
2022-07-05 Tobias Burnus <tobias@codesourcery.com>
Backport from mainline:
--- /dev/null
+/* { dg-do compile } */
+
+void
+foo ()
+{
+ int f = 0;
+ #pragma omp scope firstprivate(f) /* { dg-error "firstprivate variable 'f' is private in outer context" } */
+ f++;
+}
--- /dev/null
+typedef enum omp_allocator_handle_t
+#if __cplusplus >= 201103L
+: __UINTPTR_TYPE__
+#endif
+{
+ omp_null_allocator = 0,
+ omp_default_mem_alloc = 1,
+ omp_large_cap_mem_alloc = 2,
+ omp_const_mem_alloc = 3,
+ omp_high_bw_mem_alloc = 4,
+ omp_low_lat_mem_alloc = 5,
+ omp_cgroup_mem_alloc = 6,
+ omp_pteam_mem_alloc = 7,
+ omp_thread_mem_alloc = 8,
+ __omp_allocator_handle_t_max__ = __UINTPTR_MAX__
+} omp_allocator_handle_t;
+
+int a = 0, b = 42, c = 0;
+
+void
+foo (omp_allocator_handle_t h)
+{
+ #pragma omp scope private (a) private (b) reduction (+: c) allocate (allocator (h): a, b, c)
+ {
+ if (b != 42)
+ __builtin_abort ();
+ a = 36;
+ b = 15;
+ c++;
+ }
+}
[[omp::directive (cancellation point parallel)]];
}
}
- [[omp::directive (scope private (p) reduction(+:r) nowait)]]
+ [[omp::directive (scope private (p) firstprivate (f) reduction(+:r) nowait
+ allocate (omp_default_mem_alloc: r))]]
;
- [[omp::directive (scope private (p) reduction(task, +:r))]]
+ [[omp::directive (scope private (p) firstprivate (f) reduction(task, +:r)
+ allocate (omp_default_mem_alloc: f))]]
;
extern int t2;
[[omp::directive (threadprivate (t2))]];
[[omp::directive (cancellation point, parallel)]];
}
}
- [[omp::directive (scope, private (p), reduction(+:r), nowait)]]
+ [[omp::directive (scope, private (p), firstprivate (f), reduction(+:r), nowait,
+ allocate(omp_default_mem_alloc: r))]]
;
- [[using omp:directive (scope, private (p), reduction(task, +:r))]]
+ [[using omp:directive (scope, private (p), firstprivate (f), reduction(task, +:r),
+ allocate (omp_default_mem_alloc: f))]]
;
extern int t2;
[[omp::directive (threadprivate (t2))]];
+2022-07-05 Tobias Burnus <tobias@codesourcery.com>
+
+ Backport from mainline:
+ 2022-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ * 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-07-05 Tobias Burnus <tobias@codesourcery.com>
Backport from mainline:
int i2, j2, n2 = 9, l4;
int i3, j3, n3 = 10, l5;
int i4, j4, n4 = 11, l6;
- int i5;
+ int i5, n5;
int v[x], w[x];
int r2[4] = { 0, 0, 0, 0 };
int xo = x;
|| 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 (h: x, y, r)
+ {
+ int *volatile p1 = &x;
+ int *volatile p2 = &y;
+ int *volatile p3 = &r;
+ if (x != 42)
+ abort ();
+ #pragma omp barrier
+ *p2 = 1;
+ p1[0]++;
+ p3[0]++;
+ #pragma omp barrier
+ if (x != 43 || y != 1 || r != 1)
+ abort ();
+ if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
+ | (uintptr_t) p3) & 63) != 0)
+ abort ();
+ }
+ }
+ if (x != 42 || r != n5)
+ abort ();
}
void
int i2, j2, n2 = 9, l4;
int i3, j3, n3 = 10, l5;
int i4, j4, n4 = 11, l6;
- int i5;
+ int i5, n5;
int v[x], w[x];
int r2[4] = { 0, 0, 0, 0 };
int xo = x;
|| 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
--- /dev/null
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort ();
+
+int
+main ()
+{
+ int a[64] = {};
+ int r = 0, r2 = 0, i, n = 64;
+ #pragma omp parallel
+ {
+ #pragma omp scope nowait
+ #pragma omp scope nowait firstprivate (n)
+ #pragma omp for
+ for (i = 0; i < 64; i++)
+ a[i] += 1;
+ #pragma omp scope reduction(+: r) nowait firstprivate (n)
+ {
+ #pragma omp for nowait
+ for (i = 0; i < 64; i++)
+ {
+ r += i;
+ if (a[i] != 1)
+ abort ();
+ }
+ #pragma omp barrier
+ if (n != 64)
+ abort ();
+ else
+ n = 128;
+ }
+ #pragma omp barrier
+ if (r != 64 * 63 / 2)
+ abort ();
+ #pragma omp scope nowait private (i)
+ #pragma omp scope reduction(+: r2)
+ {
+ #pragma omp for nowait
+ for (i = 0; i < 64; i++)
+ {
+ r2 += 2 * i;
+ a[i] += i;
+ }
+ }
+ if (r2 != 64 * 63)
+ abort ();
+ #pragma omp for nowait
+ for (i = 0; i < 64; i++)
+ if (a[i] != i + 1)
+ abort ();
+ }
+ return 0;
+}