@@ -2040,13 +2040,25 @@ output_in_order (void)
free (nodes);
}
-/* Collect all global variables with "omp declare target" attribute into
- OFFLOAD_VARS. It will be streamed out in ipa_write_summaries. */
+/* Check whether there is at least one function or global variable to offload.
+ Also collect all such global variables into OFFLOAD_VARS, the functions were
+ already collected in omp-low.c. They will be streamed out in
+ ipa_write_summaries. */
-static void
-init_offload_var_table (void)
+static bool
+initialize_offload (void)
{
+ bool have_offload = false;
+ struct cgraph_node *node;
struct varpool_node *vnode;
+
+ FOR_EACH_DEFINED_FUNCTION (node)
+ if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (node->decl)))
+ {
+ have_offload = true;
+ break;
+ }
+
FOR_EACH_DEFINED_VARIABLE (vnode)
{
if (!lookup_attribute ("omp declare target",
@@ -2054,13 +2066,17 @@ init_offload_var_table (void)
|| TREE_CODE (vnode->decl) != VAR_DECL
|| DECL_SIZE (vnode->decl) == 0)
continue;
+ have_offload = true;
vec_safe_push (offload_vars, vnode->decl);
}
+
+ return have_offload;
}
static void
ipa_passes (void)
{
+ bool have_offload = false;
gcc::pass_manager *passes = g->get_passes ();
set_cfun (NULL);
@@ -2068,6 +2084,14 @@ ipa_passes (void)
gimple_register_cfg_hooks ();
bitmap_obstack_initialize (NULL);
+ if (!in_lto_p && (flag_openacc || flag_openmp))
+ {
+ have_offload = initialize_offload ();
+ /* OpenACC / OpenMP offloading requires LTO infrastructure. */
+ if (have_offload)
+ flag_generate_lto = 1;
+ }
+
invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_START, NULL);
if (!in_lto_p)
@@ -2108,11 +2132,7 @@ ipa_passes (void)
if (!in_lto_p)
{
- init_offload_var_table ();
-
- if ((flag_openacc || flag_openmp)
- && !(vec_safe_is_empty (offload_funcs)
- && vec_safe_is_empty (offload_vars)))
+ if (have_offload)
{
section_name_prefix = OMP_SECTION_NAME_PREFIX;
ipa_write_summaries (true);
@@ -668,6 +668,11 @@ run_gcc (unsigned argc, char *argv[])
close (fd);
continue;
}
+ /* We may choose not to write out this .opts section in the future. In
+ that case we'll have to use something else to look for. */
+ if (simple_object_find_section (sobj, OMP_SECTION_NAME_PREFIX "." "opts",
+ &offset, &length, &errmsg, &err))
+ have_offload = true;
if (!simple_object_find_section (sobj, LTO_SECTION_NAME_PREFIX "." "opts",
&offset, &length, &errmsg, &err))
{
@@ -675,11 +680,6 @@ run_gcc (unsigned argc, char *argv[])
close (fd);
continue;
}
- /* We may choose not to write out this .opts section in the future. In
- that case we'll have to use something else to look for. */
- if (simple_object_find_section (sobj, OMP_SECTION_NAME_PREFIX "." "opts",
- &offset, &length, &errmsg, &err))
- have_offload = true;
lseek (fd, file_offset + offset, SEEK_SET);
data = (char *)xmalloc (length);
read (fd, data, length);
@@ -871,7 +871,32 @@ run_gcc (unsigned argc, char *argv[])
/* Remember at which point we can scrub args to re-use the commons. */
new_head_argc = obstack_object_size (&argv_obstack) / sizeof (void *);
- if (lto_mode == LTO_MODE_LTO)
+ if (have_offload)
+ {
+ compile_images_for_openmp_targets (argc, argv);
+ if (offload_names)
+ {
+ find_ompbeginend ();
+ for (i = 0; offload_names[i]; i++)
+ printf ("%s\n", offload_names[i]);
+ free_array_of_ptrs ((void **) offload_names, i);
+ }
+ }
+
+ if (ompbegin)
+ printf ("%s\n", ompbegin);
+
+ if (lto_mode == LTO_MODE_NONE)
+ {
+ /* If we are in lto-wrapper, but -flto option is absent, it means that
+ there is no need to perform a link-time recompilation, i.e. lto-wrapper
+ is used only for compiling offload images. */
+ for (i = 1; i < argc; ++i)
+ if (strncmp (argv[i], "-fresolution=", sizeof ("-fresolution=") - 1))
+ printf ("%s\n", argv[i]);
+ goto finish;
+ }
+ else if (lto_mode == LTO_MODE_LTO)
{
flto_out = make_temp_file (".lto.o");
if (linker_output)
@@ -879,7 +904,7 @@ run_gcc (unsigned argc, char *argv[])
obstack_ptr_grow (&argv_obstack, "-o");
obstack_ptr_grow (&argv_obstack, flto_out);
}
- else
+ else if (lto_mode == LTO_MODE_WHOPR)
{
const char *list_option = "-fltrans-output-list=";
size_t list_option_len = strlen (list_option);
@@ -939,7 +964,7 @@ run_gcc (unsigned argc, char *argv[])
free (flto_out);
flto_out = NULL;
}
- else
+ else if (lto_mode == LTO_MODE_WHOPR)
{
FILE *stream = fopen (ltrans_output_file, "r");
FILE *mstream = NULL;
@@ -1084,25 +1109,6 @@ cont:
for (i = 0; i < nr; ++i)
maybe_unlink (input_names[i]);
}
- if (have_offload)
- {
- compile_images_for_openmp_targets (argc, argv);
- if (offload_names)
- {
- find_ompbeginend ();
- for (i = 0; offload_names[i]; i++)
- {
- fputs (offload_names[i], stdout);
- putc ('\n', stdout);
- }
- free_array_of_ptrs ((void **)offload_names, i);
- }
- }
- if (ompbegin)
- {
- fputs (ompbegin, stdout);
- putc ('\n', stdout);
- }
for (i = 0; i < nr; ++i)
{
@@ -1110,11 +1116,6 @@ cont:
putc ('\n', stdout);
free (input_names[i]);
}
- if (ompend)
- {
- fputs (ompend, stdout);
- putc ('\n', stdout);
- }
nr = 0;
free (output_names);
free (input_names);
@@ -1122,6 +1123,10 @@ cont:
obstack_free (&env_obstack, NULL);
}
+finish:
+ if (ompend)
+ printf ("%s\n", ompend);
+
obstack_free (&argv_obstack, NULL);
}
@@ -13774,6 +13774,12 @@ omp_finish_file (void)
get_identifier (".omp_var_table"),
vars_decl_type);
TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
+ /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
+ otherwise a joint table in a binary will contain padding between
+ tables from multiple object files. */
+ DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
+ DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
+ DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
DECL_INITIAL (funcs_decl) = ctor_f;
DECL_INITIAL (vars_decl) = ctor_v;
set_decl_section_name (funcs_decl, funcs_section_name);
@@ -2303,7 +2303,7 @@ ipa_write_summaries (bool is_omp)
struct cgraph_node *node;
struct cgraph_node **order;
- if (!(flag_generate_lto || flag_openacc || flag_openmp) || seen_error () )
+ if (!flag_generate_lto || seen_error ())
return;
select_what_to_dump (is_omp);
@@ -86,6 +86,8 @@ along with this program; see the file COPYING3. If not see
#define LTO_SECTION_PREFIX ".gnu.lto_.symtab"
#define LTO_SECTION_PREFIX_LEN (sizeof (LTO_SECTION_PREFIX) - 1)
+#define OFFLOAD_SECTION ".gnu.target_lto_.opts"
+#define OFFLOAD_SECTION_LEN (sizeof (OFFLOAD_SECTION) - 1)
/* The part of the symbol table the plugin has to keep track of. Note that we
must keep SYMS until all_symbols_read is called to give the linker time to
@@ -111,6 +113,7 @@ struct plugin_symtab
struct plugin_objfile
{
int found;
+ int offload;
simple_object_read *objfile;
struct plugin_symtab *out;
const struct ld_plugin_input_file *file;
@@ -862,6 +865,21 @@ err:
return 0;
}
+/* Find an offload section of an object file. */
+
+static int
+process_offload_section (void *data, const char *name, off_t offset, off_t len)
+{
+ if (!strncmp (name, OFFLOAD_SECTION, OFFLOAD_SECTION_LEN))
+ {
+ struct plugin_objfile *obj = (struct plugin_objfile *) data;
+ obj->offload = 1;
+ return 0;
+ }
+
+ return 1;
+}
+
/* Callback used by gold to check if the plugin will claim FILE. Writes
the result in CLAIMED. */
@@ -899,6 +917,7 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
*claimed = 0;
obj.file = file;
obj.found = 0;
+ obj.offload = 0;
obj.out = <o_file.symtab;
errmsg = NULL;
obj.objfile = simple_object_start_read (file->fd, file->offset, LTO_SEGMENT_NAME,
@@ -920,7 +939,11 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
goto err;
}
- if (obj.found == 0)
+ if (obj.objfile)
+ simple_object_find_sections (obj.objfile, process_offload_section,
+ &obj, &err);
+
+ if (obj.found == 0 && obj.offload == 0)
goto err;
if (obj.found > 1)