OSDN Git Service

* lto.h (lto_elf_file_open): Rename prototype from this ...
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto.c
index ab4c208..b6001d8 100644 (file)
@@ -1,5 +1,5 @@
 /* Top-level LTO routines.
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright 2009, 2010 Free Software Foundation, Inc.
    Contributed by CodeSourcery, Inc.
 
 This file is part of GCC.
@@ -46,7 +46,17 @@ along with GCC; see the file COPYING3.  If not see
 /* This needs to be included after config.h.  Otherwise, _GNU_SOURCE will not
    be defined in time to set __USE_GNU in the system headers, and strsignal
    will not be declared.  */
+#if HAVE_MMAP_FILE
 #include <sys/mman.h>
+#endif
+
+/* Handle opening elf files on hosts, such as Windows, that may use 
+   text file handling that will break binary access.  */
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
 
 DEF_VEC_P(bitmap);
 DEF_VEC_ALLOC_P(bitmap,heap);
@@ -247,12 +257,34 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
   lto_data_in_delete (data_in);
 }
 
+/* strtoll is not portable. */
+int64_t
+lto_parse_hex (const char *p) {
+  uint64_t ret = 0;
+  for (; *p != '\0'; ++p)
+    {
+      char c = *p;
+      unsigned char part;
+      ret <<= 4;
+      if (c >= '0' && c <= '9')
+        part = c - '0';
+      else if (c >= 'a' && c <= 'f')
+        part = c - 'a' + 10;
+      else if (c >= 'A' && c <= 'F')
+        part = c - 'A' + 10;
+      else
+        internal_error ("could not parse hex number");
+      ret |= part;
+    }
+  return ret;
+}
+
 /* Read resolution for file named FILE_NAME. The resolution is read from
    RESOLUTION. An array with the symbol resolution is returned. The array
    size is written to SIZE. */
 
 static VEC(ld_plugin_symbol_resolution_t,heap) *
-lto_resolution_read (FILE *resolution, const char *file_name)
+lto_resolution_read (FILE *resolution, lto_file *file)
 {
   /* We require that objects in the resolution file are in the same
      order as the lto1 command line. */
@@ -266,15 +298,27 @@ lto_resolution_read (FILE *resolution, const char *file_name)
   if (!resolution)
     return NULL;
 
-  name_len = strlen (file_name);
+  name_len = strlen (file->filename);
   obj_name = XNEWVEC (char, name_len + 1);
   fscanf (resolution, " ");   /* Read white space. */
 
   fread (obj_name, sizeof (char), name_len, resolution);
   obj_name[name_len] = '\0';
-  if (strcmp (obj_name, file_name) != 0)
+  if (strcmp (obj_name, file->filename) != 0)
     internal_error ("unexpected file name %s in linker resolution file. "
-                   "Expected %s", obj_name, file_name);
+                   "Expected %s", obj_name, file->filename);
+  if (file->offset != 0)
+    {
+      int t;
+      char offset_p[17];
+      int64_t offset;
+      t = fscanf (resolution, "@0x%16s", offset_p);
+      if (t != 1)
+        internal_error ("could not parse file offset");
+      offset = lto_parse_hex (offset_p);
+      if (offset != file->offset)
+        internal_error ("unexpected offset");
+    }
 
   free (obj_name);
 
@@ -282,6 +326,7 @@ lto_resolution_read (FILE *resolution, const char *file_name)
 
   for (i = 0; i < num_symbols; i++)
     {
+      int t;
       unsigned index;
       char r_str[27];
       enum ld_plugin_symbol_resolution r;
@@ -289,7 +334,9 @@ lto_resolution_read (FILE *resolution, const char *file_name)
       unsigned int lto_resolution_str_len =
        sizeof (lto_resolution_str) / sizeof (char *);
 
-      fscanf (resolution, "%u %26s", &index, r_str);
+      t = fscanf (resolution, "%u %26s %*[^\n]\n", &index, r_str);
+      if (t != 2)
+        internal_error ("Invalid line in the resolution file.");
       if (index > max_index)
        max_index = index;
 
@@ -301,12 +348,11 @@ lto_resolution_read (FILE *resolution, const char *file_name)
              break;
            }
        }
