[PATCH 2/7] OpenMP 4.0 offloading infrastructure: LTO streaming.

gcc/
	* cgraph.c: Include context.h.
	(cgraph_node::create): Set node->offloadable and g->have_offload if
	decl have "omp declare target" attribute.
	* cgraph.h (symtab_node): Add need_lto_streaming and offloadable flags.
	* cgraphunit.c: Include lto-section-names.h.
	(ipa_passes): Call ipa_write_summaries if there is something to write to
	OFFLOAD_SECTION_NAME_PREFIX sections.
	(symbol_table::compile): Set flag_generate_lto if there is something to
	offload.
	Replace flag_lto with flag_generate_lto before lto_streamer_hooks_init.
	* context.c (gcc::context::context): Initialize have_offload with false.
	* context.h (class context): Add have_offload flag.
	* ipa-inline-analysis.c (inline_generate_summary): Do not exit under
	flag_generate_lto.
	(inline_free_summary): Always remove hooks.
	* lto-cgraph.c (referenced_from_other_partition_p): Ignore references
	from non-offloadable nodes while streaming a node into offload section.
	(reachable_from_other_partition_p): Likewise.
	(select_what_to_stream): New function.
	(compute_ltrans_boundary): Do not call
	lto_set_symtab_encoder_in_partition if the node should not be streamed.
	* lto-section-names.h (OFFLOAD_SECTION_NAME_PREFIX): Define.
	(section_name_prefix): Declare.
	* lto-streamer.c (section_name_prefix): New variable.
	(lto_get_section_name): Use section_name_prefix instead of
	LTO_SECTION_NAME_PREFIX.
	* lto-streamer.h (select_what_to_stream): Declare.
	* omp-low.c: Include context.h.
	(is_targetreg_ctx): New function.
	(scan_sharing_clauses): Use offloadable flag, instead of an attribute.
	(create_omp_child_function, check_omp_nesting_restrictions): Use new
	is_targetreg_ctx function.  Replace usage of "omp declare target"
	attribute with a cgraph_node flag offloadable.
	(expand_omp_target): Set mark_force_output for offloadable functions.
	(lower_omp_critical): Set offloadable flag for omp critical symbol.
	* passes.c (ipa_write_summaries): New argument offload_lto_mode.  Call
	select_what_to_stream.  Do not call lto_set_symtab_encoder_in_partition
	if the node should not be streamed out.
	* tree-pass.h (ipa_write_summaries): New bool argument.
	* varpool.c: Include context.h.
	(varpool_node::get_create): Set node->offloadable and g->have_offload if
	decl have "omp declare target" attribute.

gcc/lto/
	* lto-object.c (lto_obj_add_section): Use section_name_prefix instead of
	LTO_SECTION_NAME_PREFIX.
	* lto-partition.c (lto_promote_cross_file_statics): Call
	select_what_to_stream.
	* lto.c (lto_section_with_id): Use section_name_prefix instead of
	LTO_SECTION_NAME_PREFIX.
	(read_cgraph_and_symbols): Read OFFLOAD_SECTION_NAME_PREFIX sections, if
	being built as an offload compiler.

Co-Authored-By: Andrey Turetskiy <andrey.turetskiy@intel.com>
Co-Authored-By: Bernd Schmidt <bernds@codesourcery.com>
Co-Authored-By: Michael Zolotukhin <michael.v.zolotukhin@intel.com>

From-SVN: r217486
This commit is contained in:
Ilya Verbin 2014-11-13 13:37:38 +00:00 committed by Kirill Yukhin
parent 85c64bbee9
commit 1f6be68256
19 changed files with 205 additions and 38 deletions

View File

