This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[lto] Initial support to avoid redundant optimization/codegen


In an LTO compile, we typically compile the same code twice.  The
first time with the front-end and the second time with lto1.
However, in several instances, the second compilation is not
really necessary.

For instance, suppose that we have 3 files f[123].o and no IPA
passes did any transformations that affected f3.o.  With the
current compilation model, we will generate final code for f3.o
when it's compiled with the front-end and again when compiled
with lto1.  In both cases, we will end up generating the exact
same bits.  This is really wasteful.

This patch adds some initial foundations to support not compiling
f3.o again.  With the current setup, it is much easier to support
this when using WHOPR.  When we detect that f3.o does not need to
be recompiled we can simply use it unchanged instead of
generating an LTRANS file for it.

The same would be possible with LTO by simply removing the
callgraph set representing f3.o.

This patch does not change the behaviour, it simply sets things
up.  I have a fully functional patch for the complete
functionality but it still needs some debugging, so I'm flushing
these bits out to avoid lugging a big patch around.

Bootstrapped and tested on x86_64.


Diego.



	* lto-function-out.c (output_ssa_names): Do not emit
	SSA names for memory symbols.
	(output_tree_with_context): Call decl_function_context to
	check if EXPR is a global symbol.
	* lto-function-in.c: Do not include cpplib.h
	(input_var_decl): Tidy.
	* lto-cgraph.c (input_node): Tidy.
	(input_cgraph_1): Tidy.
	(input_cgraph): Call lto_mark_file_for_ltrans.
	* lto-section-in.h: Include target.h and cgraph.h.
	(struct lto_file_decl_data): Tidy.
	Add field needs_ltrans_p.
	(lto_file_needs_ltrans_p): New.
	(lto_mark_file_for_ltrans): New.
	(cgraph_node_set_needs_ltrans_p): New.
	* Makefile.in (LTO_SECTION_IN_H): Add dependency on
	TARGET_H and CGRAPH_H.
	(LTO_SECTION_OUT_H): Fix incorrect dependencies.
	(lto-function-in.o): Remove dependency on dwarf2asm.h and
	dwarf2out.h.

lto/ChangeLog

	* lto.c (free_section_data): Tidy.
	(lto_1_to_1_map): Tidy.
	(lto_add_all_inlinees): Tidy.
	(prefix_name_with_star): New.
	(get_filename_for_set): New.
	(lto_wpa_write_files): Call cgraph_node_set_needs_ltrans_p
	to determine what cgraph node sets to write.
	Call get_filename_for_set to compute temporary file
	names.
	(lto_execute_ltrans): Do not execute LTRANS on files with
	names that start with '*'.
	Move logic to execute LTRANS together so that LTRANS is
	invoked only if there are any files to compile.
	(do_whole_program_analysis): Only remove output files
	that do not start with '*'.

Index: lto-function-out.c
===================================================================
--- lto-function-out.c	(revision 146527)
+++ lto-function-out.c	(working copy)
@@ -1,4 +1,4 @@
-/* Write the gimple representation of a function and it's local
+/* Write the gimple representation of a function and its local
    variables to a .o file.

    Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -1557,7 +1557,9 @@ output_ssa_names (struct output_block *o
     {
       tree ptr = VEC_index (tree, SSANAMES (fn), i);

-      if (ptr == NULL_TREE || SSA_NAME_IN_FREE_LIST (ptr))
+      if (ptr == NULL_TREE
+	  || SSA_NAME_IN_FREE_LIST (ptr)
+	  || !is_gimple_reg (ptr))
 	continue;

       output_uleb128 (ob, i);
@@ -3307,7 +3309,7 @@ output_tree_with_context (struct output_
       break;

     case VAR_DECL:
-      if (TREE_STATIC (expr) || DECL_EXTERNAL (expr))
+      if (decl_function_context (expr) == NULL_TREE)
         output_var_decl (ob, expr);
       else
         /* We should not be seeing local variables here.  */