-      if (j >= lto_resolution_str_len)
-       internal_error ("tried to read past the end of the linker resolution "
-                       "file");
+      if (j == lto_resolution_str_len)
+       internal_error ("Invalid resolution in the resolution file.");
 
       VEC_safe_grow_cleared (ld_plugin_symbol_resolution_t, heap, ret,
-                            index + 1);
+                            max_index + 1);
       VEC_replace (ld_plugin_symbol_resolution_t, ret, index, r);
     }
 
@@ -328,12 +374,11 @@ lto_file_read (lto_file *file, FILE *resolution_file)
   size_t len;
   VEC(ld_plugin_symbol_resolution_t,heap) *resolutions;
   
-  resolutions = lto_resolution_read (resolution_file, file->filename);
+  resolutions = lto_resolution_read (resolution_file, file);
 
   file_data = XCNEW (struct lto_file_decl_data);
   file_data->file_name = file->filename;
-  file_data->fd = -1;
-  file_data->section_hash_table = lto_elf_build_section_table (file);
+  file_data->section_hash_table = lto_obj_build_section_table (file);
   file_data->renaming_hash_table = lto_create_renaming_table ();
 
   data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len);
@@ -361,17 +406,33 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
                       intptr_t offset, size_t len)
 {
   char *result;
+  static int fd = -1;
+  static char *fd_name;
 #if LTO_MMAP_IO
   intptr_t computed_len;
   intptr_t computed_offset;
   intptr_t diff;
 #endif
 
-  if (file_data->fd == -1)
-    file_data->fd = open (file_data->file_name, O_RDONLY);
-
-  if (file_data->fd == -1)
-    return NULL;
+  /* Keep a single-entry file-descriptor cache.  The last file we
+     touched will get closed at exit.
+     ???  Eventually we want to add a more sophisticated larger cache
+     or rather fix function body streaming to not stream them in
+     practically random order.  */
+  if (fd != -1
+      && strcmp (fd_name, file_data->file_name) != 0)
+    {
+      free (fd_name);
+      close (fd);
+      fd = -1;
+    }
+  if (fd == -1)
+    {
+      fd_name = xstrdup (file_data->file_name);
+      fd = open (file_data->file_name, O_RDONLY|O_BINARY);
+      if (fd == -1)
+       return NULL;
+    }
 
 #if LTO_MMAP_IO
   if (!page_mask)
@@ -385,26 +446,17 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
   computed_len = len + diff;
 
   result = (char *) mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE,
-                         file_data->fd, computed_offset);
+                         fd, computed_offset);
   if (result == MAP_FAILED)
-    {
-      close (file_data->fd);
-      return NULL;
-    }
+    return NULL;
 
   return result + diff;
 #else
   result = (char *) xmalloc (len);
-  if (result == NULL)
-    {
-      close (file_data->fd);
-      return NULL;
-    }
-  if (lseek (file_data->fd, offset, SEEK_SET) != offset
-      || read (file_data->fd, result, len) != (ssize_t) len)
+  if (lseek (fd, offset, SEEK_SET) != offset
+      || read (fd, result, len) != (ssize_t) len)
     {
       free (result);
-      close (file_data->fd);
       return NULL;
     }
 
