From a4dd85e01599890286d9af5b106a1ab20e51169e Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Sat, 14 Nov 2020 01:46:16 +0100 Subject: [PATCH] openmp: Add support for non-VLA {,first}private allocate on omp task This patch adds support for custom allocators on private/firstprivate clauses for task (and taskloop) constructs. Private didn't need anything special, but firstprivate if it is passed by reference needs the GOMP_alloc calls in the copyfn and GOMP_free in the task body. 2020-11-14 Jakub Jelinek * gimplify.c (gimplify_omp_for): Add OMP_CLAUSE_ALLOCATE_ALLOCATOR decls as firstprivate on task clauses even when allocate clause decl is not lastprivate. * omp-low.c (install_var_field): Don't dereference omp_is_reference types if mask is 33 rather than 1. (scan_sharing_clauses): Populate allocate_map even for task constructs. For now remove it back for variables mentioned in reduction and in_reduction clauses on task/taskloop constructs or on VLA task firstprivates. For firstprivate on task construct, install the var field into field_map with by_ref and 33 instead of false and 1 if mentioned in allocate clause. (lower_private_allocate): Set TREE_THIS_NOTRAP on the created MEM_REF. (lower_rec_input_clauses): Handle allocate for task firstprivatized non-VLA variables. (create_task_copyfn): Likewise. * testsuite/libgomp.c-c++-common/allocate-1.c (struct S): New type. (foo): Add tests for non-VLA private and firstprivate clauses on omp task. (bar): Likewise. Remove taking of address from private/firstprivate variables. * testsuite/libgomp.c++/allocate-1.C (struct S): New type. (foo): Add p, q, px and s arguments. Add tests for array reductions and for non-VLA private and firstprivate clauses on omp task. (bar): Removed. (main): Adjust foo caller. Don't call bar. --- gcc/gimplify.c | 24 +-- gcc/omp-low.c | 108 +++++++++-- libgomp/testsuite/libgomp.c++/allocate-1.C | 169 ++++++++++-------- .../libgomp.c-c++-common/allocate-1.c | 112 +++++++++++- 4 files changed, 300 insertions(+), 113 deletions(-) diff --git a/gcc/gimplify.c b/gcc/gimplify.c index b861e17d8ae..2566ec7f0af 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -12463,22 +12463,22 @@ gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) /* Allocate clause we duplicate on task and inner taskloop if the decl is lastprivate, otherwise just put on task. */ case OMP_CLAUSE_ALLOCATE: + if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) + && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))) + { + /* Additionally, put firstprivate clause on task + for the allocator if it is not constant. */ + *gtask_clauses_ptr + = build_omp_clause (OMP_CLAUSE_LOCATION (c), + OMP_CLAUSE_FIRSTPRIVATE); + OMP_CLAUSE_DECL (*gtask_clauses_ptr) + = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c); + gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr); + } if (lastprivate_uids && bitmap_bit_p (lastprivate_uids, DECL_UID (OMP_CLAUSE_DECL (c)))) { - if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) - && DECL_P (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c))) - { - /* Additionally, put firstprivate clause on task - for the allocator if it is not constant. */ - *gtask_clauses_ptr - = build_omp_clause (OMP_CLAUSE_LOCATION (c), - OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (*gtask_clauses_ptr) - = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c); - gtask_clauses_ptr = &OMP_CLAUSE_CHAIN (*gtask_clauses_ptr); - } *gfor_clauses_ptr = c; gfor_clauses_ptr = &OMP_CLAUSE_CHAIN (c); *gtask_clauses_ptr = copy_node (c); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index a1604e0ee3c..09a8cbdc433 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -803,7 +803,7 @@ install_var_field (tree var, bool by_ref, int mask, omp_context *ctx) } else if (by_ref) type = build_pointer_type (type); - else if ((mask & 3) == 1 && omp_is_reference (var)) + else if ((mask & (32 | 3)) == 1 && omp_is_reference (var)) type = TREE_TYPE (type); field = build_decl (DECL_SOURCE_LOCATION (var), @@ -1141,8 +1141,6 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) /* omp_default_mem_alloc is 1 */ || !integer_onep (OMP_CLAUSE_ALLOCATE_ALLOCATOR (c)))) { - if (is_task_ctx (ctx)) - continue; /* For now. */ if (ctx->allocate_map == NULL) ctx->allocate_map = new hash_map; ctx->allocate_map->put (OMP_CLAUSE_DECL (c), @@ -1222,18 +1220,20 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) ctx->local_reduction_clauses = tree_cons (NULL, c, ctx->local_reduction_clauses); } - if ((OMP_CLAUSE_REDUCTION_INSCAN (c) - || OMP_CLAUSE_REDUCTION_TASK (c)) && ctx->allocate_map) + /* FALLTHRU */ + + case OMP_CLAUSE_IN_REDUCTION: + decl = OMP_CLAUSE_DECL (c); + if (ctx->allocate_map + && ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION + && (OMP_CLAUSE_REDUCTION_INSCAN (c) + || OMP_CLAUSE_REDUCTION_TASK (c))) + || is_task_ctx (ctx))) { - tree decl = OMP_CLAUSE_DECL (c); /* For now. */ if (ctx->allocate_map->get (decl)) ctx->allocate_map->remove (decl); } - /* FALLTHRU */ - - case OMP_CLAUSE_IN_REDUCTION: - decl = OMP_CLAUSE_DECL (c); if (TREE_CODE (decl) == MEM_REF) { tree t = TREE_OPERAND (decl, 0); @@ -1317,7 +1317,16 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) if (is_variable_sized (decl)) { if (is_task_ctx (ctx)) - install_var_field (decl, false, 1, ctx); + { + if (ctx->allocate_map + && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) + { + /* For now. */ + if (ctx->allocate_map->get (decl)) + ctx->allocate_map->remove (decl); + } + install_var_field (decl, false, 1, ctx); + } break; } else if (is_taskreg_ctx (ctx)) @@ -1329,7 +1338,11 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) if (is_task_ctx (ctx) && (global || by_ref || omp_is_reference (decl))) { - install_var_field (decl, false, 1, ctx); + if (ctx->allocate_map + && ctx->allocate_map->get (decl)) + install_var_field (decl, by_ref, 32 | 1, ctx); + else + install_var_field (decl, false, 1, ctx); if (!global) install_var_field (decl, by_ref, 2, ctx); } @@ -4498,7 +4511,9 @@ lower_private_allocate (tree var, tree new_var, tree &allocator, gimple_seq_add_stmt (ilist, g); if (!is_ref) { - SET_DECL_VALUE_EXPR (new_var, build_simple_mem_ref (allocate_ptr)); + tree x = build_simple_mem_ref (allocate_ptr); + TREE_THIS_NOTRAP (x) = 1; + SET_DECL_VALUE_EXPR (new_var, x); DECL_HAS_VALUE_EXPR_P (new_var) = 1; } return true; @@ -5409,7 +5424,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx)) { x = build_receiver_ref (var, false, ctx); - x = build_fold_addr_expr_loc (clause_loc, x); + if (ctx->allocate_map) + if (tree *allocatep = ctx->allocate_map->get (var)) + { + allocator = *allocatep; + if (TREE_CODE (allocator) != INTEGER_CST) + allocator = build_outer_var_ref (allocator, ctx); + allocator = fold_convert (pointer_sized_int_node, + allocator); + allocate_ptr = unshare_expr (x); + } + if (allocator == NULL_TREE) + x = build_fold_addr_expr_loc (clause_loc, x); } else if (lower_private_allocate (var, new_var, allocator, allocate_ptr, @@ -5676,6 +5702,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, gimplify_and_add (x, dlist); if (allocator) { + if (!is_gimple_val (allocator)) + { + tree avar = create_tmp_var (TREE_TYPE (allocator)); + gimplify_assign (avar, allocator, dlist); + allocator = avar; + } + if (!is_gimple_val (allocate_ptr)) + { + tree apvar = create_tmp_var (TREE_TYPE (allocate_ptr)); + gimplify_assign (apvar, allocate_ptr, dlist); + allocate_ptr = apvar; + } tree f = builtin_decl_explicit (BUILT_IN_GOMP_FREE); gimple *g = gimple_build_call (f, 2, allocate_ptr, allocator); @@ -5704,6 +5742,18 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, || use_pointer_for_field (var, NULL)) { x = build_receiver_ref (var, false, ctx); + if (ctx->allocate_map) + if (tree *allocatep = ctx->allocate_map->get (var)) + { + allocator = *allocatep; + if (TREE_CODE (allocator) != INTEGER_CST) + allocator = build_outer_var_ref (allocator, ctx); + allocator = fold_convert (pointer_sized_int_node, + allocator); + allocate_ptr = unshare_expr (x); + x = build_simple_mem_ref (x); + TREE_THIS_NOTRAP (x) = 1; + } SET_DECL_VALUE_EXPR (new_var, x); DECL_HAS_VALUE_EXPR_P (new_var) = 1; goto do_dtor; @@ -11290,7 +11340,35 @@ create_task_copyfn (gomp_task *task_stmt, omp_context *ctx) if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE) t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); else - t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src); + { + if (ctx->allocate_map) + if (tree *allocatorp = ctx->allocate_map->get (decl)) + { + tree allocator = *allocatorp; + if (TREE_CODE (allocator) != INTEGER_CST) + { + n = splay_tree_lookup (ctx->sfield_map, + (splay_tree_key) allocator); + allocator = (tree) n->value; + if (tcctx.cb.decl_map) + allocator = *tcctx.cb.decl_map->get (allocator); + tree a = build_simple_mem_ref_loc (loc, sarg); + allocator = omp_build_component_ref (a, allocator); + } + allocator = fold_convert (pointer_sized_int_node, allocator); + tree a = builtin_decl_explicit (BUILT_IN_GOMP_ALLOC); + tree align = build_int_cst (size_type_node, + DECL_ALIGN_UNIT (decl)); + tree sz = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dst))); + tree ptr = build_call_expr_loc (loc, a, 3, align, sz, + allocator); + ptr = fold_convert (TREE_TYPE (dst), ptr); + t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, ptr); + append_to_statement_list (t, &list); + dst = build_simple_mem_ref_loc (loc, dst); + } + t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src); + } append_to_statement_list (t, &list); break; case OMP_CLAUSE_PRIVATE: diff --git a/libgomp/testsuite/libgomp.c++/allocate-1.C b/libgomp/testsuite/libgomp.c++/allocate-1.C index ee89f31b6b3..0876719f0a1 100644 --- a/libgomp/testsuite/libgomp.c++/allocate-1.C +++ b/libgomp/testsuite/libgomp.c++/allocate-1.C @@ -2,17 +2,26 @@ #include #include +struct S { int a, b; }; + void -foo (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocator_handle_t h, int fl) +foo (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, int *&p, + int *&q, int &px, struct S &s, omp_allocator_handle_t h, int fl) { int i; typedef int T[x]; T v, w; T &v2 = v; T &w2 = w; + int r1[4] = { 0, 0, 0, 0 }; + int (&r2)[4] = r1; int xo = x; for (i = 0; i < x; i++) w[i] = i; + for (i = 0; i < 4; i++) + p[i] = 0; + for (i = 0; i < 3; i++) + q[i] = 0; #pragma omp parallel private (y, v2) firstprivate (x) allocate (x, y, v2) { int *volatile p1 = &x; @@ -66,6 +75,7 @@ foo (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocato | (uintptr_t) &l | (uintptr_t) &n) & 63) != 0) abort (); } + x = xo; #pragma omp parallel { #pragma omp for lastprivate (l2) allocate (h: l2, l3) lastprivate (conditional: l3) @@ -80,84 +90,86 @@ foo (int &x, int &y, int &r, int &l, int (&l2)[4], int &l3, int &n, omp_allocato 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++) + #pragma omp for reduction(+:p[2:px], q[:3], r2) allocate(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 (); + } + #pragma omp task private(y) firstprivate(x) allocate(x, y) { + int *volatile p1 = &x; + int *volatile p2 = &y; if (x != 42) abort (); - y = 1; - l = i; - n += y + 15; - r += i; + p1[0]++; + p2[0] = 21; + if (x != 43 || y != 21) + abort (); + if ((fl & 2) && (((uintptr_t) p1 | (uintptr_t) p2) & 63) != 0) + abort (); + } + #pragma omp task private(y) firstprivate(x) allocate(h: 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 (); + } + #pragma omp task private(y) firstprivate(s) allocate(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 (); + } + #pragma omp task private(y) firstprivate(s) allocate(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 (); } - #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 (); + 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 (); } int @@ -171,24 +183,25 @@ main () if (a == omp_null_allocator) abort (); omp_set_default_allocator (omp_default_mem_alloc); + struct S s = { 27, 29 }; + int p1[4], q1[3], px = 2; + int *p = p1; + int *q = q1; 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); + foo (x, y, r, l, l2, l3, n, p, q, px, s, 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); + foo (x, y, r, l, l2, l3, n, p, q, px, s, 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); + foo (x, y, r, l, l2, l3, n, p, q, px, s, 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); + foo (x, y, r, l, l2, l3, n, p, q, px, s, 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; - bar (x, y, r, l, l2, l3, n, a); + foo (x, y, r, l, l2, l3, n, p, q, px, s, omp_default_mem_alloc, 2); omp_destroy_allocator (a); return 0; } diff --git a/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c b/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c index 5dd51b5a2b9..4398ff957ef 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c +++ b/libgomp/testsuite/libgomp.c-c++-common/allocate-1.c @@ -2,6 +2,8 @@ #include #include +struct S { int a, b; }; + void foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl) { @@ -13,6 +15,7 @@ foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl) 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++) @@ -72,6 +75,7 @@ foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl) | (uintptr_t) &l | (uintptr_t) &n) & 63) != 0) abort (); } + x = xo; #pragma omp parallel { #pragma omp for lastprivate (l2) private (i1) allocate (h: l2, l3, i1) lastprivate (conditional: l3) @@ -137,6 +141,62 @@ foo (int x, int *p, int *q, int px, omp_allocator_handle_t h, int fl) if ((fl & 1) && (((uintptr_t) &q[0] | (uintptr_t) &r2[0]) & 63) != 0) abort (); } + #pragma omp task private(y) firstprivate(x) allocate(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 (); + } + #pragma omp task private(y) firstprivate(x) allocate(h: 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 (); + } + #pragma omp task private(y) firstprivate(s) allocate(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 (); + } + #pragma omp task private(y) firstprivate(s) allocate(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 (); @@ -164,16 +224,15 @@ bar (int x, omp_allocator_handle_t h) 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) { - int *volatile p1 = &x; - int *volatile p2 = &y; if (x != 42) abort (); #pragma omp barrier - *p2 = 1; - p1[0]++; + y = 1; + x++; #pragma omp barrier if (x != 43 || y != 1) abort (); @@ -182,13 +241,11 @@ bar (int x, omp_allocator_handle_t h) #pragma omp teams #pragma omp parallel private (y) firstprivate (x) allocate (h: x, y) { - int *volatile p1 = &x; - int *volatile p2 = &y; if (x != 42) abort (); #pragma omp barrier - *p2 = 1; - p1[0]++; + y = 1; + x++; #pragma omp barrier if (x != 43 || y != 1) abort (); @@ -204,6 +261,7 @@ bar (int x, omp_allocator_handle_t h) n += y + 15; r += i; } + x = xo; #pragma omp parallel { #pragma omp for lastprivate (l2) private (i1) allocate (h: l2, l3, i1) lastprivate (conditional: l3) @@ -240,6 +298,44 @@ bar (int x, omp_allocator_handle_t h) #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(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(h: 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 (); -- 2.30.2