@ -1,3 +1,51 @@
2014-11-13 Ilya Verbin <ilya.verbin@intel.com>
Bernd Schmidt <bernds@codesourcery.com>
Andrey Turetskiy <andrey.turetskiy@intel.com>
Michael Zolotukhin <michael.v.zolotukhin@intel.com>
* cgraph.c: Include context.h.
(cgraph_node::create): Set node->offloadable and g->have_offload if
decl have "omp declare target" attribute.
* cgraph.h (symtab_node): Add need_lto_streaming and offloadable flags.
* cgraphunit.c: Include lto-section-names.h.
(ipa_passes): Call ipa_write_summaries if there is something to write to
OFFLOAD_SECTION_NAME_PREFIX sections.
(symbol_table::compile): Set flag_generate_lto if there is something to
offload.
Replace flag_lto with flag_generate_lto before lto_streamer_hooks_init.
* context.c (gcc::context::context): Initialize have_offload with false.
* context.h (class context): Add have_offload flag.
* ipa-inline-analysis.c (inline_generate_summary): Do not exit under
flag_generate_lto.
(inline_free_summary): Always remove hooks.
* lto-cgraph.c (referenced_from_other_partition_p): Ignore references
from non-offloadable nodes while streaming a node into offload section.
(reachable_from_other_partition_p): Likewise.
(select_what_to_stream): New function.
(compute_ltrans_boundary): Do not call
lto_set_symtab_encoder_in_partition if the node should not be streamed.
* lto-section-names.h (OFFLOAD_SECTION_NAME_PREFIX): Define.
(section_name_prefix): Declare.
* lto-streamer.c (section_name_prefix): New variable.
(lto_get_section_name): Use section_name_prefix instead of
LTO_SECTION_NAME_PREFIX.
* lto-streamer.h (select_what_to_stream): Declare.
* omp-low.c: Include context.h.
(is_targetreg_ctx): New function.
(scan_sharing_clauses): Use offloadable flag, instead of an attribute.
(create_omp_child_function, check_omp_nesting_restrictions): Use new
is_targetreg_ctx function. Replace usage of "omp declare target"
attribute with a cgraph_node flag offloadable.
(expand_omp_target): Set mark_force_output for offloadable functions.
(lower_omp_critical): Set offloadable flag for omp critical symbol.
* passes.c (ipa_write_summaries): New argument offload_lto_mode. Call
select_what_to_stream. Do not call lto_set_symtab_encoder_in_partition
if the node should not be streamed out.
* tree-pass.h (ipa_write_summaries): New bool argument.
* varpool.c: Include context.h.
(varpool_node::get_create): Set node->offloadable and g->have_offload if
decl have "omp declare target" attribute.
2014-11-13 Bernd Schmidt <bernds@codesourcery.com> 2014-11-13 Bernd Schmidt <bernds@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com> Thomas Schwinge <thomas@codesourcery.com>
Ilya Verbin <ilya.verbin@intel.com> Ilya Verbin <ilya.verbin@intel.com>

View File

@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see
#include "profile.h" #include "profile.h"
#include "params.h" #include "params.h"
#include "tree-chkp.h" #include "tree-chkp.h"
#include "context.h"
/* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */ /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */
#include "tree-pass.h" #include "tree-pass.h"
@ -494,6 +495,14 @@ cgraph_node::create (tree decl)
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
node->decl = decl; node->decl = decl;
if (flag_openmp
&& lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
{
node->offloadable = 1;
g->have_offload = true;
}
node->register_symbol (); node->register_symbol ();
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)

View File

@ -450,6 +450,13 @@ public:
/* Set when init priority is set. */ /* Set when init priority is set. */
unsigned in_init_priority_hash : 1; unsigned in_init_priority_hash : 1;
/* Set when symbol needs to be streamed into LTO bytecode for LTO, or in case
of offloading, for separate compilation for a different target. */
unsigned need_lto_streaming : 1;
/* Set when symbol can be streamed into bytecode for offloading. */
unsigned offloadable : 1;
/* Ordering of all symtab entries. */ /* Ordering of all symtab entries. */
int order; int order;

View File