@@ -447,7 +499,7 @@ get_section_data (struct lto_file_decl_data *file_data,
    starts at OFFSET and has LEN bytes.  */
 
 static void
-free_section_data (struct lto_file_decl_data *file_data,
+free_section_data (struct lto_file_decl_data *file_data ATTRIBUTE_UNUSED,
                   enum lto_section_type section_type ATTRIBUTE_UNUSED,
                   const char *name ATTRIBUTE_UNUSED,
                   const char *offset, size_t len ATTRIBUTE_UNUSED)
@@ -458,9 +510,6 @@ free_section_data (struct lto_file_decl_data *file_data,
   intptr_t diff;
 #endif
 
-  if (file_data->fd == -1)
-    return;
-
 #if LTO_MMAP_IO
   computed_offset = ((intptr_t) offset) & page_mask;
   diff = (intptr_t) offset - computed_offset;
@@ -505,6 +554,10 @@ lto_1_to_1_map (void)
 
   for (node = cgraph_nodes; node; node = node->next)
     {
+      /* We will get proper partition based on function they are inlined to or
+        cloned from.  */
+      if (node->global.inlined_to || node->clone_of)
+       continue;
       /* We only need to partition the nodes that we read from the
         gimple bytecode files.  */
       file_data = node->local.lto_file_data;
@@ -540,22 +593,19 @@ finish:
 
 static void
 lto_add_inline_clones (cgraph_node_set set, struct cgraph_node *node,
-                      bitmap original_decls, bitmap inlined_decls)
+                      bitmap original_decls)
 {
    struct cgraph_node *callee;
    struct cgraph_edge *edge;
 
    cgraph_node_set_add (set, node);
 
-   if (!bitmap_bit_p (original_decls, DECL_UID (node->decl)))
-     bitmap_set_bit (inlined_decls, DECL_UID (node->decl));
-
    /* Check to see if NODE has any inlined callee.  */
    for (edge = node->callees; edge != NULL; edge = edge->next_callee)
      {
        callee = edge->callee;
        if (callee->global.inlined_to != NULL)
-         lto_add_inline_clones (set, callee, original_decls, inlined_decls);
+         lto_add_inline_clones (set, callee, original_decls);
      }
 }
 
@@ -563,14 +613,13 @@ lto_add_inline_clones (cgraph_node_set set, struct cgraph_node *node,
    information in the callgraph.  Returns a bitmap of decls that have
    been inlined into SET indexed by UID.  */
 
-static bitmap
+static void
 lto_add_all_inlinees (cgraph_node_set set)
 {
   cgraph_node_set_iterator csi;
   struct cgraph_node *node;
   bitmap original_nodes = lto_bitmap_alloc ();
   bitmap original_decls = lto_bitmap_alloc ();
-  bitmap inlined_decls = lto_bitmap_alloc ();
   bool changed;
 
   /* We are going to iterate SET while adding to it, mark all original
@@ -610,19 +659,17 @@ lto_add_all_inlinees (cgraph_node_set set)
     }
   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);
-      if (bitmap_bit_p (original_nodes, node->uid))
-       lto_add_inline_clones (set, node, original_decls, inlined_decls);
-    }
+ /* 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);
+     if (bitmap_bit_p (original_nodes, node->uid))
+      lto_add_inline_clones (set, node, original_decls);
+   }
 
   lto_bitmap_free (original_nodes);
   lto_bitmap_free (original_decls);
-
-  return inlined_decls;
 }
 
 /* Owing to inlining, we may need to promote a file-scope variable
@@ -713,7 +760,8 @@ globalize_cross_file_statics (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
     }
   else if (TREE_CODE (t) == FUNCTION_DECL && !TREE_PUBLIC (t))
     {
-      if (!cgraph_node_in_set_p (cgraph_node (t), context->set))
+      if (!cgraph_node_in_set_p (cgraph_node (t), context->set)
+         || cgraph_node (t)->address_taken)
        {
          /* This file-scope static function is reachable from a set
             which does not contain the function DECL.  Make it global
@@ -951,8 +999,6 @@ lto_wpa_write_files (void)
   unsigned i, n_sets, last_out_file_ix, num_out_files;
   lto_file *file;
   cgraph_node_set set;
-  bitmap decls;
-  VEC(bitmap,heap) *inlined_decls = NULL;
 
   timevar_push (TV_WHOPR_WPA);
 
@@ -962,8 +1008,7 @@ lto_wpa_write_files (void)
      compiled by LTRANS.  */
   for (i = 0; VEC_iterate (cgraph_node_set, lto_cgraph_node_sets, i, set); i++)
     {
-      decls = lto_add_all_inlinees (set);
-      VEC_safe_push (bitmap, heap, inlined_decls, decls);
+      lto_add_all_inlinees (set);
       lto_stats.num_output_cgraph_nodes += VEC_length (cgraph_node_ptr,
                                                       set->nodes);
     }
@@ -995,21 +1040,16 @@ lto_wpa_write_files (void)
       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);
+         file = lto_obj_file_open (temp_filename, true);
          if (!file)
-           fatal_error ("lto_elf_file_open() failed");
+           fatal_error ("lto_obj_file_open() failed");
 
          lto_set_current_out_file (file);
-         lto_new_extern_inline_states ();
 
-         decls = VEC_index (bitmap, inlined_decls, i);
-         lto_force_functions_extern_inline (decls);
-
-         ipa_write_summaries_of_cgraph_node_set (set);
-         lto_delete_extern_inline_states ();
+         ipa_write_optimization_summaries (set);
 
          lto_set_current_out_file (NULL);
-         lto_elf_file_close (file);
+         lto_obj_file_close (file);
        }
     }
 
@@ -1019,15 +1059,13 @@ lto_wpa_write_files (void)
 
   output_files[last_out_file_ix] = NULL;
 
-  for (i = 0; VEC_iterate (bitmap, inlined_decls, i, decls); i++)
-    lto_bitmap_free (decls);
-  VEC_free (bitmap, heap, inlined_decls);
-
   timevar_pop (TV_WHOPR_WPA_IO);
 
   return output_files;
 }
 
+/* Template of LTRANS dumpbase suffix.  */
+#define DUMPBASE_SUFFIX        ".ltrans18446744073709551615"
 
 /* Perform local transformations (LTRANS) on the files in the NULL-terminated
    FILES array.  These should have been written previously by
@@ -1047,6 +1085,8 @@ lto_execute_ltrans (char *const *files)
   int err;
   int status;
   FILE *ltrans_output_list_stream = NULL;
+  bool seen_dumpbase = false;
+  char *dumpbase_suffix = NULL;
 
   timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
 
@@ -1085,13 +1125,26 @@ lto_execute_ltrans (char *const *files)
          ++j;
        obstack_init (&env_obstack);
        obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
-       obstack_1grow (&env_obstack, 0);
+       if (seen_dumpbase)
+         obstack_grow (&env_obstack, DUMPBASE_SUFFIX,
+                       sizeof (DUMPBASE_SUFFIX));
+       else
+         obstack_1grow (&env_obstack, 0);
        option = XOBFINISH (&env_obstack, char *);
+       if (seen_dumpbase)
+         {
+           dumpbase_suffix = option + 7 + j - i;
+           seen_dumpbase = false;
+         }
 
        /* LTRANS does not need -fwpa nor -fltrans-*.  */
        if (strncmp (option, "-fwpa", 5) != 0
            && strncmp (option, "-fltrans-", 9) != 0)
-         *argv_ptr++ = option;
+         {
+           if (strncmp (option, "-dumpbase", 9) == 0)
+             seen_dumpbase = true;
+           *argv_ptr++ = option;
+         }
       }
   *argv_ptr++ = "-fltrans";
 
