summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlya Verbin <ilya.verbin@intel.com>2014-09-25 13:43:09 +0400
committerIlya Verbin <ilya.verbin@intel.com>2014-11-12 15:39:27 +0300
commit3918aafa926d870c56795fce018d294ab376fb90 (patch)
tree46735aa94d1a16e9b864c2bc56e4044b6e5ca85d
parent3a0b95b951b135ac9af6aafcf6104d9e77940df8 (diff)
downloadgcc-3918aafa926d870c56795fce018d294ab376fb90.tar.gz
[PATCH 2] OpenMP 4.0 offloading infrastructure: LTO streaming
2014-10-01 Ilya Verbin <ilya.verbin@intel.com> Ilya Tocar <ilya.tocar@intel.com> Andrey Turetskiy <andrey.turetskiy@intel.com> Bernd Schmidt <bernds@codesourcery.com> gcc/ * cgraph.h (symtab_node): Add need_lto_streaming flag. * cgraphunit.c: Include lto-section-names.h. (initialize_offload): New function. (ipa_passes): Initialize offload and call ipa_write_summaries if there is something to write to OFFLOAD_SECTION_NAME_PREFIX sections. (symbol_table::compile): Call lto_streamer_hooks_init under flag_openmp. * ipa-inline-analysis.c (inline_generate_summary): Do not exit under flag_openmp. (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 (is_targetreg_ctx): New function. (create_omp_child_function, check_omp_nesting_restrictions): Use it. (expand_omp_target): Set mark_force_output for the offloaded functions. (lower_omp_critical): Add target attribute 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. 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.
-rw-r--r--gcc/cgraph.c9
-rw-r--r--gcc/cgraph.h7
-rw-r--r--gcc/cgraphunit.c20
-rw-r--r--gcc/context.c2
-rw-r--r--gcc/context.h3
-rw-r--r--gcc/ipa-inline-analysis.c12
-rw-r--r--gcc/lto-cgraph.c32
-rw-r--r--gcc/lto-section-names.h5
-rw-r--r--gcc/lto-streamer.c3
-rw-r--r--gcc/lto-streamer.h1
-rw-r--r--gcc/lto/lto-object.c3
-rw-r--r--gcc/lto/lto-partition.c2
-rw-r--r--gcc/lto/lto.c6
-rw-r--r--gcc/omp-low.c54
-rw-r--r--gcc/passes.c11
-rw-r--r--gcc/tree-pass.h2
-rw-r--r--gcc/varpool.c9
17 files changed, 143 insertions, 38 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 7216b897184..8dcccbf19c6 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see
#include "profile.h"
#include "params.h"
#include "tree-chkp.h"
+#include "context.h"
/* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */
#include "tree-pass.h"
@@ -494,6 +495,14 @@ cgraph_node::create (tree decl)
gcc_assert (TREE_CODE (decl) == FUNCTION_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 ();
if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index e2becb96d56..1395bc1b4d9 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -450,6 +450,13 @@ public:
/* Set when init priority is set. */
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. */
int order;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 25af2347f42..9f49ed05f6e 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -224,6 +224,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "dbgcnt.h"
#include "tree-chkp.h"
+#include "lto-section-names.h"
/* Queue of cgraph nodes scheduled to be added into cgraph. This is a
secondary queue used during optimization to accommodate passes that
@@ -2079,7 +2080,18 @@ ipa_passes (void)
targetm.asm_out.lto_start ();
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)
targetm.asm_out.lto_end ();
@@ -2163,8 +2175,12 @@ symbol_table::compile (void)
fprintf (stderr, "Performing interprocedural optimizations\n");
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 (flag_lto)
+ if (flag_generate_lto)
lto_streamer_hooks_init ();
/* Don't run the IPA passes if there was any error or sorry messages. */
diff --git a/gcc/context.c b/gcc/context.c
index 5339e28a98b..9279be40dd7 100644
--- a/gcc/context.c
+++ b/gcc/context.c
@@ -30,6 +30,8 @@ gcc::context *g;
gcc::context::context ()
{
+ have_offload = false;
+
/* 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
before the pass manager. */
diff --git a/gcc/context.h b/gcc/context.h
index b8fb439f1af..689ae5ad187 100644
--- a/gcc/context.h
+++ b/gcc/context.h
@@ -33,6 +33,9 @@ class context
public:
context ();
+ /* The flag shows if there are symbols to be streamed for offloading. */
+ bool have_offload;
+
/* Pass-management. */
pass_manager *get_passes () { gcc_assert (m_passes); return m_passes; }
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index eb1c6ec2d0d..0373b108699 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -4024,7 +4024,7 @@ inline_generate_summary (void)
/* When not optimizing, do not bother to analyze. Inlining is still done
because edge redirection needs to happen there. */
- if (!optimize && !flag_lto && !flag_wpa)
+ if (!optimize && !flag_generate_lto && !flag_wpa)
return;
function_insertion_hook_holder =
@@ -4339,11 +4339,6 @@ void
inline_free_summary (void)
{
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)
symtab->remove_cgraph_insertion_hook (function_insertion_hook_holder);
function_insertion_hook_holder = NULL;
@@ -4359,6 +4354,11 @@ inline_free_summary (void)
if (edge_duplication_hook_holder)
symtab->remove_edge_duplication_hook (edge_duplication_hook_holder);
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);
inline_edge_summary_vec.release ();
if (edge_predicate_pool)
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index da1f0e44682..fc8410c1c3e 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -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++)
{
+ /* 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
|| !lto_symtab_encoder_in_partition_p (encoder, ref->referring))
return true;
@@ -348,9 +353,16 @@ reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t
if (node->global.inlined_to)
return false;
for (e = node->callers; e; e = e->next_caller)
- if (e->caller->in_other_partition
- || !lto_symtab_encoder_in_partition_p (encoder, e->caller))
- return true;
+ {
+ /* 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
+ || !lto_symtab_encoder_in_partition_p (encoder, e->caller))
+ return true;
+ }
return false;
}
@@ -818,6 +830,16 @@ create_references (lto_symtab_encoder_t encoder, symtab_node *node)
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
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))
{
struct cgraph_node *node = lsei_cgraph_node (lsei);
+ if (!node->need_lto_streaming)
+ continue;
add_node_to (encoder, node, true);
lto_set_symtab_encoder_in_partition (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);
+ if (!vnode->need_lto_streaming)
+ continue;
lto_set_symtab_encoder_in_partition (encoder, vnode);
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
create_references (encoder, vnode);
diff --git a/gcc/lto-section-names.h b/gcc/lto-section-names.h
index cb752309872..f5dbed26bad 100644
--- a/gcc/lto-section-names.h
+++ b/gcc/lto-section-names.h
@@ -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
sections a '.' and the section type are appended. */
#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. */
diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c
index b6cac0b5e99..e8347dccd65 100644
--- a/gcc/lto-streamer.c
+++ b/gcc/lto-streamer.c
@@ -60,6 +60,7 @@ struct lto_stats_d lto_stats;
static bitmap_obstack lto_obstack;
static bool lto_obstack_initialized;
+const char *section_name_prefix = LTO_SECTION_NAME_PREFIX;
/* 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);
else
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);
}
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 4b875a2b8ba..cdbe507d718 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -831,6 +831,7 @@ bool referenced_from_this_partition_p (symtab_node *,
bool reachable_from_this_partition_p (struct cgraph_node *,
lto_symtab_encoder_t);
lto_symtab_encoder_t compute_ltrans_boundary (lto_symtab_encoder_t encoder);
+void select_what_to_stream (bool);
/* In lto-symtab.c. */
diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c
index 1178326b991..b4124f65b97 100644
--- a/gcc/lto/lto-object.c
+++ b/gcc/lto/lto-object.c
@@ -242,8 +242,7 @@ lto_obj_add_section (void *data, const char *name, off_t offset,
void **slot;
struct lto_section_list *list = loasd->list;
- if (strncmp (name, LTO_SECTION_NAME_PREFIX,
- strlen (LTO_SECTION_NAME_PREFIX)) != 0)
+ if (strncmp (name, section_name_prefix, strlen (section_name_prefix)))
return 1;
new_name = xstrdup (name);
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index 0e1a95bf918..65f0582cf6b 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -952,6 +952,8 @@ lto_promote_cross_file_statics (void)
gcc_assert (flag_wpa);
+ select_what_to_stream (false);
+
/* First compute boundaries. */
n_sets = ltrans_partitions.length ();
for (i = 0; i < n_sets; i++)
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index d8519d9426b..fbf4913875d 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -2137,7 +2137,7 @@ lto_section_with_id (const char *name, unsigned HOST_WIDE_INT *id)
{
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;
s = strrchr (name, '.');
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);
+#ifdef ACCEL_COMPILER
+ section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
+#endif
+
real_file_decl_data
= decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
real_file_count = nfiles;
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index b59d069ac14..71cf471ef66 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -86,6 +86,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-nested.h"
#include "tree-eh.h"
#include "cilk.h"
+#include "context.h"
/* 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. */
static inline bool
@@ -1642,8 +1653,7 @@ scan_sharing_clauses (tree clauses, omp_context *ctx)
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& DECL_P (decl)
&& is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
- && lookup_attribute ("omp declare target",
- DECL_ATTRIBUTES (decl)))
+ && varpool_node::get_create (decl)->offloadable)
break;
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& 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);
if (DECL_P (decl)
&& is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
- && lookup_attribute ("omp declare target",
- DECL_ATTRIBUTES (decl)))
+ && varpool_node::get_create (decl)->offloadable)
break;
if (DECL_P (decl))
{
@@ -1938,26 +1947,19 @@ create_omp_child_function (omp_context *ctx, bool task_copy)
DECL_EXTERNAL (decl) = 0;
DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = make_node (BLOCK);
- bool target_p = false;
- if (lookup_attribute ("omp declare target",
- DECL_ATTRIBUTES (current_function_decl)))
- target_p = true;
+ if (cgraph_node::get (current_function_decl)->offloadable)
+ cgraph_node::get_create (decl)->offloadable = 1;
else
{
omp_context *octx;
for (octx = ctx; octx; octx = octx->outer)
- if (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
- && gimple_omp_target_kind (octx->stmt)
- == GF_OMP_TARGET_KIND_REGION)
+ if (is_targetreg_ctx (octx))
{
- target_p = true;
+ cgraph_node::get_create (decl)->offloadable = 1;
+ g->have_offload = true;
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),
RESULT_DECL, NULL_TREE, void_type_node);
@@ -2663,8 +2665,7 @@ check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
break;
case GIMPLE_OMP_TARGET:
for (; ctx != NULL; ctx = ctx->outer)
- if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
- && gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_REGION)
+ if (is_targetreg_ctx (ctx))
{
const char *name;
switch (gimple_omp_target_kind (stmt))
@@ -8281,6 +8282,7 @@ expand_omp_target (struct omp_region *region)
if (kind == GF_OMP_TARGET_KIND_REGION)
{
unsigned srcidx, dstidx, num;
+ struct cgraph_node *node;
/* If the target region needs data sent from the parent
function, then the very first statement (except possible
@@ -8412,6 +8414,11 @@ expand_omp_target (struct omp_region *region)
push_cfun (child_cfun);
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
pass_cleanup_cfg isn't the first pass to happen with the
new child, these dead EH edges might cause problems.
@@ -9282,6 +9289,17 @@ lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
DECL_COMMON (decl) = 1;
DECL_ARTIFICIAL (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);
splay_tree_insert (critical_name_mutexes, (splay_tree_key) name,
diff --git a/gcc/passes.c b/gcc/passes.c
index 5e91a79414a..aa40fe5fa30 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -2416,7 +2416,7 @@ ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
/* Write out summaries for all the nodes in the callgraph. */
void
-ipa_write_summaries (void)
+ipa_write_summaries (bool offload_lto_mode)
{
lto_symtab_encoder_t encoder;
int i, order_pos;
@@ -2427,6 +2427,8 @@ ipa_write_summaries (void)
if (!flag_generate_lto || seen_error ())
return;
+ select_what_to_stream (offload_lto_mode);
+
encoder = lto_symtab_encoder_new (false);
/* Create the callgraph set in the same order used in
@@ -2453,15 +2455,16 @@ ipa_write_summaries (void)
renumber_gimple_stmt_uids ();
pop_cfun ();
}
- if (node->definition)
+ if (node->definition && node->need_lto_streaming)
lto_set_symtab_encoder_in_partition (encoder, node);
}
FOR_EACH_DEFINED_FUNCTION (node)
- if (node->alias)
+ if (node->alias && node->need_lto_streaming)
lto_set_symtab_encoder_in_partition (encoder, node);
FOR_EACH_DEFINED_VARIABLE (vnode)
- lto_set_symtab_encoder_in_partition (encoder, vnode);
+ if (vnode->need_lto_streaming)
+ lto_set_symtab_encoder_in_partition (encoder, vnode);
ipa_write_summaries_1 (compute_ltrans_boundary (encoder));
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index a3efdd84b08..387e0e324ad 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -600,7 +600,7 @@ extern void pass_fini_dump_file (opt_pass *);
extern const char *get_current_pass_name (void);
extern void print_current_pass (FILE *);
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_read_summaries (void);
extern void ipa_read_optimization_summaries (void);
diff --git a/gcc/varpool.c b/gcc/varpool.c
index ac7abc1be86..ee889f2db53 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssa-alias.h"
#include "gimple.h"
#include "lto-streamer.h"
+#include "context.h"
const char * const tls_model_names[]={"none", "tls-emulated", "tls-real",
"tls-global-dynamic", "tls-local-dynamic",
@@ -164,6 +165,14 @@ varpool_node::get_create (tree decl)
node = varpool_node::create_empty ();
node->decl = decl;
+
+ if (flag_openmp
+ && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
+ {
+ node->offloadable = 1;
+ g->have_offload = true;
+ }
+
node->register_symbol ();
return node;
}