Index: lto-function-in.c
===================================================================
--- lto-function-in.c	(revision 146527)
+++ lto-function-in.c	(working copy)
@@ -52,7 +52,6 @@ Boston, MA 02110-1301, USA.  */
 #include "lto-section-in.h"
 #include "lto-tree-in.h"
 #include "lto-utils.h"
-#include "cpplib.h"

 tree input_tree (struct lto_input_block *, struct data_in *);
 static tree input_tree_with_context (struct lto_input_block *ib,
@@ -2826,12 +2825,9 @@ input_var_decl (struct lto_input_block *
       SET_DECL_DEBUG_EXPR (decl, debug_expr);
   }

-  /* FIXME lto: Adapted from DWARF reader. Probably needs more thought.
-     We are only interested in variables with static storage duration.
-     I expected the test "DECL_FILE_SCOPE_P (decl)" to suffice below, but
-     it does not work.  In particular, the context of a vtable is the
-     class to which it belongs.  */
-  if (!decl_function_context (decl))
+  /* Register symbols with file or global scope to mark what input
+     file has their definition.  */
+  if (decl_function_context (decl) == NULL_TREE)
     {
       /* Variable has file scope, not local. Need to ensure static variables
 	 between different files don't clash unexpectedly.  */
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 146424)
+++ lto-cgraph.c	(working copy)
@@ -457,7 +457,7 @@ input_overwrite_node (struct lto_file_de
    Return the node read or overwriten.  */

 static struct cgraph_node *
-input_node (struct lto_file_decl_data* file_data,
+input_node (struct lto_file_decl_data *file_data,
 	    struct lto_input_block *ib,
 	    enum LTO_cgraph_tags tag)
 {
@@ -634,7 +634,7 @@ input_edge (struct lto_input_block *ib,
 /* Input a cgraph from IB using the info in FILE_DATA.  */

 static void
-input_cgraph_1 (struct lto_file_decl_data* file_data,
+input_cgraph_1 (struct lto_file_decl_data *file_data,
 		struct lto_input_block *ib)
 {
   enum LTO_cgraph_tags tag;
@@ -717,6 +717,10 @@ input_cgraph (void)
       input_cgraph_1 (file_data, ib);
       lto_destroy_simple_input_block (file_data, LTO_section_cgraph,
 				      ib, data, len);
+
+      /* Assume that every file read needs to be processed by LTRANS.  */
+      if (flag_wpa)
+	lto_mark_file_for_ltrans (file_data);
     }

   /* Clear out the aux field that was used to store enough state to
Index: lto-section-in.h
===================================================================
--- lto-section-in.h	(revision 146424)
+++ lto-section-in.h	(working copy)
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.
 #ifndef GCC_LTO_SECTION_IN_H
 #define GCC_LTO_SECTION_IN_H

+#include "target.h"
+#include "cgraph.h"
 #include "lto-header.h"

 struct lto_input_block
@@ -51,10 +53,11 @@ struct lto_tree_ref_table {
   unsigned int size;	/* Size of array. */
 };

-/* Structure to hold states of input scope. */
-struct lto_in_decl_state {
+/* Structure to hold states of input scope.  */
+struct lto_in_decl_state
+{
   /* Array of lto_in_decl_buffers to store type and decls streams. */
-  struct lto_tree_ref_table	streams[LTO_N_DECL_STREAMS];
+  struct lto_tree_ref_table streams[LTO_N_DECL_STREAMS];

   /* If this in-decl state is associated with a function. FN_DECL
      point to the FUNCTION_DECL. */
@@ -70,21 +73,21 @@ typedef struct lto_in_decl_state *lto_in
 struct lto_file_decl_data
 {
   /* Decl state currently used. */
-  struct lto_in_decl_state	*current_decl_state;
+  struct lto_in_decl_state *current_decl_state;

   /* Decl state corresponding to regions outside of any functions
      in the compilation unit. */
-  struct lto_in_decl_state	*global_decl_state;
+  struct lto_in_decl_state *global_decl_state;

   /* Hash table maps lto-related section names to location in file.  */
   htab_t function_decl_states;

-  /* The .o file that these offsets relate to.
-
-  FIXME!!! This will most likely have to be upgraded if the .o files
-  have been archived.  */
+  /* The .o file that these offsets relate to.  */
   const char *file_name;

+  /* Nonzero if this file should be recompiled with LTRANS.  */
+  unsigned needs_ltrans_p : 1;
+
   /* If the file is open, this is the fd of the mapped section.  This
      is -1 if the file has not yet been opened.  */
   int fd;
@@ -216,4 +219,38 @@ extern struct lto_in_decl_state *
 extern void lto_debug_in_fun (struct lto_debug_context *, char);
 #endif

+/* In lto-function-out.c  */
+extern void lto_register_decl_definition (tree, struct lto_file_decl_data *);
+
+/* Return true if FILE needs to be compiled with LTRANS.  */
+
+static inline bool
+lto_file_needs_ltrans_p (struct lto_file_decl_data *file)
+{
+  return file->needs_ltrans_p != 0;
+}
+
+/* Mark FILE to be compiled with LTRANS.  */
+
+static inline void
+lto_mark_file_for_ltrans (struct lto_file_decl_data *file)
+{
+  file->needs_ltrans_p = 1;
+}
+
+/* Return true if any files in node set SET need to be compiled
+   with LTRANS.  */
+
+static inline bool
+cgraph_node_set_needs_ltrans_p (cgraph_node_set set)
+{
+  cgraph_node_set_iterator csi;
+
+  for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+    if (lto_file_needs_ltrans_p (csi_node (csi)->local.lto_file_data))
+      return true;
+
+  return false;
+}
+
 #endif  /* GCC_LTO_SECTION_IN_H  */
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 146424)
+++ lto/lto.c	(working copy)
@@ -503,15 +503,16 @@ free_section_data (struct lto_file_decl_
   if (file_data->fd == -1)
     return;

-  computed_offset = ((intptr_t)offset) & page_mask;
-  diff = (intptr_t)offset - computed_offset;
+  computed_offset = ((intptr_t) offset) & page_mask;
+  diff = (intptr_t) offset - computed_offset;
   computed_len = len + diff;

-  munmap ((void *)computed_offset, computed_len);
+  munmap ((void *) computed_offset, computed_len);
 }

 /* Vector of all cgraph node sets. */
-static GTY (()) VEC(cgraph_node_set ,gc) *lto_cgraph_node_sets;
+static GTY (()) VEC(cgraph_node_set, gc) *lto_cgraph_node_sets;
+

 /* Group cgrah nodes by input files.  This is used mainly for testing
    right now.  */
@@ -548,7 +549,7 @@ lto_1_to_1_map (void)

       slot = pointer_map_contains (pmap, file_data);
       if (slot)
-	  set = (cgraph_node_set) *slot;
+	set = (cgraph_node_set) *slot;
       else
 	{
 	  set = cgraph_node_set_new ();
@@ -556,6 +557,7 @@ lto_1_to_1_map (void)
 	  *slot = set;
 	  VEC_safe_push (cgraph_node_set, gc, lto_cgraph_node_sets, set);
 	}
+
       cgraph_node_set_add (set, node);
     }

@@ -570,7 +572,7 @@ finish:


 /* Add inlined clone NODE and its master clone to SET, if NODE itself has
-   inlined callee, recursively add the callees.  */
+   inlined callees, recursively add the callees.  */

 static void
 lto_add_inline_clones (cgraph_node_set set, struct cgraph_node *node,
@@ -594,8 +596,8 @@ lto_add_inline_clones (cgraph_node_set s
 }

 /* Compute the transitive closure of inlining of SET based on the
-   information in the callgraph.  Returns a bitmap of decls indexed
-   by UID.  */
+   information in the callgraph.  Returns a bitmap of decls that have
+   been inlined into SET indexed by UID.  */

 static bitmap
 lto_add_all_inlinees (cgraph_node_set set)
@@ -644,6 +646,8 @@ lto_add_all_inlinees (cgraph_node_set se
     }
   while (changed);

+  /* Transitively add to SET all the inline clones for every node that
+     has been inlined.  */
   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
     {
       node = csi_node (csi);
@@ -789,6 +793,7 @@ lto_scan_statics_in_cgraph_node (struct
   /* Return if the DECL of nodes has been visited before.  */
   if (bitmap_bit_p (context->seen_node_decls, DECL_UID (node->decl)))
     return;
+
   bitmap_set_bit (context->seen_node_decls, DECL_UID (node->decl));

   state = lto_get_function_in_decl_state (node->local.lto_file_data,
@@ -834,7 +839,7 @@ lto_promote_cross_file_statics (void)
   cgraph_node_set set;
   cgraph_node_set_iterator csi;
   globalize_context_t context;
-
+
   memset (&context, 0, sizeof (context));
   context.all_vars = lto_bitmap_alloc ();
   context.all_static_vars = lto_bitmap_alloc ();
@@ -865,8 +870,76 @@ lto_promote_cross_file_statics (void)
   lto_bitmap_free (context.all_static_vars);
 }

+
+/* Given a file name FNAME, return a string with FNAME prefixed with '*'.  */
+
+static char *
+prefix_name_with_star (const char *fname)
+{
+  char *star_fname;
+  size_t len;
+
+  len = strlen (fname) + 1 + 1;
+  star_fname = XNEWVEC (char, len);
+  snprintf (star_fname, len, "*%s", fname);
+
+  return star_fname;
+}
+
+/* Return a file name associated with cgraph node set SET.  This may
+   be a new temporary file name if SET needs to be processed by
+   LTRANS, or the original file name if all the nodes in SET belong to
+   the same input file.  */
+
+static char *
+get_filename_for_set (cgraph_node_set set)
+{
+  char *fname = NULL;
+  static const size_t max_suffix_len = 100;
+
+  if (cgraph_node_set_needs_ltrans_p (set))
+    {
+      /* Create a new temporary file to store SET.  To facilitate
+	 debugging, use file names from SET as part of the new
+	 temporary file name.  */
+      cgraph_node_set_iterator si;
+      struct pointer_set_t *pset = pointer_set_create ();
+      char *suffix = NULL;
+      for (si = csi_start (set); !csi_end_p (si); csi_next (&si))
+	{
+	  struct cgraph_node *n = csi_node (si);
+	  const char *f = lbasename (n->local.lto_file_data->file_name);
+	  if (!pointer_set_insert (pset, n->local.lto_file_data))
+	    suffix = reconcat (suffix, "-", f, suffix, NULL);
+	  if (strlen (suffix) > max_suffix_len)
+	    break;
+	}
+      pointer_set_destroy (pset);
+      suffix = reconcat (suffix, suffix, ".lto.o", NULL);
+      fname = make_cwd_temp_file (suffix);
+
+      /* If suffix proved to be too long, try something smaller.  */
+      if (fname == NULL)
+	fname = make_cwd_temp_file (".lto.o");
+
+      gcc_assert (fname);
+    }
+  else
+    {
+      /* Since SET does not need to be processed by LTRANS, use
+	 the original file name and mark it with a '*' prefix so that
+	 lto_execute_ltrans knows not to send it to ltrans_driver.  */
+      cgraph_node_set_iterator si = csi_start (set);
+      struct cgraph_node *first = csi_node (si);
+      fname = prefix_name_with_star (first->local.lto_file_data->file_name);
+    }
+
+  return fname;
+}
+
 static lto_file *current_lto_file;

+
 /* Write all output files in WPA mode.  Returns a NULL-terminated array of
    output file names.  */

@@ -874,7 +947,7 @@ static char **
 lto_wpa_write_files (void)
 {
   char **output_files;
-  unsigned i, n_sets;
+  unsigned i, n_sets, last_out_file_ix, num_out_files;
   lto_file *file;
   cgraph_node_set set;
   bitmap decls;
@@ -882,7 +955,10 @@ lto_wpa_write_files (void)

   timevar_push (TV_WHOPR_WPA);

-  /* Include all inlined functions.  */
+  /* Include all inlined functions and determine what sets need to be
+     compiled by LTRANS.  After this loop, only those sets that
+     contain callgraph nodes from more than one file will need to be
+     compiled by LTRANS.  */
   for (i = 0; VEC_iterate (cgraph_node_set, lto_cgraph_node_sets, i, set); i++)
     {
       decls = lto_add_all_inlinees (set);
@@ -899,39 +975,48 @@ lto_wpa_write_files (void)

   timevar_push (TV_WHOPR_WPA_IO);

-  output_files = XNEWVEC (char *, VEC_length (cgraph_node_set,
-					      lto_cgraph_node_sets) + 1);
+  /* The number of output files depends on the number of input files
+     and how many callgraph node sets we create.  Reserve enough space
+     for the maximum of these two.  */
+  num_out_files = MAX (VEC_length (cgraph_node_set, lto_cgraph_node_sets),
+                       num_in_fnames);
+  output_files = XNEWVEC (char *, num_out_files + 1);

   n_sets = VEC_length (cgraph_node_set, lto_cgraph_node_sets);
   for (i = 0; i < n_sets; i++)
     {
-      char *temp_filename = make_cwd_temp_file (".lto.o");
+      char *temp_filename;

+      set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
+      temp_filename = get_filename_for_set (set);
       output_files[i] = temp_filename;

-      file = lto_elf_file_open (temp_filename, true);
-      if (!file)
-        fatal_error ("lto_elf_file_open() failed");
+      if (cgraph_node_set_needs_ltrans_p (set))
+	{
+	  /* Write all the nodes in SET to TEMP_FILENAME.  */
+	  file = lto_elf_file_open (temp_filename, true);
+	  if (!file)
+	    fatal_error ("lto_elf_file_open() failed");

-      lto_set_current_out_file (file);
-      lto_new_extern_inline_states ();
+	  lto_set_current_out_file (file);
+	  lto_new_extern_inline_states ();

-      decls = VEC_index (bitmap, inlined_decls, i);
-      lto_force_functions_extern_inline (decls);
+	  decls = VEC_index (bitmap, inlined_decls, i);
+	  lto_force_functions_extern_inline (decls);

-      /* Set AUX to 1 in the last LTRANS file.  */
-      set = VEC_index (cgraph_node_set, lto_cgraph_node_sets, i);
-      set->aux = (void*) ((intptr_t) (i == (n_sets - 1)));
-      ipa_write_summaries_of_cgraph_node_set (set);
-      lto_delete_extern_inline_states ();
-
-      lto_set_current_out_file (NULL);
-      lto_elf_file_close (file);
+	  ipa_write_summaries_of_cgraph_node_set (set);
+	  lto_delete_extern_inline_states ();
+
+	  lto_set_current_out_file (NULL);
+	  lto_elf_file_close (file);
+	}
     }

+  last_out_file_ix = n_sets;
+
   lto_stats.num_output_files += n_sets;

-  output_files[i] = NULL;
+  output_files[last_out_file_ix] = NULL;

   for (i = 0; VEC_iterate (bitmap, inlined_decls, i, decls); i++)
     lto_bitmap_free (decls);
@@ -967,31 +1052,6 @@ lto_execute_ltrans (char *const *files)

   timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);

-  /* Set the CC environment variable.  */
-  env_val = getenv ("COLLECT_GCC");
-  if (!env_val)
-    fatal_error ("environment variable COLLECT_GCC must be set");
-
-  obstack_init (&env_obstack);
-  obstack_grow (&env_obstack, "CC=", sizeof ("CC=") - 1);
-  obstack_grow (&env_obstack, env_val, strlen (env_val) + 1);
-  putenv (XOBFINISH (&env_obstack, char *));
-
-  /* Set the CFLAGS environment variable.  */
-  env_val = getenv ("COLLECT_GCC_OPTIONS");
-  if (!env_val)
-    fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
-
-  obstack_init (&env_obstack);
-  obstack_grow (&env_obstack, "CFLAGS=", sizeof ("CFLAGS=") - 1);
-  obstack_grow (&env_obstack, env_val, strlen (env_val));
-  obstack_grow (&env_obstack, extra_cflags, strlen (extra_cflags) + 1);
-  putenv (XOBFINISH (&env_obstack, char *));
-
-  pex = pex_init (0, "lto1", NULL);
-  if (pex == NULL)
-    fatal_error ("pex_init failed: %s", xstrerror (errno));
-
   /* Initalize the arguments for the LTRANS driver.  */
   for (i = 0; files[i]; ++i);
   argv = XNEWVEC (char *, i + 2);
@@ -1008,47 +1068,99 @@ lto_execute_ltrans (char *const *files)
   *argv_ptr++ = ltrans_driver;
   for (i = 0; files[i]; ++i)
     {
-      *argv_ptr++ = files[i];
+      size_t len;

-      /* Replace the .o suffix with a .ltrans.o suffix and write the resulting
-	 name to the LTRANS output list.  */
-      if (ltrans_output_list_stream)
+      /* If the file is prefixed with a '*', it means that we do not
+	 need to re-compile it with LTRANS because it has not been
+	 modified by WPA.  Skip it from the command line to
+	 ltrans-driver, but add it to ltrans_output_list_stream so it
+	 is linked after we are done.  */
+      if (files[i][0] == '*')
 	{
-	  size_t len = strlen (files[i]) - 2;
+	  size_t len = strlen (files[i]) - 1;
+	  if (ltrans_output_list_stream)
+	    if (fwrite (&files[i][1], 1, len, ltrans_output_list_stream) < len
+		|| fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
+	      error ("writing to LTRANS output list %s: %m",
+		     ltrans_output_list);
+	}
+      else
+	{
+	  /* Otherwise, add FILES[I] to ltrans-driver's command line
+	     and add the resulting file to LTRANS output list.  */
+	  *argv_ptr++ = files[i];

-	  if (fwrite (files[i], 1, len, ltrans_output_list_stream) < len
-	      || fwrite (".ltrans.o\n", 1, 10, ltrans_output_list_stream) < 10)
-	    error ("writing to LTRANS output list %s: %m", ltrans_output_list);
+	  /* Replace the .o suffix with a .ltrans.o suffix and write
+	     the resulting name to the LTRANS output list.  */
+	  if (ltrans_output_list_stream)
+	    {
+	      len = strlen (files[i]) - 2;
+
+	      if (fwrite (files[i], 1, len, ltrans_output_list_stream) < len
+		  || fwrite (".ltrans.o\n", 1, 10, ltrans_output_list_stream)
+		     < 10)
+		error ("writing to LTRANS output list %s: %m",
+		       ltrans_output_list);
+	    }
 	}
     }
+
   *argv_ptr++ = NULL;

   /* Close the LTRANS output list.  */
   if (ltrans_output_list_stream && fclose (ltrans_output_list_stream))
     error ("closing LTRANS output list %s: %m", ltrans_output_list);

-  /* Execute the LTRANS driver.  */
-  errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL, NULL,
-		    &err);
-  if (errmsg)
-    fatal_error ("%s: %s", errmsg, xstrerror (err));
+  /* If there are any files to compile, execute the LTRANS driver.  */
+  if (argv[1] != NULL)
+    {
+      /* Set the CC environment variable.  */
+      env_val = getenv ("COLLECT_GCC");
+      if (!env_val)
+	fatal_error ("environment variable COLLECT_GCC must be set");

-  if (!pex_get_status (pex, 1, &status))
-    fatal_error ("can't get program status: %s", xstrerror (errno));
+      obstack_init (&env_obstack);
+      obstack_grow (&env_obstack, "CC=", sizeof ("CC=") - 1);
+      obstack_grow (&env_obstack, env_val, strlen (env_val) + 1);
+      putenv (XOBFINISH (&env_obstack, char *));

-  pex_free (pex);
+      /* Set the CFLAGS environment variable.  */
+      env_val = getenv ("COLLECT_GCC_OPTIONS");
+      if (!env_val)
+	fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");

-  if (status)
-    {
-      if (WIFSIGNALED (status))
+      obstack_init (&env_obstack);
+      obstack_grow (&env_obstack, "CFLAGS=", sizeof ("CFLAGS=") - 1);
+      obstack_grow (&env_obstack, env_val, strlen (env_val));
+      obstack_grow (&env_obstack, extra_cflags, strlen (extra_cflags) + 1);
+      putenv (XOBFINISH (&env_obstack, char *));
+
+      pex = pex_init (0, "lto1", NULL);
+      if (pex == NULL)
+	fatal_error ("pex_init failed: %s", xstrerror (errno));
+
+      errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL, NULL,
+			&err);
+      if (errmsg)
+	fatal_error ("%s: %s", errmsg, xstrerror (err));
+
+      if (!pex_get_status (pex, 1, &status))
+	fatal_error ("can't get program status: %s", xstrerror (errno));
+
+      if (status)
 	{
-	  int sig = WTERMSIG (status);
-	  fatal_error ("%s terminated with signal %d [%s]%s",
-		       argv[0], sig, strsignal (sig),
-		       WCOREDUMP (status) ? ", core dumped" : "");
+	  if (WIFSIGNALED (status))
+	    {
+	      int sig = WTERMSIG (status);
+	      fatal_error ("%s terminated with signal %d [%s]%s",
+			   argv[0], sig, strsignal (sig),
+			   WCOREDUMP (status) ? ", core dumped" : "");
+	    }
+	  else
+	    fatal_error ("%s terminated with status %d", argv[0], status);
 	}
-      else
-	fatal_error ("%s terminated with status %d", argv[0], status);
+
+      pex_free (pex);
     }

   timevar_pop (TV_WHOPR_WPA_LTRANS_EXEC);
@@ -1677,9 +1789,12 @@ do_whole_program_analysis (void)

   for (i = 0; output_files[i]; ++i)
     {
-      lto_maybe_unlink (output_files[i]);
+      if (output_files[i][0] != '*')
+	lto_maybe_unlink (output_files[i]);
+
       free (output_files[i]);
     }
+
   XDELETEVEC (output_files);
 }

Index: Makefile.in
===================================================================
--- Makefile.in	(revision 146527)
+++ Makefile.in	(working copy)
@@ -881,8 +881,8 @@ DBGCNT_H = dbgcnt.h dbgcnt.def
 EBIMAP_H = ebitmap.h sbitmap.h
 LTO_TAGS_H = lto-tags.h tree.h sbitmap.h lto-header.h
 LTO_SECTION_H = lto-section.h lto-header.h
-LTO_SECTION_IN_H = lto-section-in.h lto-header.h
-LTO_SECTION_OUT_H = lto-section-in.h lto-section.h lto-header.h
+LTO_SECTION_IN_H = lto-section-in.h lto-header.h $(TARGET_H) $(CGRAPH_H)
+LTO_SECTION_OUT_H = lto-section-out.h lto-section.h lto-header.h
 LTO_TREE_IN_H = lto-tree-in.h $(LTO_SECTION_IN_H) $(PLUGIN_API_H)
 LTO_OPTS_H = lto-section-in.h lto-opts.h
 TREE_VECTORIZER_H = tree-vectorizer.h $(TREE_DATA_REF_H)
@@ -2094,8 +2094,7 @@ lto-function-in.o: lto-function-in.c $(C
    $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h tree-pass.h \
    tree-flow.h $(CGRAPH_H) $(FUNCTION_H) $(GGC_H) $(DIAGNOSTIC_H) except.h \
    debug.h $(TIMEVAR_H) $(LTO_TAGS_H) lto-tree-flags.def $(LTO_TREE_IN_H) \
-   lto-tree-tags.def $(LTO_SECTION_IN_H)  output.h dwarf2asm.h dwarf2out.h \
-   libfuncs.h lto-utils.h
+   lto-tree-tags.def $(LTO_SECTION_IN_H)  output.h libfuncs.h lto-utils.h
 lto-function-out.o : lto-function-out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
    $(TM_H) $(TOPLEV_H) $(TREE_H) $(EXPR_H) $(FLAGS_H) $(PARAMS_H) input.h \
    $(VARRAY_H) $(HASHTAB_H) langhooks.h $(BASIC_BLOCK_H) tree-iterator.h \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]