@@ -1149,6 +1202,11 @@ lto_execute_ltrans (char *const *files)
          argv_ptr[2] = files[i];
          argv_ptr[3] = NULL;
 
+         /* Append a sequence number to -dumpbase for LTRANS.  */
+         if (dumpbase_suffix)
+           snprintf (dumpbase_suffix, sizeof (DUMPBASE_SUFFIX) - 7,
+                     "%lu", (unsigned long) i);
+
          /* Execute the driver.  */
          pex = pex_init (0, "lto1", NULL);
          if (pex == NULL)
@@ -1191,7 +1249,6 @@ lto_execute_ltrans (char *const *files)
 
 
 typedef struct {
-  struct pointer_set_t *free_list;
   struct pointer_set_t *seen;
 } lto_fixup_data_t;
 
@@ -1336,7 +1393,7 @@ static void
 lto_fixup_field_decl (tree t, void *data)
 {
   lto_fixup_decl_common (t, data);
-  gcc_assert (no_fixup_p (DECL_FIELD_OFFSET (t)));
+  LTO_FIXUP_SUBTREE (DECL_FIELD_OFFSET (t));
   LTO_FIXUP_SUBTREE (DECL_BIT_FIELD_TYPE (t));
   LTO_FIXUP_SUBTREE (DECL_QUALIFIER (t));
   gcc_assert (no_fixup_p (DECL_FIELD_BIT_OFFSET (t)));
@@ -1504,30 +1561,6 @@ lto_fixup_tree (tree *tp, int *walk_subtrees, void *data)
 
       if (t != prevailing)
        {
-         if (TREE_CODE (t) == FUNCTION_DECL
-             && TREE_NOTHROW (prevailing) != TREE_NOTHROW (t))
-           {
-             /* If the prevailing definition does not throw but the
-                declaration (T) was considered throwing, then we
-                simply add PREVAILING to the list of throwing
-                functions.  However, if the opposite is true, then
-                the call to PREVAILING was generated assuming that
-                the function didn't throw, which means that CFG
-                cleanup may have removed surrounding try/catch
-                regions.
-
-                Note that we currently accept these cases even when
-                they occur within a single file.  It's certainly a
-                user error, but we silently allow the compiler to
-                remove surrounding try/catch regions.  Perhaps we
-                could emit a warning here, instead of silently
-                accepting the conflicting declaration.  */
-             if (TREE_NOTHROW (prevailing))
-               lto_mark_nothrow_fndecl (prevailing);
-           }
-
-         pointer_set_insert (fixup_data->free_list, t);
-
           /* Also replace t with prevailing defintion.  We don't want to
              insert the other defintion in the seen set as we want to
              replace all instances of it.  */
@@ -1636,20 +1669,6 @@ lto_fixup_state_aux (void **slot, void *aux)
   return 1;
 }
 
-/* A callback to pointer_set_traverse. Frees the tree pointed by p. Removes
-   from it from the UID -> DECL mapping. */
-
-static bool
-free_decl (const void *p, void *data ATTRIBUTE_UNUSED)
-{
-  const_tree ct = (const_tree) p;
-  tree t = CONST_CAST_TREE (ct);
-
-  lto_symtab_clear_resolution (t);
-
-  return true;
-}
-
 /* Fix the decls from all FILES. Replaces each decl with the corresponding
    prevailing one.  */
 
@@ -1658,11 +1677,9 @@ lto_fixup_decls (struct lto_file_decl_data **files)
 {
   unsigned int i;
   tree decl;
-  struct pointer_set_t *free_list = pointer_set_create ();
   struct pointer_set_t *seen = pointer_set_create ();
   lto_fixup_data_t data;
 
-  data.free_list = free_list;
   data.seen = seen;
   for (i = 0; files[i]; i++)
     {
@@ -1681,8 +1698,6 @@ lto_fixup_decls (struct lto_file_decl_data **files)
        VEC_replace (tree, lto_global_var_decls, i, decl);
     }
 
-  pointer_set_traverse (free_list, free_decl, NULL);
-  pointer_set_destroy (free_list);
   pointer_set_destroy (seen);
 }
 
@@ -1725,21 +1740,18 @@ lto_read_all_file_options (void)
   for (i = 0; i < num_in_fnames; i++)
     {
       struct lto_file_decl_data *file_data;
-      lto_file *file = lto_elf_file_open (in_fnames[i], false);
+      lto_file *file = lto_obj_file_open (in_fnames[i], false);
       if (!file)
        break;
 
       file_data = XCNEW (struct lto_file_decl_data);
       file_data->file_name = file->filename;
-      file_data->fd = -1;
-      file_data->section_hash_table = lto_elf_build_section_table (file);
+      file_data->section_hash_table = lto_obj_build_section_table (file);
 
       lto_read_file_options (file_data);
 
-      lto_elf_file_close (file);
+      lto_obj_file_close (file);
       htab_delete (file_data->section_hash_table);
-      if (file_data->fd != -1)
-       close (file_data->fd);
       free (file_data);
     }
 
@@ -1777,7 +1789,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
       unsigned num_objects;
 
       resolution = fopen (resolution_file_name, "r");
-      gcc_assert (resolution != NULL);
+      if (resolution == NULL)
+       fatal_error ("could not open symbol resolution file: %s",
+                    xstrerror (errno));
+
       t = fscanf (resolution, "%u", &num_objects);
       gcc_assert (t == 1);
 
@@ -1785,12 +1800,20 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
       gcc_assert (num_objects == nfiles);
     }
 
