gcc/libgomp/testsuite/libgomp.c++/allocate-1.C

195 lines
4.8 KiB
C++
Raw Normal View History

openmp: Implement allocate clause in omp lowering. For now, task/taskloop constructs aren't handled and C/C++ array reductions and reductions with task or inscan modifiers need further work. Instead of calling omp_alloc/omp_free (where the former doesn't have alignment argument and omp_aligned_alloc is 5.1 only feature), this calls GOMP_alloc/GOMP_free, so that the library can fail if it would fall back into NULL (exception is zero length allocations). 2020-11-12 Jakub Jelinek <jakub@redhat.com> gcc/ * builtin-types.def (BT_FN_PTR_SIZE_SIZE_PTRMODE): New function type. * omp-builtins.def (BUILT_IN_GOACC_DECLARE): Move earlier. (BUILT_IN_GOMP_ALLOC, BUILT_IN_GOMP_FREE): New builtins. * gimplify.c (gimplify_scan_omp_clauses): Force allocator into a decl if it is not NULL, INTEGER_CST or decl. (gimplify_adjust_omp_clauses): Clear GOVD_EXPLICIT on explicit clauses which are being removed. Remove allocate clauses for variables not seen if they are private, firstprivate or linear too. Call omp_notice_variable on the allocator otherwise. (gimplify_omp_for): Handle iterator vars mentioned in allocate clauses similarly to non-is_gimple_reg iterators. * omp-low.c (struct omp_context): Add allocate_map field. (delete_omp_context): Delete it. (scan_sharing_clauses): Fill it from allocate clauses. Remove it if mentioned also in shared clause. (lower_private_allocate): New function. (lower_rec_input_clauses): Handle allocate clause for privatized variables, except for task/taskloop, C/C++ array reductions for now and task/inscan variables. (lower_send_shared_vars): Don't consider variables in allocate_map as shared. * omp-expand.c (expand_omp_for_generic, expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Use expand_omp_build_assign instead of gimple_build_assign + gsi_insert_after. * builtins.c (builtin_fnspec): Handle BUILTIN_GOMP_ALLOC and BUILTIN_GOMP_FREE. * tree-ssa-ccp.c (evaluate_stmt): Handle BUILTIN_GOMP_ALLOC. * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Handle BUILTIN_GOMP_ALLOC. (mark_all_reaching_defs_necessary_1): Handle BUILTIN_GOMP_ALLOC and BUILTIN_GOMP_FREE. (propagate_necessity): Likewise. gcc/fortran/ * f95-lang.c (ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LIST): Define. (gfc_init_builtin_functions): Add alloc_size and warn_unused_result attributes to __builtin_GOMP_alloc. * types.def (BT_PTRMODE): New primitive type. (BT_FN_VOID_PTR_PTRMODE, BT_FN_PTR_SIZE_SIZE_PTRMODE): New function types. libgomp/ * libgomp.map (GOMP_alloc, GOMP_free): Export at GOMP_5.0.1. * omp.h.in (omp_alloc): Add malloc and alloc_size attributes. * libgomp_g.h (GOMP_alloc, GOMP_free): Declare. * allocator.c (omp_aligned_alloc): New for now static function, add alignment argument and handle it. (omp_alloc): Reimplement using omp_aligned_alloc. (GOMP_alloc, GOMP_free): New functions. (omp_free): Add ialias. * testsuite/libgomp.c-c++-common/allocate-1.c: New test. * testsuite/libgomp.c++/allocate-1.C: New test.
2020-11-13 04:38:04 +08:00
#include <omp.h>
#include <stdlib.h>
#include <stdint.h>
void
foo (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocator_handle_t h, int fl)
{
int i;
typedef int T[x];
T v, w;
T &v2 = v;
T &w2 = w;
int xo = x;
for (i = 0; i < x; i++)
w[i] = i;
#pragma omp parallel private (y, v2) firstprivate (x) allocate (x, y, v2)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
v2[0] = 7;
v2[41] = 8;
#pragma omp barrier
if (x != 43 || y != 1)
abort ();
if (v2[0] != 7 || v2[41] != 8)
abort ();
if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2
| (uintptr_t) &v2[0]) & 63) != 0)
abort ();
}
x = xo;
#pragma omp teams
#pragma omp parallel private (y) firstprivate (x, w2) allocate (h: x, y, w2)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42 || w2[17] != 17 || w2[41] != 41)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
w2[19]++;
#pragma omp barrier
if (x != 43 || y != 1 || w2[19] != 20)
abort ();
if ((fl & 1) && (((uintptr_t) p1 | (uintptr_t) p2
| (uintptr_t) &w2[0]) & 63) != 0)
abort ();
}
x = xo;
#pragma omp parallel for private (y) firstprivate (x) allocate (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;
if ((fl & 1) && (((uintptr_t) &x | (uintptr_t) &y | (uintptr_t) &r
| (uintptr_t) &l | (uintptr_t) &n) & 63) != 0)
abort ();
}
#pragma omp parallel
{
#pragma omp for lastprivate (l2) allocate (h: l2, l3) lastprivate (conditional: l3)
for (i = 0; i < 64; i++)
{
l2[0] = i;
l2[1] = i + 1;
l2[2] = i + 2;
l2[3] = i + 3;
if (i < 37)
l3 = i;
if ((fl & 1) && (((uintptr_t) &l2[0] | (uintptr_t) &l3) & 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 ();
}
void
bar (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocator_handle_t h)
{
int i;
typedef int T[x];
T v, w;
T &v2 = v;
T &w2 = w;
int xo = x;
for (i = 0; i < x; i++)
w[i] = i;
#pragma omp parallel private (y, v2) firstprivate (x) allocate (x, y, v2)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
v2[0] = 7;
v2[41] = 8;
#pragma omp barrier
if (x != 43 || y != 1)
abort ();
if (v2[0] != 7 || v2[41] != 8)
abort ();
}
x = xo;
#pragma omp teams
#pragma omp parallel private (y) firstprivate (x, w2) allocate (h: x, y, w2)
{
int *volatile p1 = &x;
int *volatile p2 = &y;
if (x != 42 || w2[17] != 17 || w2[41] != 41)
abort ();
#pragma omp barrier
*p2 = 1;
p1[0]++;
#pragma omp barrier
if (x != 43 || y != 1)
abort ();
}
x = xo;
#pragma omp parallel for private (y) firstprivate (x) allocate (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;
}
#pragma omp parallel
{
#pragma omp for lastprivate (l2) allocate (h: l2, l3) lastprivate (conditional: l3)
for (i = 0; i < 64; i++)
{
l2[0] = i;
l2[1] = i + 1;
l2[2] = i + 2;
l2[3] = i + 3;
if (i < 37)
l3 = i;
}
}
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 ();
}
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);
if (a == omp_null_allocator)
abort ();
omp_set_default_allocator (omp_default_mem_alloc);
int x = 42, y = 0, r = 0, l, l2[4], l3, n = 8;
foo (x, y, r, l, l2, l3, n, omp_null_allocator, 0);
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
l2[2] = -1; l2[3] = -1; n = 8;
foo (x, y, r, l, l2, l3, n, omp_default_mem_alloc, 0);
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
l2[2] = -1; l2[3] = -1; n = 8;
foo (x, y, r, l, l2, l3, n, a, 1);
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
l2[2] = -1; l2[3] = -1; n = 8;
omp_set_default_allocator (a);
foo (x, y, r, l, l2, l3, n, omp_null_allocator, 3);
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
l2[2] = -1; l2[3] = -1; n = 8;
foo (x, y, r, l, l2, l3, n, omp_default_mem_alloc, 2);
x = 42; y = 0; r = 0; l = -1; l2[0] = -1; l2[1] = -1;
l2[2] = -1; l2[3] = -1; n = 8;
bar (x, y, r, l, l2, l3, n, a);
omp_destroy_allocator (a);
return 0;
}