Hi,

On 05 Sep 19:09, Ilya Verbin wrote:
> I hope that it will not affect the regular LTO compilation.  At least, the
> 'make check' did not reveal any regression on the system with linker plugin.

I found that relying on -flto option in lto-wrapper was a bad idea.
E.g., this simple case is not working:

$ gcc -c -flto test.c
$ gcc test.o  # Here -flto is absent, but lto-wrapper must recompile IR from 
test.o

So I reverted back all conditions with lto_mode in lto-wrapper, and instead 
introduced a new flag have_lto.
The following patch looks like working now.

Thanks,
  -- Ilya


---
 gcc/cgraphunit.c        | 38 +++++++++++++++++++++-------
 gcc/lto-wrapper.c       | 66 +++++++++++++++++++++++++++----------------------
 gcc/omp-low.c           |  6 +++++
 gcc/passes.c            |  2 +-
 lto-plugin/lto-plugin.c | 25 ++++++++++++++++++-
 5 files changed, 97 insertions(+), 40 deletions(-)

diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index f0c9f5c..b87e6dd 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -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);
diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c
index 80d10f3..86669cf 100644
--- a/gcc/lto-wrapper.c
+++ b/gcc/lto-wrapper.c
@@ -619,6 +619,7 @@ run_gcc (unsigned argc, char *argv[])
   unsigned int decoded_options_count;
   struct obstack argv_obstack;
   int new_head_argc;
+  bool have_lto = false;
   bool have_offload = false;
 
   /* Get the driver and options.  */
@@ -668,6 +669,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 +681,7 @@ 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;
+      have_lto = true;
       lseek (fd, file_offset + offset, SEEK_SET);
       data = (char *)xmalloc (length);
       read (fd, data, length);
@@ -871,6 +873,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 (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 object files contain offload sections, but do not contain LTO sections,
+     then there is no need to perform a link-time recompilation, i.e.
+     lto-wrapper is used only for a compilation of offload images.  */
+  if (have_offload && !have_lto)
+    {
+      for (i = 1; i < argc; ++i)
+       if (strncmp (argv[i], "-fresolution=", sizeof ("-fresolution=") - 1))
+         printf ("%s\n", argv[i]);
+      goto finish;
+    }
+
   if (lto_mode == LTO_MODE_LTO)
     {
       flto_out = make_temp_file (".lto.o");
@@ -1084,25 +1112,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 +1119,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 +1126,10 @@ cont:
       obstack_free (&env_obstack, NULL);
     }
 
+finish:
+  if (ompend)
+    printf ("%s\n", ompend);
+
   obstack_free (&argv_obstack, NULL);
 }
 
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 6ed8239..cf00407 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -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);
diff --git a/gcc/passes.c b/gcc/passes.c
index 8172185..e776059 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -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);
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index 910e23c..f53d9e2 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -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 = &lto_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)
-- 
1.8.3.1

Reply via email to