openmp: Implicitly add 'declare target' directives for dynamic initializers in C++
2020-12-18 Kwok Cheung Yeung <kcy@codesourcery.com> gcc/ * langhooks-def.h (lhd_get_decl_init): New. (lhd_finish_decl_inits): New. (LANG_HOOKS_GET_DECL_INIT): New. (LANG_HOOKS_OMP_FINISH_DECL_INITS): New. (LANG_HOOKS_DECLS): Add LANG_HOOKS_GET_DECL_INIT and LANG_HOOKS_OMP_FINISH_DECL_INITS. * langhooks.c (lhd_omp_get_decl_init): New. (lhd_omp_finish_decl_inits): New. * langhooks.h (struct lang_hooks_for_decls): Add omp_get_decl_init and omp_finish_decl_inits. * omp-offload.c (omp_discover_declare_target_var_r): Use get_decl_init langhook in place of DECL_INITIAL. Call omp_finish_decl_inits langhook at end of function. gcc/cp/ * cp-lang.c (cxx_get_decl_init): New. (cxx_omp_finish_decl_inits): New. (LANG_HOOKS_GET_DECL_INIT): New. (LANG_HOOKS_OMP_FINISH_DECL_INITS): New. * cp-tree.h (dynamic_initializers): New. * decl.c (dynamic_initializers): New. * decl2.c (c_parse_final_cleanups): Add initializer entries from vars to dynamic_initializers. gcc/testsuite/ * g++.dg/gomp/declare-target-3.C: New.
This commit is contained in:
parent
7ff5706fcd
commit
3af02d32cc
9 changed files with 118 additions and 5 deletions
|
@ -34,6 +34,8 @@ static tree cp_eh_personality (void);
|
|||
static tree get_template_innermost_arguments_folded (const_tree);
|
||||
static tree get_template_argument_pack_elems_folded (const_tree);
|
||||
static tree cxx_enum_underlying_base_type (const_tree);
|
||||
static tree *cxx_omp_get_decl_init (tree);
|
||||
static void cxx_omp_finish_decl_inits (void);
|
||||
|
||||
/* Lang hooks common to C++ and ObjC++ are declared in cp/cp-objcp-common.h;
|
||||
consequently, there should be very few hooks below. */
|
||||
|
@ -92,6 +94,12 @@ static tree cxx_enum_underlying_base_type (const_tree);
|
|||
#undef LANG_HOOKS_GET_SUBSTRING_LOCATION
|
||||
#define LANG_HOOKS_GET_SUBSTRING_LOCATION c_get_substring_location
|
||||
|
||||
#undef LANG_HOOKS_OMP_GET_DECL_INIT
|
||||
#define LANG_HOOKS_OMP_GET_DECL_INIT cxx_omp_get_decl_init
|
||||
|
||||
#undef LANG_HOOKS_OMP_FINISH_DECL_INITS
|
||||
#define LANG_HOOKS_OMP_FINISH_DECL_INITS cxx_omp_finish_decl_inits
|
||||
|
||||
/* Each front end provides its own lang hook initializer. */
|
||||
struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
|
@ -233,6 +241,30 @@ tree cxx_enum_underlying_base_type (const_tree type)
|
|||
return underlying_type;
|
||||
}
|
||||
|
||||
/* The C++ version of the omp_get_decl_init langhook returns the static
|
||||
initializer for a variable declaration if present, otherwise it
|
||||
tries to find and return the dynamic initializer. If not present,
|
||||
it returns NULL. */
|
||||
|
||||
static tree *
|
||||
cxx_omp_get_decl_init (tree decl)
|
||||
{
|
||||
if (DECL_INITIAL (decl))
|
||||
return &DECL_INITIAL (decl);
|
||||
|
||||
return hash_map_safe_get (dynamic_initializers, decl);
|
||||
}
|
||||
|
||||
/* The C++ version of the omp_finish_decl_inits langhook allows GC to
|
||||
reclaim the memory used by the hash-map used to hold dynamic initializer
|
||||
information. */
|
||||
|
||||
static void
|
||||
cxx_omp_finish_decl_inits (void)
|
||||
{
|
||||
dynamic_initializers = NULL;
|
||||
}
|
||||
|
||||
#if CHECKING_P
|
||||
|
||||
namespace selftest {
|
||||
|
|
|
@ -5631,6 +5631,10 @@ extern GTY(()) tree static_aggregates;
|
|||
/* Likewise, for thread local storage. */
|
||||
extern GTY(()) tree tls_aggregates;
|
||||
|
||||
/* A hash-map mapping from variable decls to the dynamic initializer for
|
||||
the decl. This is currently only used by OpenMP. */
|
||||
extern GTY(()) decl_tree_map *dynamic_initializers;
|
||||
|
||||
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
|
||||
|
||||
/* These are uses as bits in flags passed to various functions to
|
||||
|
|
|
@ -146,6 +146,10 @@ tree static_aggregates;
|
|||
/* Like static_aggregates, but for thread_local variables. */
|
||||
tree tls_aggregates;
|
||||
|
||||
/* A hash-map mapping from variable decls to the dynamic initializer for
|
||||
the decl. This is currently only used by OpenMP. */
|
||||
decl_tree_map *dynamic_initializers;
|
||||
|
||||
/* -- end of C++ */
|
||||
|
||||
/* A node for the integer constant 2. */
|
||||
|
|
|
@ -5006,6 +5006,13 @@ c_parse_final_cleanups (void)
|
|||
loop. */
|
||||
if (tree vars = prune_vars_needing_no_initialization (&static_aggregates))
|
||||
{
|
||||
if (flag_openmp)
|
||||
/* Add initializer information from VARS into
|
||||
DYNAMIC_INITIALIZERS. */
|
||||
for (t = vars; t; t = TREE_CHAIN (t))
|
||||
hash_map_safe_put<hm_ggc> (dynamic_initializers,
|
||||
TREE_VALUE (t), TREE_PURPOSE (t));
|
||||
|
||||
/* We need to start a new initialization function each time
|
||||
through the loop. That's because we need to know which
|
||||
vtables have been referenced, and TREE_SYMBOL_REFERENCED
|
||||
|
|
|
@ -87,6 +87,8 @@ extern void lhd_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *,
|
|||
tree);
|
||||
extern bool lhd_omp_mappable_type (tree);
|
||||
extern bool lhd_omp_scalar_p (tree);
|
||||
extern tree *lhd_omp_get_decl_init (tree);
|
||||
extern void lhd_omp_finish_decl_inits ();
|
||||
|
||||
extern const char *lhd_get_substring_location (const substring_loc &,
|
||||
location_t *out_loc);
|
||||
|
@ -265,6 +267,8 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
|
|||
#define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null
|
||||
#define LANG_HOOKS_OMP_FINISH_CLAUSE lhd_omp_finish_clause
|
||||
#define LANG_HOOKS_OMP_SCALAR_P lhd_omp_scalar_p
|
||||
#define LANG_HOOKS_OMP_GET_DECL_INIT lhd_omp_get_decl_init
|
||||
#define LANG_HOOKS_OMP_FINISH_DECL_INITS lhd_omp_finish_decl_inits
|
||||
|
||||
#define LANG_HOOKS_DECLS { \
|
||||
LANG_HOOKS_GLOBAL_BINDINGS_P, \
|
||||
|
@ -293,7 +297,9 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
|
|||
LANG_HOOKS_OMP_CLAUSE_LINEAR_CTOR, \
|
||||
LANG_HOOKS_OMP_CLAUSE_DTOR, \
|
||||
LANG_HOOKS_OMP_FINISH_CLAUSE, \
|
||||
LANG_HOOKS_OMP_SCALAR_P \
|
||||
LANG_HOOKS_OMP_SCALAR_P, \
|
||||
LANG_HOOKS_OMP_GET_DECL_INIT, \
|
||||
LANG_HOOKS_OMP_FINISH_DECL_INITS \
|
||||
}
|
||||
|
||||
/* LTO hooks. */
|
||||
|
|
|
@ -632,6 +632,22 @@ lhd_omp_scalar_p (tree decl)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Return static initializer for DECL. */
|
||||
|
||||
tree *
|
||||
lhd_omp_get_decl_init (tree decl)
|
||||
{
|
||||
return &DECL_INITIAL (decl);
|
||||
}
|
||||
|
||||
/* Free any extra memory used to hold initializer information for
|
||||
variable declarations. */
|
||||
|
||||
void
|
||||
lhd_omp_finish_decl_inits (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Register language specific type size variables as potentially OpenMP
|
||||
firstprivate variables. */
|
||||
|
||||
|
|
|
@ -299,6 +299,16 @@ struct lang_hooks_for_decls
|
|||
/* Return true if DECL is a scalar variable (for the purpose of
|
||||
implicit firstprivatization). */
|
||||
bool (*omp_scalar_p) (tree decl);
|
||||
|
||||
/* Return a pointer to the tree representing the initializer
|
||||
expression for the non-local variable DECL. Return NULL if
|
||||
DECL is not initialized. */
|
||||
tree *(*omp_get_decl_init) (tree decl);
|
||||
|
||||
/* Free any extra memory used to hold initializer information for
|
||||
variable declarations. omp_get_decl_init must not be called
|
||||
after calling this. */
|
||||
void (*omp_finish_decl_inits) (void);
|
||||
};
|
||||
|
||||
/* Language hooks related to LTO serialization. */
|
||||
|
|
|
@ -315,7 +315,7 @@ omp_discover_declare_target_var_r (tree *tp, int *walk_subtrees, void *data)
|
|||
DECL_ATTRIBUTES (*tp)
|
||||
= remove_attribute ("omp declare target link", DECL_ATTRIBUTES (*tp));
|
||||
}
|
||||
if (TREE_STATIC (*tp) && DECL_INITIAL (*tp))
|
||||
if (TREE_STATIC (*tp) && lang_hooks.decls.omp_get_decl_init (*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);
|
||||
|
@ -361,14 +361,15 @@ omp_discover_implicit_declare_target (void)
|
|||
&& DECL_STRUCT_FUNCTION (cgn->decl)->has_omp_target)
|
||||
worklist.safe_push (cgn->decl);
|
||||
}
|
||||
FOR_EACH_STATIC_INITIALIZER (vnode)
|
||||
if (omp_declare_target_var_p (vnode->decl))
|
||||
FOR_EACH_VARIABLE (vnode)
|
||||
if (lang_hooks.decls.omp_get_decl_init (vnode->decl)
|
||||
&& omp_declare_target_var_p (vnode->decl))
|
||||
worklist.safe_push (vnode->decl);
|
||||
while (!worklist.is_empty ())
|
||||
{
|
||||
tree decl = worklist.pop ();
|
||||
if (VAR_P (decl))
|
||||
walk_tree_without_duplicates (&DECL_INITIAL (decl),
|
||||
walk_tree_without_duplicates (lang_hooks.decls.omp_get_decl_init (decl),
|
||||
omp_discover_declare_target_var_r,
|
||||
&worklist);
|
||||
else if (omp_declare_target_fn_p (decl))
|
||||
|
@ -380,6 +381,8 @@ omp_discover_implicit_declare_target (void)
|
|||
omp_discover_declare_target_fn_r,
|
||||
&worklist);
|
||||
}
|
||||
|
||||
lang_hooks.decls.omp_finish_decl_inits ();
|
||||
}
|
||||
|
||||
|
||||
|
|
31
gcc/testsuite/g++.dg/gomp/declare-target-3.C
Normal file
31
gcc/testsuite/g++.dg/gomp/declare-target-3.C
Normal file
|
@ -0,0 +1,31 @@
|
|||
// { dg-do compile }
|
||||
// { dg-additional-options "-fdump-tree-gimple" }
|
||||
|
||||
// Test implicit marking of declare target to.
|
||||
|
||||
int foo () { return 1; }
|
||||
int bar () { return 2; } // Implicitly marked (due to b)
|
||||
int baz () { return 3; } // Implicitly marked (due to d via c)
|
||||
int qux () { return 4; } // Implicitly marked (due to g via f and e)
|
||||
|
||||
int a = foo ();
|
||||
int b = bar (); // Explicitly marked
|
||||
int c = baz (); // Implicitly marked (due to d)
|
||||
int *d = &c; // Explicitly marked
|
||||
int e = qux (); // Implicitly marked (due to g via f)
|
||||
int f = e + 1; // Implicitly marked (due to g)
|
||||
int *g = &f; // Explicitly marked
|
||||
|
||||
#pragma omp declare target to(b, d, g)
|
||||
|
||||
// { dg-final { scan-tree-dump-not "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint foo \\\(\\\)" "gimple" } }
|
||||
// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint bar \\\(\\\)" "gimple" } }
|
||||
// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint baz \\\(\\\)" "gimple" } }
|
||||
// { dg-final { scan-tree-dump "__attribute__\\\(\\\(omp declare target\\\)\\\)\\\nint qux \\\(\\\)" "gimple" } }
|
||||
// { dg-final { scan-assembler-not "\\\.offload_var_table:\\n.+\\\.quad\\s+a" } }
|
||||
// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+b" } }
|
||||
// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+c" } }
|
||||
// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+d" } }
|
||||
// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+e" } }
|
||||
// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+f" } }
|
||||
// { dg-final { scan-assembler "\\\.offload_var_table:\\n.+\\\.quad\\s+g" } }
|
Loading…
Add table
Reference in a new issue