+  if (!quiet_flag)
+    fprintf (stderr, "Reading object files:");
+
   /* Read all of the object files specified on the command line.  */
   for (i = 0, last_file_ix = 0; i < nfiles; ++i)
     {
       struct lto_file_decl_data *file_data = NULL;
+      if (!quiet_flag)
+       {
+         fprintf (stderr, " %s", fnames[i]);
+         fflush (stderr);
+       }
 
-      current_lto_file = lto_elf_file_open (fnames[i], false);
+      current_lto_file = lto_obj_file_open (fnames[i], false);
       if (!current_lto_file)
        break;
 
@@ -1800,7 +1823,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
 
       all_file_decl_data[last_file_ix++] = file_data;
 
-      lto_elf_file_close (current_lto_file);
+      lto_obj_file_close (current_lto_file);
       current_lto_file = NULL;
     }
 
@@ -1815,33 +1838,49 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
   /* Each pass will set the appropriate timer.  */
   timevar_pop (TV_IPA_LTO_DECL_IO);
 
+  if (!quiet_flag)
+    fprintf (stderr, "\nReading the callgraph\n");
+
   /* Read the callgraph.  */
   input_cgraph ();
 
-  /* Read the IPA summary data.  */
-  ipa_read_summaries ();
+  if (!quiet_flag)
+    fprintf (stderr, "Merging declarations\n");
 
   /* Merge global decls.  */
   lto_symtab_merge_decls ();
 
