On Fri, Jul 17, 2015 at 06:43:06PM +0200, Jakub Jelinek wrote: > > BTW, do you plan to remove GOMP_MAP_POINTER mappings from array sections? > > The enter/exit patch for libgomp depends on this change. > > My current plan (for Monday and onwards) is to first implement firstprivate > on target construct, once that works hack on the GOMP_MAP_POINTER > replacement, and then rewrite the gimplification rules for target construct > for the new 2.15.5 rules (so that this one does not really break all the > target tests we need the first two working somehow).
Ok, so here is the first part of that, GOMP_MAP_FIRSTPRIVATE support as a way to support firstprivate/is_device_ptr clauses on target construct (and private clause too, though that is compiler only change). firstprivate VLAs aren't supported yet, but that will be a compiler only change. I'll commit this patch tomorrow. 2015-07-20 Jakub Jelinek <ja...@redhat.com> gcc/ * omp-low.c (scan_sharing_clauses): Handle firstprivate and is_device_ptr clauses on target region. (lower_omp_target): Handle OMP_CLAUSE_FIRSTPRIVATE, OMP_CLAUSE_IS_DEVICE_PTR and OMP_CLAUSE_PRIVATE. include/ * gomp-constants.h (enum gomp_map_kind): Add GOMP_MAP_FIRSTPRIVATE. libgomp/ * target.c (gomp_map_vars): Handle GOMP_MAP_FIRSTPRIVATE. * testsuite/libgomp.c/target-13.c: New test. * testsuite/libgomp.c/target-14.c: New test. * testsuite/libgomp.c++/target-5.C: New test. * testsuite/libgomp.c++/target-6.C: New test. --- gcc/omp-low.c.jj 2015-07-16 18:09:25.000000000 +0200 +++ gcc/omp-low.c 2015-07-20 17:43:33.271401254 +0200 @@ -1930,6 +1930,10 @@ scan_sharing_clauses (tree clauses, omp_ else if (!global) install_var_field (decl, by_ref, 3, ctx); } + else if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR) + && is_gimple_omp_offloaded (ctx->stmt)) + install_var_field (decl, !is_reference (decl), 3, ctx); install_var_local (decl, ctx); if (is_gimple_omp_oacc (ctx->stmt) && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) @@ -12929,6 +12933,21 @@ lower_omp_target (gimple_stmt_iterator * DECL_HAS_VALUE_EXPR_P (new_var) = 1; } map_cnt++; + break; + + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_IS_DEVICE_PTR: + map_cnt++; + var = OMP_CLAUSE_DECL (c); + if (!is_reference (var) + && !is_gimple_reg_type (TREE_TYPE (var))) + { + x = build_receiver_ref (var, true, ctx); + tree new_var = lookup_decl (var, ctx); + SET_DECL_VALUE_EXPR (new_var, x); + DECL_HAS_VALUE_EXPR_P (new_var) = 1; + } + break; } if (offloaded) @@ -12994,7 +13013,8 @@ lower_omp_target (gimple_stmt_iterator * for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) switch (OMP_CLAUSE_CODE (c)) { - tree ovar, nc; + tree ovar, nc, s, purpose, var, x; + unsigned int talign; default: break; @@ -13037,13 +13057,13 @@ lower_omp_target (gimple_stmt_iterator * continue; } - unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar)); + talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar)); if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign) talign = DECL_ALIGN_UNIT (ovar); if (nc) { - tree var = lookup_decl_in_outer_ctx (ovar, ctx); - tree x = build_sender_ref (ovar, ctx); + var = lookup_decl_in_outer_ctx (ovar, ctx); + x = build_sender_ref (ovar, ctx); if (maybe_lookup_oacc_reduction (var, ctx)) { gcc_checking_assert (offloaded @@ -13092,11 +13112,11 @@ lower_omp_target (gimple_stmt_iterator * gimplify_assign (x, var, &ilist); } } - tree s = OMP_CLAUSE_SIZE (c); + s = OMP_CLAUSE_SIZE (c); if (s == NULL_TREE) s = TYPE_SIZE_UNIT (TREE_TYPE (ovar)); s = fold_convert (size_type_node, s); - tree purpose = size_int (map_idx++); + purpose = size_int (map_idx++); CONSTRUCTOR_APPEND_ELT (vsize, purpose, s); if (TREE_CODE (s) != INTEGER_CST) TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0; @@ -13126,6 +13146,52 @@ lower_omp_target (gimple_stmt_iterator * build_int_cstu (tkind_type, tkind)); if (nc && nc != c) c = nc; + break; + + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_IS_DEVICE_PTR: + ovar = OMP_CLAUSE_DECL (c); + if (is_reference (ovar)) + talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar))); + else + talign = DECL_ALIGN_UNIT (ovar); + var = lookup_decl_in_outer_ctx (ovar, ctx); + x = build_sender_ref (ovar, ctx); + if (is_reference (var)) + gimplify_assign (x, var, &ilist); + else if (is_gimple_reg (var)) + { + tree avar = create_tmp_var (TREE_TYPE (var)); + mark_addressable (avar); + gimplify_assign (avar, var, &ilist); + avar = build_fold_addr_expr (avar); + gimplify_assign (x, avar, &ilist); + } + else + { + var = build_fold_addr_expr (var); + gimplify_assign (x, var, &ilist); + } + if (is_reference (var)) + s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar))); + else + s = TYPE_SIZE_UNIT (TREE_TYPE (ovar)); + s = fold_convert (size_type_node, s); + purpose = size_int (map_idx++); + CONSTRUCTOR_APPEND_ELT (vsize, purpose, s); + if (TREE_CODE (s) != INTEGER_CST) + TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0; + + tkind = GOMP_MAP_FIRSTPRIVATE; + gcc_checking_assert (tkind + < (HOST_WIDE_INT_C (1U) << talign_shift)); + talign = ceil_log2 (talign); + tkind |= talign << talign_shift; + gcc_checking_assert (tkind + <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type))); + CONSTRUCTOR_APPEND_ELT (vkind, purpose, + build_int_cstu (tkind_type, tkind)); + break; } gcc_assert (map_idx == map_cnt); @@ -13173,6 +13239,57 @@ lower_omp_target (gimple_stmt_iterator * if (offloaded) { + for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) + switch (OMP_CLAUSE_CODE (c)) + { + tree var; + default: + break; + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_IS_DEVICE_PTR: + var = OMP_CLAUSE_DECL (c); + if (is_reference (var) + || is_gimple_reg_type (TREE_TYPE (var))) + { + tree new_var = lookup_decl (var, ctx); + tree x = build_receiver_ref (var, !is_reference (var), ctx); + gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue); + gimple_seq_add_stmt (&new_body, + gimple_build_assign (new_var, x)); + } + break; + case OMP_CLAUSE_PRIVATE: + var = OMP_CLAUSE_DECL (c); + if (is_reference (var)) + { + location_t clause_loc = OMP_CLAUSE_LOCATION (c); + tree new_var = lookup_decl (var, ctx); + tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var))); + if (TREE_CONSTANT (x)) + { + const char *name = NULL; + if (DECL_NAME (var)) + name = IDENTIFIER_POINTER (DECL_NAME (new_var)); + + x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)), + name); + gimple_add_tmp_var (x); + TREE_ADDRESSABLE (x) = 1; + x = build_fold_addr_expr_loc (clause_loc, x); + } + else + { + tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA); + x = build_call_expr_loc (clause_loc, atmp, 1, x); + } + + x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x); + gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue); + gimple_seq_add_stmt (&new_body, + gimple_build_assign (new_var, x)); + } + break; + } gimple_seq_add_seq (&new_body, tgt_body); new_body = maybe_catch_exception (new_body); } --- include/gomp-constants.h.jj 2015-06-23 16:23:45.000000000 +0200 +++ include/gomp-constants.h 2015-07-20 12:27:58.103210763 +0200 @@ -72,6 +72,8 @@ enum gomp_map_kind /* Is a device pointer. OMP_CLAUSE_SIZE for these is unused; is implicitly POINTER_SIZE_UNITS. */ GOMP_MAP_FORCE_DEVICEPTR = (GOMP_MAP_FLAG_SPECIAL_1 | 0), + /* Do not map, copy bits for firstprivate instead. */ + GOMP_MAP_FIRSTPRIVATE = (GOMP_MAP_FLAG_SPECIAL | 0), /* Allocate. */ GOMP_MAP_FORCE_ALLOC = (GOMP_MAP_FLAG_FORCE | GOMP_MAP_ALLOC), /* ..., and copy to device. */ --- libgomp/target.c.jj 2015-07-15 13:00:32.000000000 +0200 +++ libgomp/target.c 2015-07-20 16:03:20.745931639 +0200 @@ -243,6 +243,7 @@ gomp_map_vars (struct gomp_device_descr bool short_mapkind, bool is_target) { size_t i, tgt_align, tgt_size, not_found_cnt = 0; + bool has_firstprivate = false; const int rshift = short_mapkind ? 8 : 3; const int typemask = short_mapkind ? 0xff : 0x7; struct splay_tree_s *mem_map = &devicep->mem_map; @@ -280,6 +281,18 @@ gomp_map_vars (struct gomp_device_descr cur_node.host_end = cur_node.host_start + sizes[i]; else cur_node.host_end = cur_node.host_start + sizeof (void *); + if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE) + { + tgt->list[i].key = NULL; + + size_t align = (size_t) 1 << (kind >> rshift); + if (tgt_align < align) + tgt_align = align; + tgt_size = (tgt_size + align - 1) & ~(align - 1); + tgt_size += cur_node.host_end - cur_node.host_start; + has_firstprivate = true; + continue; + } splay_tree_key n = splay_tree_lookup (mem_map, &cur_node); if (n) gomp_map_vars_existing (devicep, n, &cur_node, &tgt->list[i], @@ -348,9 +361,10 @@ gomp_map_vars (struct gomp_device_descr tgt_size = mapnum * sizeof (void *); tgt->array = NULL; - if (not_found_cnt) + if (not_found_cnt || has_firstprivate) { - tgt->array = gomp_malloc (not_found_cnt * sizeof (*tgt->array)); + if (not_found_cnt) + tgt->array = gomp_malloc (not_found_cnt * sizeof (*tgt->array)); splay_tree_node array = tgt->array; size_t j; @@ -360,6 +374,18 @@ gomp_map_vars (struct gomp_device_descr int kind = get_kind (short_mapkind, kinds, i); if (hostaddrs[i] == NULL) continue; + if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE) + { + size_t align = (size_t) 1 << (kind >> rshift); + tgt_size = (tgt_size + align - 1) & ~(align - 1); + tgt->list[i].offset = tgt_size; + size_t len = sizes[i]; + devicep->host2dev_func (devicep->target_id, + (void *) (tgt->tgt_start + tgt_size), + (void *) hostaddrs[i], len); + tgt_size += len; + continue; + } splay_tree_key k = &array->key; k->host_start = (uintptr_t) hostaddrs[i]; if (!GOMP_MAP_POINTER_P (kind & typemask)) @@ -491,7 +517,13 @@ gomp_map_vars (struct gomp_device_descr for (i = 0; i < mapnum; i++) { if (tgt->list[i].key == NULL) - cur_node.tgt_offset = (uintptr_t) NULL; + { + if (hostaddrs[i] == NULL) + cur_node.tgt_offset = (uintptr_t) NULL; + else + cur_node.tgt_offset = tgt->tgt_start + + tgt->list[i].offset; + } else cur_node.tgt_offset = tgt->list[i].key->tgt->tgt_start + tgt->list[i].key->tgt_offset; --- libgomp/testsuite/libgomp.c/target-13.c.jj 2015-07-20 16:07:28.259375318 +0200 +++ libgomp/testsuite/libgomp.c/target-13.c 2015-07-20 16:26:05.828330031 +0200 @@ -0,0 +1,45 @@ +#ifdef __cplusplus +extern "C" +#else +extern +#endif +void abort (void); +struct S { int s, t; }; + +void +foo () +{ + int x = 5, y = 6, err = 0; + struct S u = { 7, 8 }, v = { 9, 10 }; + double s = 11.5, t = 12.5; + #pragma omp target private (x, u, s) firstprivate (y, v, t) map(from:err) + { + x = y; + u = v; + s = t; + err = (x != 6 || y != 6 + || u.s != 9 || u.t != 10 || v.s != 9 || v.t != 10 + || s != 12.5 || t != 12.5); + x += 1; + y += 2; + u.s += 3; + v.t += 4; + s += 2.5; + t += 3.0; + if (x != 7 || y != 8 + || u.s != 12 || u.t != 10 || v.s != 9 || v.t != 14 + || s != 15.0 || t != 15.5) + err = 1; + } + if (err || x != 5 || y != 6 + || u.s != 7 || u.t != 8 || v.s != 9 || v.t != 10 + || s != 11.5 || t != 12.5) + abort (); +} + +int +main () +{ + foo (); + return 0; +} --- libgomp/testsuite/libgomp.c/target-14.c.jj 2015-07-20 17:44:51.443299100 +0200 +++ libgomp/testsuite/libgomp.c/target-14.c 2015-07-20 17:49:20.745483458 +0200 @@ -0,0 +1,38 @@ +#include <omp.h> +#include <stdlib.h> + +int +main () +{ + int d = omp_get_default_device (); + int id = omp_get_initial_device (); + int err; + void *p; + + if (d < 0 || d >= omp_get_num_devices ()) + d = id; + + p = omp_target_alloc (128 * sizeof (int), d); + if (p == NULL) + return 0; + + #pragma omp target is_device_ptr (p) if (d >= 0) device (d >= 0 ? d : 0) + { + int i, *q = (int *) p; + for (i = 0; i < 128; i++) + q[i] = i + 7; + } + #pragma omp target is_device_ptr (p) if (d >= 0) device (d >= 0 ? d : 0) map(from:err) + { + int i; + err = 0; + for (i = 0; i < 128; i++) + if (((int *) p)[i] != i + 7) + err = 1; + } + if (err) + abort (); + + omp_target_free (p, d); + return 0; +} --- libgomp/testsuite/libgomp.c++/target-5.C.jj 2015-07-20 16:23:39.592423836 +0200 +++ libgomp/testsuite/libgomp.c++/target-5.C 2015-07-20 16:26:31.049968908 +0200 @@ -0,0 +1 @@ +#include "../libgomp.c/target-13.c" --- libgomp/testsuite/libgomp.c++/target-6.C.jj 2015-07-20 16:26:44.196780672 +0200 +++ libgomp/testsuite/libgomp.c++/target-6.C 2015-07-20 17:36:18.357533147 +0200 @@ -0,0 +1,64 @@ +extern "C" void abort (void); +struct S { int s, t; }; + +void +foo (int &x, int &y, S &u, S &v, double &s, double &t) +{ + int err = 0, i; + int a[y - 2], b[y - 2]; + int (&c)[y - 2] = a, (&d)[y - 2] = b; + for (i = 0; i < y - 2; i++) + { + c[i] = i; + d[i] = 3 + i; + } + #pragma omp target private (x, u, s, c, i) firstprivate (y, v, t, d) map(from:err) + { + x = y; + u = v; + s = t; + for (i = 0; i < y - 2; i++) + c[i] = d[i]; + err = (x != 6 || y != 6 + || u.s != 9 || u.t != 10 || v.s != 9 || v.t != 10 + || s != 12.5 || t != 12.5); + for (i = 0; i < y - 2; i++) + if (d[i] != 3 + i || c[i] != 3 + i) + err = 1; + else + { + c[i] += 2 * i; + d[i] += i; + } + x += 1; + y += 2; + u.s += 3; + v.t += 4; + s += 2.5; + t += 3.0; + if (x != 7 || y != 8 + || u.s != 12 || u.t != 10 || v.s != 9 || v.t != 14 + || s != 15.0 || t != 15.5) + err = 1; + for (i = 0; i < y - 4; i++) + if (d[i] != 3 + 2 * i || c[i] != 3 + 3 * i) + err = 1; + } + if (err || x != 5 || y != 6 + || u.s != 7 || u.t != 8 || v.s != 9 || v.t != 10 + || s != 11.5 || t != 12.5) + abort (); + for (i = 0; i < y - 2; i++) + if (d[i] != 3 + i || c[i] != i) + abort (); +} + +int +main () +{ + int x = 5, y = 6; + S u = { 7, 8 }, v = { 9, 10 }; + double s = 11.5, t = 12.5; + foo (x, y, u, v, s, t); + return 0; +} Jakub