aboutsummaryrefslogtreecommitdiff
path: root/gcc/omp-offload.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2020-05-12 09:17:09 +0200
committerJakub Jelinek <jakub@redhat.com>2020-05-12 09:17:09 +0200
commitdc703151d4f4560e647649506d5b4ceb0ee11e90 (patch)
treee0982957d9abe22aec71e6199d1e306e9b0795ab /gcc/omp-offload.c
parentfe8c8f1e5ed61f00c14ff36caf4f510a7a09781d (diff)
downloadgcc-dc703151d4f4560e647649506d5b4ceb0ee11e90.zip
gcc-dc703151d4f4560e647649506d5b4ceb0ee11e90.tar.gz
gcc-dc703151d4f4560e647649506d5b4ceb0ee11e90.tar.bz2
openmp: Implement discovery of implicit declare target to clauses
This attempts to implement what the OpenMP 5.0 spec in declare target section says as ammended by the 5.1 changes so far (related to device_type(host)), except that it doesn't have the device(ancestor: ...) handling yet because we do not support it yet, and I've left so far out the except lambda note, because I need that clarified. 2020-05-12 Jakub Jelinek <jakub@redhat.com> * omp-offload.h (omp_discover_implicit_declare_target): Declare. * omp-offload.c: Include context.h. (omp_declare_target_fn_p, omp_declare_target_var_p, omp_discover_declare_target_fn_r, omp_discover_declare_target_var_r, omp_discover_implicit_declare_target): New functions. * cgraphunit.c (analyze_functions): Call omp_discover_implicit_declare_target. * testsuite/libgomp.c/target-39.c: New test.
Diffstat (limited to 'gcc/omp-offload.c')
-rw-r--r--gcc/omp-offload.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/gcc/omp-offload.c b/gcc/omp-offload.c
index c66f38b..c1eb378 100644
--- a/gcc/omp-offload.c
+++ b/gcc/omp-offload.c
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "stringpool.h"
#include "attribs.h"
#include "cfgloop.h"
+#include "context.h"
/* Describe the OpenACC looping structure of a function. The entire
function is held in a 'NULL' loop. */
@@ -158,6 +159,138 @@ add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
}
}
+/* Return true if DECL is a function for which its references should be
+ analyzed. */
+
+static bool
+omp_declare_target_fn_p (tree decl)
+{
+ return (TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
+ && !lookup_attribute ("omp declare target host",
+ DECL_ATTRIBUTES (decl))
+ && (!flag_openacc
+ || oacc_get_fn_attrib (decl) == NULL_TREE));
+}
+
+/* Return true if DECL Is a variable for which its initializer references
+ should be analyzed. */
+
+static bool
+omp_declare_target_var_p (tree decl)
+{
+ return (VAR_P (decl)
+ && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
+ && !lookup_attribute ("omp declare target link",
+ DECL_ATTRIBUTES (decl)));
+}
+
+/* Helper function for omp_discover_implicit_declare_target, called through
+ walk_tree. Mark referenced FUNCTION_DECLs implicitly as
+ declare target to. */
+
+static tree
+omp_discover_declare_target_fn_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TREE_CODE (*tp) == FUNCTION_DECL
+ && !omp_declare_target_fn_p (*tp)
+ && !lookup_attribute ("omp declare target host", DECL_ATTRIBUTES (*tp)))
+ {
+ tree id = get_identifier ("omp declare target");
+ if (!DECL_EXTERNAL (*tp) && DECL_SAVED_TREE (*tp))
+ ((vec<tree> *) data)->safe_push (*tp);
+ DECL_ATTRIBUTES (*tp) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (*tp));
+ symtab_node *node = symtab_node::get (*tp);
+ if (node != NULL)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ g->have_offload = true;
+ }
+ }
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ /* else if (TREE_CODE (*tp) == OMP_TARGET)
+ {
+ if (tree dev = omp_find_clause (OMP_TARGET_CLAUSES (*tp)))
+ if (OMP_DEVICE_ANCESTOR (dev))
+ *walk_subtrees = 0;
+ } */
+ return NULL_TREE;
+}
+
+/* Helper function for omp_discover_implicit_declare_target, called through
+ walk_tree. Mark referenced FUNCTION_DECLs implicitly as
+ declare target to. */
+
+static tree
+omp_discover_declare_target_var_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (TREE_CODE (*tp) == FUNCTION_DECL)
+ return omp_discover_declare_target_fn_r (tp, walk_subtrees, data);
+ else if (VAR_P (*tp)
+ && is_global_var (*tp)
+ && !omp_declare_target_var_p (*tp))
+ {
+ tree id = get_identifier ("omp declare target");
+ if (lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp)))
+ {
+ error_at (DECL_SOURCE_LOCATION (*tp),
+ "%qD specified both in declare target %<link%> and "
+ "implicitly in %<to%> clauses", *tp);
+ DECL_ATTRIBUTES (*tp)
+ = remove_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp));
+ }
+ if (TREE_STATIC (*tp) && DECL_INITIAL (*tp))
+ ((vec<tree> *) data)->safe_push (*tp);
+ DECL_ATTRIBUTES (*tp) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (*tp));
+ symtab_node *node = symtab_node::get (*tp);
+ if (node != NULL && !node->offloadable)
+ {
+ node->offloadable = 1;
+ if (ENABLE_OFFLOADING)
+ {
+ g->have_offload = true;
+ if (is_a <varpool_node *> (node))
+ vec_safe_push (offload_vars, node->decl);
+ }
+ }
+ }
+ else if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
+/* Perform the OpenMP implicit declare target to discovery. */
+
+void
+omp_discover_implicit_declare_target (void)
+{
+ cgraph_node *node;
+ varpool_node *vnode;
+ auto_vec<tree> worklist;
+
+ FOR_EACH_DEFINED_FUNCTION (node)
+ if (omp_declare_target_fn_p (node->decl) && DECL_SAVED_TREE (node->decl))
+ worklist.safe_push (node->decl);
+ FOR_EACH_STATIC_INITIALIZER (vnode)
+ if (omp_declare_target_var_p (vnode->decl))
+ worklist.safe_push (vnode->decl);
+ while (!worklist.is_empty ())
+ {
+ tree decl = worklist.pop ();
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ walk_tree_without_duplicates (&DECL_SAVED_TREE (decl),
+ omp_discover_declare_target_fn_r,
+ &worklist);
+ else
+ walk_tree_without_duplicates (&DECL_INITIAL (decl),
+ omp_discover_declare_target_var_r,
+ &worklist);
+ }
+}
+
+
/* Create new symbols containing (address, size) pairs for global variables,
marked with "omp declare target" attribute, as well as addresses for the
functions, which are outlined offloading regions. */