-  /* Mark cgraph nodes needed in the merged cgraph
-     This normally happens in whole-program pass, but for
-     ltrans the pass was already run at WPA phase.
-     
-     FIXME:  This is not valid way to do so; nodes can be needed
-     for non-obvious reasons.  We should stream the flags from WPA
-     phase. */
+  /* Fixup all decls and types and free the type hash tables.  */
+  lto_fixup_decls (all_file_decl_data);
+  free_gimple_type_tables ();
+
+  if (!quiet_flag)
+    fprintf (stderr, "Reading summaries\n");
+
+  /* Read the IPA summary data.  */
+  if (flag_ltrans)
+    ipa_read_optimization_summaries ();
+  else
+    ipa_read_summaries ();
+
+  /* Finally merge the cgraph according to the decl merging decisions.  */
+  lto_symtab_merge_cgraph_nodes ();
+
   if (flag_ltrans)
     for (node = cgraph_nodes; node; node = node->next)
-      if (!node->global.inlined_to
-         && cgraph_decide_is_function_needed (node, node->decl))
-        cgraph_mark_needed_node (node);
+      {
+       /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization
+          summaries computed and needs to apply changes.  At the moment WHOPR only
+          supports inlining, so we can push it here by hand.  In future we need to stream
+          this field into ltrans compilation.  */
+       if (node->analyzed)
+         VEC_safe_push (ipa_opt_pass, heap,
+                        node->ipa_transforms_to_apply,
+                        (ipa_opt_pass)&pass_ipa_inline);
+      }
 
   timevar_push (TV_IPA_LTO_DECL_IO);
 