@ -224,6 +224,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h" #include "gimplify.h"
#include "dbgcnt.h" #include "dbgcnt.h"
#include "tree-chkp.h" #include "tree-chkp.h"
#include "lto-section-names.h"
/* Queue of cgraph nodes scheduled to be added into cgraph. This is a /* Queue of cgraph nodes scheduled to be added into cgraph. This is a
secondary queue used during optimization to accommodate passes that secondary queue used during optimization to accommodate passes that
@ -2079,7 +2080,18 @@ ipa_passes (void)
targetm.asm_out.lto_start (); targetm.asm_out.lto_start ();
if (!in_lto_p) if (!in_lto_p)
ipa_write_summaries (); {
if (g->have_offload)
{
section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
ipa_write_summaries (true);
}
if (flag_lto)
{
section_name_prefix = LTO_SECTION_NAME_PREFIX;
ipa_write_summaries (false);
}
}
if (flag_generate_lto) if (flag_generate_lto)
targetm.asm_out.lto_end (); targetm.asm_out.lto_end ();
@ -2163,8 +2175,12 @@ symbol_table::compile (void)
fprintf (stderr, "Performing interprocedural optimizations\n"); fprintf (stderr, "Performing interprocedural optimizations\n");
state = IPA; state = IPA;
/* Offloading requires LTO infrastructure. */
if (!in_lto_p && g->have_offload)
flag_generate_lto = 1;
/* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */ /* If LTO is enabled, initialize the streamer hooks needed by GIMPLE. */
if (flag_lto) if (flag_generate_lto)
lto_streamer_hooks_init (); lto_streamer_hooks_init ();
/* Don't run the IPA passes if there was any error or sorry messages. */ /* Don't run the IPA passes if there was any error or sorry messages. */

View File

