Hi! And here is untested incremental libgomp side of the proposed GOMP_MAP_FIRSTPRIVATE_POINTER. I'll probably tweak it so that if GOMP_MAP_FIRSTPRIVATE is followed by one or more GOMP_MAP_FIRSTPRIVATE_POINTER where the pointers fall into the extents of the firstprivate object, it will make the whole object firstprivate and then overwrite the pointers in it (somewhat similar to GOMP_MAP_TO_PSET).
--- include/gomp-constants.h.jj 2015-07-20 12:27:58.000000000 +0200 +++ include/gomp-constants.h 2015-07-20 19:43:47.734326985 +0200 @@ -74,6 +74,8 @@ enum gomp_map_kind 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), + /* Do not map, but pointer assign a pointer instead. */ + GOMP_MAP_FIRSTPRIVATE_POINTER = (GOMP_MAP_FLAG_SPECIAL | 1), /* Allocate. */ GOMP_MAP_FORCE_ALLOC = (GOMP_MAP_FLAG_FORCE | GOMP_MAP_ALLOC), /* ..., and copy to device. */ --- libgomp/target.c.jj 2015-07-20 16:03:20.000000000 +0200 +++ libgomp/target.c 2015-07-20 19:57:38.735556137 +0200 @@ -276,12 +276,8 @@ gomp_map_vars (struct gomp_device_descr tgt->list[i].key = NULL; continue; } - cur_node.host_start = (uintptr_t) hostaddrs[i]; - if (!GOMP_MAP_POINTER_P (kind & typemask)) - 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) + if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE + || (kind & typemask) == GOMP_MAP_FIRSTPRIVATE_POINTER) { tgt->list[i].key = NULL; @@ -289,10 +285,18 @@ gomp_map_vars (struct gomp_device_descr 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; + if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE_POINTER) + tgt_size += sizeof (void *); + else + tgt_size += sizes[i]; has_firstprivate = true; continue; } + cur_node.host_start = (uintptr_t) hostaddrs[i]; + if (!GOMP_MAP_POINTER_P (kind & typemask)) + cur_node.host_end = cur_node.host_start + sizes[i]; + else + cur_node.host_end = cur_node.host_start + sizeof (void *); splay_tree_key n = splay_tree_lookup (mem_map, &cur_node); if (n) gomp_map_vars_existing (devicep, n, &cur_node, &tgt->list[i], @@ -374,15 +378,28 @@ 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) + if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE + || (kind & typemask) == GOMP_MAP_FIRSTPRIVATE_POINTER) { 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); + size_t len; + if ((kind & typemask) == GOMP_MAP_FIRSTPRIVATE_POINTER) + { + len = sizeof (void *); + gomp_map_pointer (tgt, (uintptr_t) + *(void **) (hostaddrs[i]), + tgt_size, sizes[i]); + } + else + { + len = sizes[i]; + devicep->host2dev_func (devicep->target_id, + (void *) (tgt->tgt_start + + tgt_size), + (void *) hostaddrs[i], len); + } tgt_size += len; continue; } Jakub