diff options
author | Ilya Verbin <ilya.verbin@intel.com> | 2015-12-15 14:56:50 +0000 |
---|---|---|
committer | Ilya Verbin <iverbin@gcc.gnu.org> | 2015-12-15 14:56:50 +0000 |
commit | 4a38b02b4ed0b6d58e1773072daff795eb244829 (patch) | |
tree | 3ded94420f4c91b3d08a1e815cabbd436cccb009 /libgomp/target.c | |
parent | b7e2dd6fb446b6b55358f1a6ec7abcf7d28b5590 (diff) | |
download | gcc-4a38b02b4ed0b6d58e1773072daff795eb244829.tar.gz |
c-common.c (c_common_attribute_table): Handle "omp declare target link" attribute.
gcc/c-family/
* c-common.c (c_common_attribute_table): Handle "omp declare target
link" attribute.
gcc/
* cgraphunit.c (output_in_order): Do not assemble "omp declare target
link" variables in ACCEL_COMPILER.
* gimplify.c (gimplify_adjust_omp_clauses): Do not remove mapping of
"omp declare target link" variables.
* omp-low.c (scan_sharing_clauses): Do not remove mapping of "omp
declare target link" variables.
(add_decls_addresses_to_decl_constructor): For "omp declare target link"
variables output address of the artificial pointer instead of address of
the variable. Set most significant bit of the size to mark them.
(pass_data_omp_target_link): New pass_data.
(pass_omp_target_link): New class.
(find_link_var_op): New static function.
(make_pass_omp_target_link): New function.
* passes.def: Add pass_omp_target_link.
* tree-pass.h (make_pass_omp_target_link): Declare.
* varpool.c (symbol_table::output_variables): Do not assemble "omp
declare target link" variables in ACCEL_COMPILER.
gcc/lto/
* lto.c: Include stringpool.h and fold-const.h.
(offload_handle_link_vars): New static function.
(lto_main): Call offload_handle_link_vars.
libgomp/
* libgomp.h (REFCOUNT_LINK): Define.
(struct splay_tree_key_s): Add link_key.
* target.c (gomp_map_vars): Treat REFCOUNT_LINK objects as not mapped.
Replace target address of the pointer with target address of newly
mapped object in the splay tree. Set link pointer on target to the
device address of the mapped object.
(gomp_unmap_vars): Restore target address of the pointer in the splay
tree for REFCOUNT_LINK objects after unmapping.
(gomp_load_image_to_device): Set refcount to REFCOUNT_LINK for "omp
declare target link" objects.
(gomp_unload_image_from_device): Replace j with i. Force unmap of all
"omp declare target link" objects, which were mapped for the image.
(gomp_exit_data): Restore target address of the pointer in the splay
tree for REFCOUNT_LINK objects after unmapping.
* testsuite/libgomp.c/target-link-1.c: New file.
From-SVN: r231655
Diffstat (limited to 'libgomp/target.c')
-rw-r--r-- | libgomp/target.c | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/libgomp/target.c b/libgomp/target.c index 932b1761f4e..1ab30f7ca25 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -464,7 +464,7 @@ gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum, } else n = splay_tree_lookup (mem_map, &cur_node); - if (n) + if (n && n->refcount != REFCOUNT_LINK) gomp_map_vars_existing (devicep, n, &cur_node, &tgt->list[i], kind & typemask); else @@ -628,11 +628,19 @@ gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum, else k->host_end = k->host_start + sizeof (void *); splay_tree_key n = splay_tree_lookup (mem_map, k); - if (n) + if (n && n->refcount != REFCOUNT_LINK) gomp_map_vars_existing (devicep, n, k, &tgt->list[i], kind & typemask); else { + k->link_key = NULL; + if (n && n->refcount == REFCOUNT_LINK) + { + /* Replace target address of the pointer with target address + of mapped object in the splay tree. */ + splay_tree_remove (mem_map, n); + k->link_key = n; + } size_t align = (size_t) 1 << (kind >> rshift); tgt->list[i].key = k; k->tgt = tgt; @@ -752,6 +760,16 @@ gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum, gomp_fatal ("%s: unhandled kind 0x%.2x", __FUNCTION__, kind); } + + if (k->link_key) + { + /* Set link pointer on target to the device address of the + mapped object. */ + void *tgt_addr = (void *) (tgt->tgt_start + k->tgt_offset); + devicep->host2dev_func (devicep->target_id, + (void *) n->tgt_offset, + &tgt_addr, sizeof (void *)); + } array++; } } @@ -884,6 +902,9 @@ gomp_unmap_vars (struct target_mem_desc *tgt, bool do_copyfrom) if (do_unmap) { splay_tree_remove (&devicep->mem_map, k); + if (k->link_key) + splay_tree_insert (&devicep->mem_map, + (splay_tree_node) k->link_key); if (k->tgt->refcount > 1) k->tgt->refcount--; else @@ -1020,31 +1041,40 @@ gomp_load_image_to_device (struct gomp_device_descr *devicep, unsigned version, k->tgt_offset = target_table[i].start; k->refcount = REFCOUNT_INFINITY; k->async_refcount = 0; + k->link_key = NULL; array->left = NULL; array->right = NULL; splay_tree_insert (&devicep->mem_map, array); array++; } + /* Most significant bit of the size in host and target tables marks + "omp declare target link" variables. */ + const uintptr_t link_bit = 1ULL << (sizeof (uintptr_t) * __CHAR_BIT__ - 1); + const uintptr_t size_mask = ~link_bit; + for (i = 0; i < num_vars; i++) { struct addr_pair *target_var = &target_table[num_funcs + i]; - if (target_var->end - target_var->start - != (uintptr_t) host_var_table[i * 2 + 1]) + uintptr_t target_size = target_var->end - target_var->start; + + if ((uintptr_t) host_var_table[i * 2 + 1] != target_size) { gomp_mutex_unlock (&devicep->lock); if (is_register_lock) gomp_mutex_unlock (®ister_lock); - gomp_fatal ("Can't map target variables (size mismatch)"); + gomp_fatal ("Cannot map target variables (size mismatch)"); } splay_tree_key k = &array->key; k->host_start = (uintptr_t) host_var_table[i * 2]; - k->host_end = k->host_start + (uintptr_t) host_var_table[i * 2 + 1]; + k->host_end + = k->host_start + (size_mask & (uintptr_t) host_var_table[i * 2 + 1]); k->tgt = tgt; k->tgt_offset = target_var->start; - k->refcount = REFCOUNT_INFINITY; + k->refcount = target_size & link_bit ? REFCOUNT_LINK : REFCOUNT_INFINITY; k->async_refcount = 0; + k->link_key = NULL; array->left = NULL; array->right = NULL; splay_tree_insert (&devicep->mem_map, array); @@ -1072,7 +1102,6 @@ gomp_unload_image_from_device (struct gomp_device_descr *devicep, int num_funcs = host_funcs_end - host_func_table; int num_vars = (host_vars_end - host_var_table) / 2; - unsigned j; struct splay_tree_key_s k; splay_tree_key node = NULL; @@ -1088,21 +1117,46 @@ gomp_unload_image_from_device (struct gomp_device_descr *devicep, devicep->unload_image_func (devicep->target_id, version, target_data); /* Remove mappings from splay tree. */ - for (j = 0; j < num_funcs; j++) + int i; + for (i = 0; i < num_funcs; i++) { - k.host_start = (uintptr_t) host_func_table[j]; + k.host_start = (uintptr_t) host_func_table[i]; k.host_end = k.host_start + 1; splay_tree_remove (&devicep->mem_map, &k); } - for (j = 0; j < num_vars; j++) + /* Most significant bit of the size in host and target tables marks + "omp declare target link" variables. */ + const uintptr_t link_bit = 1ULL << (sizeof (uintptr_t) * __CHAR_BIT__ - 1); + const uintptr_t size_mask = ~link_bit; + bool is_tgt_unmapped = false; + + for (i = 0; i < num_vars; i++) { - k.host_start = (uintptr_t) host_var_table[j * 2]; - k.host_end = k.host_start + (uintptr_t) host_var_table[j * 2 + 1]; - splay_tree_remove (&devicep->mem_map, &k); + k.host_start = (uintptr_t) host_var_table[i * 2]; + k.host_end + = k.host_start + (size_mask & (uintptr_t) host_var_table[i * 2 + 1]); + + if (!(link_bit & (uintptr_t) host_var_table[i * 2 + 1])) + splay_tree_remove (&devicep->mem_map, &k); + else + { + splay_tree_key n = splay_tree_lookup (&devicep->mem_map, &k); + splay_tree_remove (&devicep->mem_map, n); + if (n->link_key) + { + if (n->tgt->refcount > 1) + n->tgt->refcount--; + else + { + is_tgt_unmapped = true; + gomp_unmap_tgt (n->tgt); + } + } + } } - if (node) + if (node && !is_tgt_unmapped) { free (node->tgt); free (node); @@ -1658,6 +1712,9 @@ gomp_exit_data (struct gomp_device_descr *devicep, size_t mapnum, if (k->refcount == 0) { splay_tree_remove (&devicep->mem_map, k); + if (k->link_key) + splay_tree_insert (&devicep->mem_map, + (splay_tree_node) k->link_key); if (k->tgt->refcount > 1) k->tgt->refcount--; else |