@ -30,6 +30,8 @@ gcc::context *g;
gcc::context::context () gcc::context::context ()
{ {
have_offload = false;
/* The pass manager's constructor uses the dump manager (to set up /* The pass manager's constructor uses the dump manager (to set up
dumps for the various passes), so the dump manager must be set up dumps for the various passes), so the dump manager must be set up
before the pass manager. */ before the pass manager. */

View File

@ -33,6 +33,9 @@ class context
public: public:
context (); context ();
/* The flag shows if there are symbols to be streamed for offloading. */
bool have_offload;
/* Pass-management. */ /* Pass-management. */
pass_manager *get_passes () { gcc_assert (m_passes); return m_passes; } pass_manager *get_passes () { gcc_assert (m_passes); return m_passes; }

View File

@ -4024,7 +4024,7 @@ inline_generate_summary (void)
/* When not optimizing, do not bother to analyze. Inlining is still done /* When not optimizing, do not bother to analyze. Inlining is still done
because edge redirection needs to happen there. */ because edge redirection needs to happen there. */
if (!optimize && !flag_lto && !flag_wpa) if (!optimize && !flag_generate_lto && !flag_wpa)
return; return;
function_insertion_hook_holder = function_insertion_hook_holder =
@ -4339,11 +4339,6 @@ void
inline_free_summary (void) inline_free_summary (void)
{ {
struct cgraph_node *node; struct cgraph_node *node;
if (!inline_edge_summary_vec.exists ())
return;
FOR_EACH_DEFINED_FUNCTION (node)
if (!node->alias)
reset_inline_summary (node);
if (function_insertion_hook_holder) if (function_insertion_hook_holder)
symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder); symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder);
function_insertion_hook_holder = NULL; function_insertion_hook_holder = NULL;
@ -4359,6 +4354,11 @@ inline_free_summary (void)
if (edge_duplication_hook_holder) if (edge_duplication_hook_holder)
symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
edge_duplication_hook_holder = NULL; edge_duplication_hook_holder = NULL;
if (!inline_edge_summary_vec.exists ())
return;
FOR_EACH_DEFINED_FUNCTION (node)
if (!node->alias)
reset_inline_summary (node);
vec_free (inline_summary_vec); vec_free (inline_summary_vec);
inline_edge_summary_vec.release (); inline_edge_summary_vec.release ();
if (edge_predicate_pool) if (edge_predicate_pool)

View File

@ -330,6 +330,11 @@ referenced_from_other_partition_p (symtab_node *node, lto_symtab_encoder_t encod
for (i = 0; node->iterate_referring (i, ref); i++) for (i = 0; node->iterate_referring (i, ref); i++)
{ {
/* Ignore references from non-offloadable nodes while streaming NODE into
offload LTO section. */
if (!ref->referring->need_lto_streaming)
continue;
if (ref->referring->in_other_partition if (ref->referring->in_other_partition
|| !lto_symtab_encoder_in_partition_p (encoder, ref->referring)) || !lto_symtab_encoder_in_partition_p (encoder, ref->referring))
return true; return true;
@ -348,9 +353,16 @@ reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t
if (node->global.inlined_to) if (node->global.inlined_to)
return false; return false;
for (e = node->callers; e; e = e->next_caller) for (e = node->callers; e; e = e->next_caller)
{
/* Ignore references from non-offloadable nodes while streaming NODE into
offload LTO section. */
if (!e->caller->need_lto_streaming)
continue;
if (e->caller->in_other_partition if (e->caller->in_other_partition
|| !lto_symtab_encoder_in_partition_p (encoder, e->caller)) || !lto_symtab_encoder_in_partition_p (encoder, e->caller))
return true; return true;
}
return false; return false;
} }
@ -818,6 +830,16 @@ create_references (lto_symtab_encoder_t encoder, symtab_node *node)
lto_symtab_encoder_encode (encoder, ref->referred); lto_symtab_encoder_encode (encoder, ref->referred);
} }
/* Select what needs to be streamed out. In regular lto mode stream everything.
In offload lto mode stream only nodes marked as offloadable. */
void
select_what_to_stream (bool offload_lto_mode)
{
struct symtab_node *snode;
FOR_EACH_SYMBOL (snode)
snode->need_lto_streaming = !offload_lto_mode || snode->offloadable;
}
/* Find all symbols we want to stream into given partition and insert them /* Find all symbols we want to stream into given partition and insert them
to encoders. to encoders.
@ -844,6 +866,8 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
!lsei_end_p (lsei); lsei_next_function_in_partition (&lsei)) !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
{ {
struct cgraph_node *node = lsei_cgraph_node (lsei); struct cgraph_node *node = lsei_cgraph_node (lsei);
if (!node->need_lto_streaming)
continue;
add_node_to (encoder, node, true); add_node_to (encoder, node, true);
lto_set_symtab_encoder_in_partition (encoder, node); lto_set_symtab_encoder_in_partition (encoder, node);
create_references (encoder, node); create_references (encoder, node);
@ -860,6 +884,8 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
{ {
varpool_node *vnode = lsei_varpool_node (lsei); varpool_node *vnode = lsei_varpool_node (lsei);
if (!vnode->need_lto_streaming)
continue;
lto_set_symtab_encoder_in_partition (encoder, vnode); lto_set_symtab_encoder_in_partition (encoder, vnode);
lto_set_symtab_encoder_encode_initializer (encoder, vnode); lto_set_symtab_encoder_encode_initializer (encoder, vnode);
create_references (encoder, vnode); create_references (encoder, vnode);

View File

@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see
name for the functions and static_initializers. For other types of name for the functions and static_initializers. For other types of
sections a '.' and the section type are appended. */ sections a '.' and the section type are appended. */
#define LTO_SECTION_NAME_PREFIX ".gnu.lto_" #define LTO_SECTION_NAME_PREFIX ".gnu.lto_"
#define OFFLOAD_SECTION_NAME_PREFIX ".gnu.offload_lto_"
/* Can be either OFFLOAD_SECTION_NAME_PREFIX when we stream IR for offload
compiler, or LTO_SECTION_NAME_PREFIX for LTO case. */
extern const char *section_name_prefix;
/* Segment name for LTO sections. This is only used for Mach-O. */ /* Segment name for LTO sections. This is only used for Mach-O. */

View File

@ -60,6 +60,7 @@ struct lto_stats_d lto_stats;
static bitmap_obstack lto_obstack; static bitmap_obstack lto_obstack;
static bool lto_obstack_initialized; static bool lto_obstack_initialized;
const char *section_name_prefix = LTO_SECTION_NAME_PREFIX;
/* Return a string representing LTO tag TAG. */ /* Return a string representing LTO tag TAG. */
@ -189,7 +190,7 @@ lto_get_section_name (int section_type, const char *name, struct lto_file_decl_d
sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, f->id); sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, f->id);
else else
sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, get_random_seed (false)); sprintf (post, "." HOST_WIDE_INT_PRINT_HEX_PURE, get_random_seed (false));
return concat (LTO_SECTION_NAME_PREFIX, sep, add, post, NULL); return concat (section_name_prefix, sep, add, post, NULL);
} }

