aboutsummaryrefslogtreecommitdiff
path: root/libgomp/splay-tree.c
diff options
context:
space:
mode:
authorTobias Burnus <tobias@codesourcery.com>2022-12-10 13:42:08 +0100
committerTobias Burnus <tobias@codesourcery.com>2022-12-10 13:42:08 +0100
commitea4b23d9c82d9be3b982c3519fe5e8e9d833a6a8 (patch)
treec347ecf7ff66c25cbf24f48afb44db0dc431d319 /libgomp/splay-tree.c
parent68ee8a64ac17ded4ffda7a6ba4f387f40305e639 (diff)
downloadgcc-ea4b23d9c82d9be3b982c3519fe5e8e9d833a6a8.zip
gcc-ea4b23d9c82d9be3b982c3519fe5e8e9d833a6a8.tar.gz
gcc-ea4b23d9c82d9be3b982c3519fe5e8e9d833a6a8.tar.bz2
libgomp: Handle OpenMP's reverse offloads
This commit enabled reverse offload for nvptx such that gomp_target_rev actually gets called. And it fills the latter function to do all of the following: finding the host function to the device func ptr and copying the arguments to the host, processing the mapping/firstprivate, calling the host function, copying back the data and freeing as needed. The data handling is made easier by assuming that all host variables either existed before (and are in the mapping) or that those are devices variables not yet available on the host. Thus, the reverse mapping can do without refcounts etc. Note that the spec disallows inside a target region device-affecting constructs other than target plus ancestor device-modifier and it also limits the clauses permitted on this construct. For the function addresses, an additional splay tree is used; for the lookup of mapped variables, the existing splay-tree is used. Unfortunately, its data structure requires a full walk of the tree; Additionally, the just mapped variables are recorded in a separate data structure an extra lookup. While the lookup is slow, assuming that only few variables get mapped in each reverse offload construct and that reverse offload is the exception and not performance critical, this seems to be acceptable. libgomp/ChangeLog: * libgomp.h (struct target_mem_desc): Predeclare; move below after 'reverse_splay_tree_node' and add rev_array member. (struct reverse_splay_tree_key_s, reverse_splay_compare): New. (reverse_splay_tree_node, reverse_splay_tree, reverse_splay_tree_key): New typedef. (struct gomp_device_descr): Add mem_map_rev member. * oacc-host.c (host_dispatch): NULL init .mem_map_rev. * plugin/plugin-nvptx.c (GOMP_OFFLOAD_get_num_devices): Claim support for GOMP_REQUIRES_REVERSE_OFFLOAD. * splay-tree.h (splay_tree_callback_stop): New typedef; like splay_tree_callback but returning int not void. (splay_tree_foreach_lazy): Define; like splay_tree_foreach but taking splay_tree_callback_stop as argument. * splay-tree.c (splay_tree_foreach_internal_lazy, splay_tree_foreach_lazy): New; but early exit if callback returns nonzero. * target.c: Instatiate splay_tree_c with splay_tree_prefix 'reverse'. (gomp_map_lookup_rev): New. (gomp_load_image_to_device): Handle reverse-offload function lookup table. (gomp_unload_image_from_device): Free devicep->mem_map_rev. (struct gomp_splay_tree_rev_lookup_data, gomp_splay_tree_rev_lookup, gomp_map_rev_lookup, struct cpy_data, gomp_map_cdata_lookup_int, gomp_map_cdata_lookup): New auxiliary structs and functions for gomp_target_rev. (gomp_target_rev): Implement reverse offloading and its mapping. (gomp_target_init): Init current_device.mem_map_rev.root. * testsuite/libgomp.fortran/reverse-offload-2.f90: New test. * testsuite/libgomp.fortran/reverse-offload-3.f90: New test. * testsuite/libgomp.fortran/reverse-offload-4.f90: New test. * testsuite/libgomp.fortran/reverse-offload-5.f90: New test. * testsuite/libgomp.fortran/reverse-offload-5a.f90: New test without mapping of on-device allocated variables.
Diffstat (limited to 'libgomp/splay-tree.c')
-rw-r--r--libgomp/splay-tree.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/libgomp/splay-tree.c b/libgomp/splay-tree.c
index 2d8742f..3809e90 100644
--- a/libgomp/splay-tree.c
+++ b/libgomp/splay-tree.c
@@ -236,3 +236,25 @@ splay_tree_foreach (splay_tree sp, splay_tree_callback func, void *data)
{
splay_tree_foreach_internal (sp->root, func, data);
}
+
+/* Like above, except when func returns != 0, stop early. */
+
+static int
+splay_tree_foreach_internal_lazy (splay_tree_node node,
+ splay_tree_callback_stop func, void *data)
+{
+ if (!node)
+ return 0;
+ if (func (&node->key, data))
+ return 1;
+ if (splay_tree_foreach_internal_lazy (node->left, func, data))
+ return 1;
+ /* Yeah, whatever. GCC can fix my tail recursion. */
+ return splay_tree_foreach_internal_lazy (node->right, func, data);
+}
+
+attribute_hidden void
+splay_tree_foreach_lazy (splay_tree sp, splay_tree_callback_stop func, void *data)
+{
+ splay_tree_foreach_internal_lazy (sp->root, func, data);
+}