-  /* Fixup all decls and types.  */
-  lto_fixup_decls (all_file_decl_data);
-
   /* FIXME lto. This loop needs to be changed to use the pass manager to
      call the ipa passes directly.  */
   if (!errorcount)
@@ -1868,6 +1907,11 @@ materialize_cgraph (void)
   unsigned i;
   timevar_id_t lto_timer;
 
+  if (!quiet_flag)
+    fprintf (stderr,
+            flag_wpa ? "Materializing decls:" : "Reading function bodies:");
+
+
   /* Now that we have input the cgraph, we need to clear all of the aux
      nodes and read the functions if we are not running in WPA mode.  */
   timevar_push (TV_IPA_LTO_GIMPLE_IO);
@@ -1886,6 +1930,7 @@ materialize_cgraph (void)
       if (node->local.lto_file_data
           && !DECL_IS_BUILTIN (node->decl))
        {
+         announce_function (node->decl);
          lto_materialize_function (node);
          lto_stats.num_input_cgraph_nodes++;
        }
@@ -1907,8 +1952,8 @@ materialize_cgraph (void)
   for (i = 0; VEC_iterate (tree, lto_global_var_decls, i, decl); i++)
     rest_of_decl_compilation (decl, 1, 0);
 
-  /* Fix up any calls to DECLs that have become not exception throwing.  */
-  lto_fixup_nothrow_decls ();
+  if (!quiet_flag)
+    fprintf (stderr, "\n");
 
   timevar_pop (lto_timer);
 }
@@ -1922,9 +1967,6 @@ do_whole_program_analysis (void)
 {
   char **output_files;
   size_t i;
-  struct cgraph_node *node; 
-
-  lto_1_to_1_map ();
 
   /* Note that since we are in WPA mode, materialize_cgraph will not
      actually read in all the function bodies.  It only materializes
@@ -1934,20 +1976,12 @@ do_whole_program_analysis (void)
   /* Reading in the cgraph uses different timers, start timing WPA now.  */
   timevar_push (TV_WHOPR_WPA);
 
-  /* FIXME lto. Hack. We should use the IPA passes.  There are a
-     number of issues with this now. 1. There is no convenient way to
-     do this. 2. Some passes may depend on properties that requires
-     the function bodies to compute.  */
   cgraph_function_flags_ready = true;
   bitmap_obstack_initialize (NULL);
   ipa_register_cgraph_hooks ();
+  cgraph_state = CGRAPH_STATE_IPA_SSA;
 
-  /* Reset inlining information before running IPA inliner.  */
-  for (node = cgraph_nodes; node; node = node->next)
-    reset_inline_failed (node);
-
-  /* FIXME lto.  We should not call this function directly. */
-  pass_ipa_inline.pass.execute ();
+  execute_ipa_pass_list (all_regular_ipa_passes);
 
   verify_cgraph ();
   bitmap_obstack_release (NULL);
@@ -1955,7 +1989,16 @@ do_whole_program_analysis (void)
   /* We are about to launch the final LTRANS phase, stop the WPA timer.  */
   timevar_pop (TV_WHOPR_WPA);
 
+  lto_1_to_1_map ();
+
+  if (!quiet_flag)
+    {
+      fprintf (stderr, "\nStreaming out");
+      fflush (stderr);
+    }
   output_files = lto_wpa_write_files ();
+  if (!quiet_flag)
+    fprintf (stderr, "\n");
 
   /* Show the LTO report before launching LTRANS.  */
   if (flag_lto_report)