View File

@ -831,6 +831,7 @@ bool referenced_from_this_partition_p (symtab_node *,
bool reachable_from_this_partition_p (struct cgraph_node *, bool reachable_from_this_partition_p (struct cgraph_node *,
lto_symtab_encoder_t); lto_symtab_encoder_t);
lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder); lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
void select_what_to_stream (bool);
/* In lto-symtab.c. */ /* In lto-symtab.c. */

View File

@ -1,3 +1,17 @@
2014-11-13 Ilya Verbin <ilya.verbin@intel.com>
Bernd Schmidt <bernds@codesourcery.com>
Andrey Turetskiy <andrey.turetskiy@intel.com>
Michael Zolotukhin <michael.v.zolotukhin@intel.com>
* lto-object.c (lto_obj_add_section): Use section_name_prefix instead of
LTO_SECTION_NAME_PREFIX.
* lto-partition.c (lto_promote_cross_file_statics): Call
select_what_to_stream.
* lto.c (lto_section_with_id): Use section_name_prefix instead of
LTO_SECTION_NAME_PREFIX.
(read_cgraph_and_symbols): Read OFFLOAD_SECTION_NAME_PREFIX sections, if
being built as an offload compiler.
2014-10-29 Richard Sandiford <richard.sandiford@arm.com> 2014-10-29 Richard Sandiford <richard.sandiford@arm.com>
* lto-lang.c: Remove redundant enum from machine_mode. * lto-lang.c: Remove redundant enum from machine_mode.

View File

@ -242,8 +242,7 @@ lto_obj_add_section (void *data, const char *name, off_t offset,
void **slot; void **slot;
struct lto_section_list *list = loasd->list; struct lto_section_list *list = loasd->list;
if (strncmp (name, LTO_SECTION_NAME_PREFIX, if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
strlen (LTO_SECTION_NAME_PREFIX)) != 0)
return 1; return 1;
new_name = xstrdup (name); new_name = xstrdup (name);

View File

@ -952,6 +952,8 @@ lto_promote_cross_file_statics (void)
gcc_assert (flag_wpa); gcc_assert (flag_wpa);
select_what_to_stream (false);
/* First compute boundaries. */ /* First compute boundaries. */
n_sets = ltrans_partitions.length (); n_sets = ltrans_partitions.length ();
for (i = 0; i < n_sets; i++) for (i = 0; i < n_sets; i++)

View File

@ -2137,7 +2137,7 @@ lto_section_with_id (const char *name, unsigned HOST_WIDE_INT *id)
{ {
const char *s; const char *s;
if (strncmp (name, LTO_SECTION_NAME_PREFIX, strlen (LTO_SECTION_NAME_PREFIX))) if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
return 0; return 0;
s = strrchr (name, '.'); s = strrchr (name, '.');
return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1; return s && sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
@ -2912,6 +2912,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
timevar_push (TV_IPA_LTO_DECL_IN); timevar_push (TV_IPA_LTO_DECL_IN);
#ifdef ACCEL_COMPILER
section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
#endif
real_file_decl_data real_file_decl_data
= decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1); = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
real_file_count = nfiles; real_file_count = nfiles;

View File

@ -86,6 +86,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-nested.h" #include "tree-nested.h"
#include "tree-eh.h" #include "tree-eh.h"
#include "cilk.h" #include "cilk.h"
#include "context.h"
/* Lowering of OpenMP parallel and workshare constructs proceeds in two /* Lowering of OpenMP parallel and workshare constructs proceeds in two
@ -273,6 +274,16 @@ is_parallel_ctx (omp_context *ctx)
} }
/* Return true if CTX is for an omp target region. */
static inline bool
is_targetreg_ctx (omp_context *ctx)
{
return gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
&& gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION;
}
/* Return true if CTX is for an omp task. */ /* Return true if CTX is for an omp task. */
static inline bool static inline bool
@ -1642,8 +1653,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& DECL_P (decl) && DECL_P (decl)
&& is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)) && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
&& lookup_attribute ("omp declare target", && varpool_node::get_create (decl)->offloadable)
DECL_ATTRIBUTES (decl)))
break; break;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER) && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
@ -1783,8 +1793,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
decl = OMP_CLAUSE_DECL (c); decl = OMP_CLAUSE_DECL (c);
if (DECL_P (decl) if (DECL_P (decl)
&& is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)) && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
&& lookup_attribute ("omp declare target", && varpool_node::get_create (decl)->offloadable)
DECL_ATTRIBUTES (decl)))
break; break;
if (DECL_P (decl)) if (DECL_P (decl))
{ {
@ -1938,26 +1947,19 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
DECL_EXTERNAL (decl) = 0; DECL_EXTERNAL (decl) = 0;
DECL_CONTEXT (decl) = NULL_TREE; DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = make_node (BLOCK); DECL_INITIAL (decl) = make_node (BLOCK);
bool target_p = false; if (cgraph_node::get (current_function_decl)->offloadable)
if (lookup_attribute ("omp declare target", cgraph_node::get_create (decl)->offloadable = 1;
DECL_ATTRIBUTES (current_function_decl)))
target_p = true;
else else
{ {
omp_context *octx; omp_context *octx;
for (octx = ctx; octx; octx = octx->outer) for (octx = ctx; octx; octx = octx->outer)
if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET if (is_targetreg_ctx (octx))
&& gimple_omp_target_kind (octx->stmt)
== GF_OMP_TARGET_KIND_REGION)
{ {
target_p = true; cgraph_node::get_create (decl)->offloadable = 1;
g->have_offload = true;
break; break;
} }
} }
if (target_p)
DECL_ATTRIBUTES (decl)
= tree_cons (get_identifier ("omp declare target"),
NULL_TREE, DECL_ATTRIBUTES (decl));
t = build_decl (DECL_SOURCE_LOCATION (decl), t = build_decl (DECL_SOURCE_LOCATION (decl),
RESULT_DECL, NULL_TREE, void_type_node); RESULT_DECL, NULL_TREE, void_type_node);
@ -2663,8 +2665,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
break; break;
case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TARGET:
for (; ctx != NULL; ctx = ctx->outer) for (; ctx != NULL; ctx = ctx->outer)
if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET if (is_targetreg_ctx (ctx))
&& gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
{ {
const char *name; const char *name;
switch (gimple_omp_target_kind (stmt)) switch (gimple_omp_target_kind (stmt))
@ -8281,6 +8282,7 @@ expand_omp_target (struct omp_region *region)
if (kind == GF_OMP_TARGET_KIND_REGION) if (kind == GF_OMP_TARGET_KIND_REGION)
{ {
unsigned srcidx, dstidx, num; unsigned srcidx, dstidx, num;
struct cgraph_node *node;
/* If the target region needs data sent from the parent /* If the target region needs data sent from the parent
function, then the very first statement (except possible function, then the very first statement (except possible
@ -8412,6 +8414,11 @@ expand_omp_target (struct omp_region *region)
push_cfun (child_cfun); push_cfun (child_cfun);
cgraph_edge::rebuild_edges (); cgraph_edge::rebuild_edges ();
/* Prevent IPA from removing child_fn as unreachable, since there are no
refs from the parent function to child_fn in offload LTO mode. */
node = cgraph_node::get (child_fn);
node->mark_force_output ();
/* Some EH regions might become dead, see PR34608. If /* Some EH regions might become dead, see PR34608. If
pass_cleanup_cfg isn't the first pass to happen with the pass_cleanup_cfg isn't the first pass to happen with the
new child, these dead EH edges might cause problems. new child, these dead EH edges might cause problems.
@ -9326,6 +9333,17 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
DECL_COMMON (decl) = 1; DECL_COMMON (decl) = 1;
DECL_ARTIFICIAL (decl) = 1; DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1; DECL_IGNORED_P (decl) = 1;
/* If '#pragma omp critical' is inside target region, the symbol must
be marked for offloading. */
omp_context *octx;
for (octx = ctx->outer; octx; octx = octx->outer)
if (is_targetreg_ctx (octx))
{
varpool_node::get_create (decl)->offloadable = 1;
break;
}
varpool_node::finalize_decl (decl); varpool_node::finalize_decl (decl);
splay_tree_insert (critical_name_mutexes, (splay_tree_key) name, splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,

View File

@ -2416,7 +2416,7 @@ ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
/* Write out summaries for all the nodes in the callgraph. */ /* Write out summaries for all the nodes in the callgraph. */
void void
ipa_write_summaries (void) ipa_write_summaries (bool offload_lto_mode)
{ {
lto_symtab_encoder_t encoder; lto_symtab_encoder_t encoder;
int i, order_pos; int i, order_pos;
@ -2427,6 +2427,8 @@ ipa_write_summaries (void)
if (!flag_generate_lto || seen_error ()) if (!flag_generate_lto || seen_error ())
return; return;
select_what_to_stream (offload_lto_mode);
encoder = lto_symtab_encoder_new (false); encoder = lto_symtab_encoder_new (false);
/* Create the callgraph set in the same order used in /* Create the callgraph set in the same order used in
@ -2453,14 +2455,15 @@ ipa_write_summaries (void)
renumber_gimple_stmt_uids (); renumber_gimple_stmt_uids ();
pop_cfun (); pop_cfun ();
} }
if (node->definition) if (node->definition && node->need_lto_streaming)
lto_set_symtab_encoder_in_partition (encoder, node); lto_set_symtab_encoder_in_partition (encoder, node);
} }
FOR_EACH_DEFINED_FUNCTION (node) FOR_EACH_DEFINED_FUNCTION (node)
if (node->alias) if (node->alias && node->need_lto_streaming)
lto_set_symtab_encoder_in_partition (encoder, node); lto_set_symtab_encoder_in_partition (encoder, node);
FOR_EACH_DEFINED_VARIABLE (vnode) FOR_EACH_DEFINED_VARIABLE (vnode)
if (vnode->need_lto_streaming)
lto_set_symtab_encoder_in_partition (encoder, vnode); lto_set_symtab_encoder_in_partition (encoder, vnode);
ipa_write_summaries_1 (compute_ltrans_boundary (encoder)); ipa_write_summaries_1 (compute_ltrans_boundary (encoder));

View File

@ -602,7 +602,7 @@ extern void pass_fini_dump_file (opt_pass *);
extern const char *get_current_pass_name (void); extern const char *get_current_pass_name (void);
extern void print_current_pass (FILE *); extern void print_current_pass (FILE *);
extern void debug_pass (void); extern void debug_pass (void);
extern void ipa_write_summaries (void); extern void ipa_write_summaries (bool);
extern void ipa_write_optimization_summaries (struct lto_symtab_encoder_d *); extern void ipa_write_optimization_summaries (struct lto_symtab_encoder_d *);
extern void ipa_read_summaries (void); extern void ipa_read_summaries (void);
extern void ipa_read_optimization_summaries (void); extern void ipa_read_optimization_summaries (void);

View File

@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-alias.h" #include "tree-ssa-alias.h"
#include "gimple.h" #include "gimple.h"
#include "lto-streamer.h" #include "lto-streamer.h"
#include "context.h"
const char * const tls_model_names[]={"none", "tls-emulated", "tls-real", const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
"tls-global-dynamic", "tls-local-dynamic", "tls-global-dynamic", "tls-local-dynamic",
@ -164,6 +165,14 @@ varpool_node::get_create (tree decl)
node = varpool_node::create_empty (); node = varpool_node::create_empty ();
node->decl = decl; node->decl = decl;
if (flag_openmp
&& lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
{
node->offloadable = 1;
g->have_offload = true;
}
node->register_symbol (); node->register_symbol ();
return node; return node;
} }