pa.md (integer_indexed_store splitters): Use mem_shadd_operand.
[gcc.git] / gcc / lto-streamer-in.c
index b9893a17b1da32c4ae05db03f240a164e4b98a59..4268bdeb8231bb715785a84a80d21b9be5f257b1 100644 (file)
@@ -1,6 +1,6 @@
 /* Read the GIMPLE representation from a file stream.
 
-   Copyright 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2009-2015 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
    Re-implemented by Diego Novillo <dnovillo@google.com>
 
@@ -25,32 +25,82 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "toplev.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "wide-int.h"
+#include "inchash.h"
 #include "tree.h"
-#include "expr.h"
+#include "fold-const.h"
+#include "stringpool.h"
+#include "hashtab.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "rtl.h"
 #include "flags.h"
+#include "statistics.h"
+#include "real.h"
+#include "fixed-value.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
+#include "expr.h"
 #include "params.h"
-#include "input.h"
-#include "hashtab.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
-#include "tree-flow.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimple-ssa.h"
+#include "tree-cfg.h"
+#include "tree-ssanames.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
+#include "tree-ssa.h"
 #include "tree-pass.h"
-#include "cgraph.h"
-#include "function.h"
-#include "ggc.h"
 #include "diagnostic.h"
 #include "except.h"
 #include "debug.h"
-#include "vec.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
 #include "ipa-utils.h"
 #include "data-streamer.h"
 #include "gimple-streamer.h"
 #include "lto-streamer.h"
 #include "tree-streamer.h"
-#include "tree-pass.h"
 #include "streamer-hooks.h"
+#include "cfgloop.h"
+
+
+struct freeing_string_slot_hasher : string_slot_hasher
+{
+  static inline void remove (value_type *);
+};
+
+inline void
+freeing_string_slot_hasher::remove (value_type *v)
+{
+  free (v);
+}
 
 /* The table to hold the file names.  */
-static htab_t file_name_hash_table;
+static hash_table<freeing_string_slot_hasher> *file_name_hash_table;
 
 
 /* Check that tag ACTUAL has one of the given values.  NUM_TAGS is the
@@ -94,14 +144,14 @@ lto_input_data_block (struct lto_input_block *ib, void *addr, size_t length)
 static const char *
 canon_file_name (const char *string)
 {
-  void **slot;
+  string_slot **slot;
   struct string_slot s_slot;
   size_t len = strlen (string);
 
   s_slot.s = string;
   s_slot.len = len;
 
-  slot = htab_find_slot (file_name_hash_table, &s_slot, INSERT);
+  slot = file_name_hash_table->find_slot (&s_slot, INSERT);
   if (*slot == NULL)
     {
       char *saved_string;
@@ -117,87 +167,180 @@ canon_file_name (const char *string)
     }
   else
     {
-      struct string_slot *old_slot = (struct string_slot *) *slot;
+      struct string_slot *old_slot = *slot;
       return old_slot->s;
     }
 }
 
+/* Pointer to currently alive instance of lto_location_cache.  */
 
-/* Clear the line info stored in DATA_IN.  */
+lto_location_cache *lto_location_cache::current_cache;
 
-static void
-clear_line_info (struct data_in *data_in)
+/* Sort locations in source order. Start with file from last application.  */
+
+int
+lto_location_cache::cmp_loc (const void *pa, const void *pb)
 {
-  if (data_in->current_file)
-    linemap_add (line_table, LC_LEAVE, false, NULL, 0);
-  data_in->current_file = NULL;
-  data_in->current_line = 0;
-  data_in->current_col = 0;
+  const cached_location *a = ((const cached_location *)pa);
+  const cached_location *b = ((const cached_location *)pb);
+  const char *current_file = current_cache->current_file;
+  int current_line = current_cache->current_line;
+
+  if (a->file == current_file && b->file != current_file)
+    return -1;
+  if (a->file != current_file && b->file == current_file)
+    return 1;
+  if (a->file == current_file && b->file == current_file)
+    {
+      if (a->line == current_line && b->line != current_line)
+       return -1;
+      if (a->line != current_line && b->line == current_line)
+       return 1;
+    }
+  if (a->file != b->file)
+    return strcmp (a->file, b->file);
+  if (a->line != b->line)
+    return a->line - b->line;
+  return a->col - b->col;
 }
 
+/* Apply all changes in location cache.  Add locations into linemap and patch
+   trees.  */
 
-/* Read a location bitpack from input block IB.  */
+bool
+lto_location_cache::apply_location_cache ()
+{
+  static const char *prev_file;
+  if (!loc_cache.length ())
+    return false;
+  if (loc_cache.length () > 1)
+    loc_cache.qsort (cmp_loc);
 
-static location_t
-lto_input_location_bitpack (struct data_in *data_in, struct bitpack_d *bp)
+  for (unsigned int i = 0; i < loc_cache.length (); i++)
+    {
+      struct cached_location loc = loc_cache[i];
+
+      if (current_file != loc.file)
+       linemap_add (line_table, prev_file ? LC_RENAME : LC_ENTER,
+                    false, loc.file, loc.line);
+      else if (current_line != loc.line)
+       {
+         int max = loc.col;
+
+         for (unsigned int j = i + 1; j < loc_cache.length (); j++)
+           if (loc.file != loc_cache[j].file
+               || loc.line != loc_cache[j].line)
+             break;
+           else if (max < loc_cache[j].col)
+             max = loc_cache[j].col;
+         linemap_line_start (line_table, loc.line, max + 1);
+       }
+      gcc_assert (*loc.loc == BUILTINS_LOCATION + 1);
+      if (current_file == loc.file && current_line == loc.line
+         && current_col == loc.col)
+       *loc.loc = current_loc;
+      else
+        current_loc = *loc.loc = linemap_position_for_column (line_table,
+                                                             loc.col);
+      current_line = loc.line;
+      prev_file = current_file = loc.file;
+      current_col = loc.col;
+    }
+  loc_cache.truncate (0);
+  accepted_length = 0;
+  return true;
+}
+
+/* Tree merging did not suceed; mark all changes in the cache as accepted.  */
+
+void
+lto_location_cache::accept_location_cache ()
+{
+  gcc_assert (current_cache == this);
+  accepted_length = loc_cache.length ();
+}
+
+/* Tree merging did suceed; throw away recent changes.  */
+
+void
+lto_location_cache::revert_location_cache ()
 {
+  loc_cache.truncate (accepted_length);
+}
+
+/* Read a location bitpack from input block IB and either update *LOC directly
+   or add it to the location cache.
+   It is neccesary to call apply_location_cache to get *LOC updated.  */
+
+void
+lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp,
+                                   struct data_in *data_in)
+{
+  static const char *stream_file;
+  static int stream_line;
+  static int stream_col;
   bool file_change, line_change, column_change;
-  unsigned len;
-  bool prev_file = data_in->current_file != NULL;
+
+  gcc_assert (current_cache == this);
 
   if (bp_unpack_value (bp, 1))
-    return UNKNOWN_LOCATION;
+    {
+      *loc = UNKNOWN_LOCATION;
+      return;
+    }
+  *loc = BUILTINS_LOCATION + 1;
 
   file_change = bp_unpack_value (bp, 1);
+  line_change = bp_unpack_value (bp, 1);
+  column_change = bp_unpack_value (bp, 1);
+
   if (file_change)
-    data_in->current_file = canon_file_name
-                             (string_for_index (data_in,
-                                                bp_unpack_var_len_unsigned (bp),
-                                                &len));
+    stream_file = canon_file_name (bp_unpack_string (data_in, bp));
 
-  line_change = bp_unpack_value (bp, 1);
   if (line_change)
-    data_in->current_line = bp_unpack_var_len_unsigned (bp);
+    stream_line = bp_unpack_var_len_unsigned (bp);
 
-  column_change = bp_unpack_value (bp, 1);
   if (column_change)
-    data_in->current_col = bp_unpack_var_len_unsigned (bp);
+    stream_col = bp_unpack_var_len_unsigned (bp);
 
-  if (file_change)
+  /* This optimization saves location cache operations druing gimple
+     streaming.  */
+     
+  if (current_file == stream_file && current_line == stream_line
+      && current_col == stream_col)
     {
-      if (prev_file)
-       linemap_add (line_table, LC_LEAVE, false, NULL, 0);
-
-      linemap_add (line_table, LC_ENTER, false, data_in->current_file,
-                  data_in->current_line);
+      *loc = current_loc;
+      return;
     }
-  else if (line_change)
-    linemap_line_start (line_table, data_in->current_line, data_in->current_col);
 
-  return linemap_position_for_column (line_table, data_in->current_col);
+  struct cached_location entry = {stream_file, loc, stream_line, stream_col};
+  loc_cache.safe_push (entry);
 }
 
+/* Read a location bitpack from input block IB and either update *LOC directly
+   or add it to the location cache.
+   It is neccesary to call apply_location_cache to get *LOC updated.  */
 
-/* Read a location from input block IB.
-   If the input_location streamer hook exists, call it.
-   Otherwise, proceed with reading the location from the
-   expanded location bitpack.  */
+void
+lto_input_location (location_t *loc, struct bitpack_d *bp,
+                   struct data_in *data_in)
+{
+  data_in->location_cache.input_location (loc, bp, data_in);
+}
+
+/* Read location and return it instead of going through location caching.
+   This should be used only when the resulting location is not going to be
+   discarded.  */
 
 location_t
-lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
+stream_input_location_now (struct bitpack_d *bp, struct data_in *data_in)
 {
-  if (streamer_hooks.input_location)
-    return streamer_hooks.input_location (ib, data_in);
-  else
-    {
-      struct bitpack_d bp;
-
-      bp = streamer_read_bitpack (ib);
-      return lto_input_location_bitpack (data_in, &bp);
-    }
+  location_t loc;
+  stream_input_location (&loc, bp, data_in);
+  data_in->location_cache.apply_location_cache ();
+  return loc;
 }
 
-
 /* Read a reference to a tree node from DATA_IN using input block IB.
    TAG is the expected node that should be found in IB, if TAG belongs
    to one of the indexable trees, expect to read a reference index to
@@ -212,7 +355,7 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
   unsigned HOST_WIDE_INT ix_u;
   tree result = NULL_TREE;
 
-  lto_tag_check_range (tag, LTO_field_decl_ref, LTO_global_decl_ref);
+  lto_tag_check_range (tag, LTO_field_decl_ref, LTO_namelist_decl_ref);
 
   switch (tag)
     {
@@ -223,7 +366,7 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
 
     case LTO_ssa_name_ref:
       ix_u = streamer_read_uhwi (ib);
-      result = VEC_index (tree, SSANAMES (fn), ix_u);
+      result = (*SSANAMES (fn))[ix_u];
       break;
 
     case LTO_field_decl_ref:
@@ -252,6 +395,7 @@ lto_input_tree_ref (struct lto_input_block *ib, struct data_in *data_in,
     case LTO_imported_decl_ref:
     case LTO_label_decl_ref:
     case LTO_translation_unit_decl_ref:
+    case LTO_namelist_decl_ref:
       ix_u = streamer_read_uhwi (ib);
       result = lto_file_decl_data_get_var_decl (data_in->file_data, ix_u);
       break;
@@ -286,7 +430,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
       lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
 
       /* Read the catch node.  */
-      n = ggc_alloc_cleared_eh_catch_d ();
+      n = ggc_cleared_alloc<eh_catch_d> ();
       n->type_list = stream_read_tree (ib, data_in);
       n->filter_list = stream_read_tree (ib, data_in);
       n->label = stream_read_tree (ib, data_in);
@@ -326,7 +470,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
   if (tag == LTO_null)
     return NULL;
 
-  r = ggc_alloc_cleared_eh_region_d ();
+  r = ggc_cleared_alloc<eh_region_d> ();
   r->index = streamer_read_hwi (ib);
 
   gcc_assert (r->index == ix);
@@ -368,9 +512,13 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
        break;
 
       case LTO_ert_must_not_throw:
-       r->type = ERT_MUST_NOT_THROW;
-       r->u.must_not_throw.failure_decl = stream_read_tree (ib, data_in);
-       r->u.must_not_throw.failure_loc = lto_input_location (ib, data_in);
+       {
+         r->type = ERT_MUST_NOT_THROW;
+         r->u.must_not_throw.failure_decl = stream_read_tree (ib, data_in);
+         bitpack_d bp = streamer_read_bitpack (ib);
+         r->u.must_not_throw.failure_loc
+          = stream_input_location_now (&bp, data_in);
+       }
        break;
 
       default:
@@ -399,7 +547,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
 
   lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
 
-  lp = ggc_alloc_cleared_eh_landing_pad_d ();
+  lp = ggc_cleared_alloc<eh_landing_pad_d> ();
   lp->index = streamer_read_hwi (ib);
   gcc_assert (lp->index == ix);
   lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib);
@@ -419,24 +567,22 @@ static void
 fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region)
 {
   unsigned i;
-  VEC(eh_region,gc) *eh_array = fn->eh->region_array;
-  VEC(eh_landing_pad,gc) *lp_array = fn->eh->lp_array;
+  vec<eh_region, va_gc> *eh_array = fn->eh->region_array;
+  vec<eh_landing_pad, va_gc> *lp_array = fn->eh->lp_array;
   eh_region r;
   eh_landing_pad lp;
 
   gcc_assert (eh_array && lp_array);
 
   gcc_assert (root_region >= 0);
-  fn->eh->region_tree = VEC_index (eh_region, eh_array, root_region);
+  fn->eh->region_tree = (*eh_array)[root_region];
 
-#define FIXUP_EH_REGION(r) (r) = VEC_index (eh_region, eh_array, \
-                                           (HOST_WIDE_INT) (intptr_t) (r))
-#define FIXUP_EH_LP(p) (p) = VEC_index (eh_landing_pad, lp_array, \
-                                       (HOST_WIDE_INT) (intptr_t) (p))
+#define FIXUP_EH_REGION(r) (r) = (*eh_array)[(HOST_WIDE_INT) (intptr_t) (r)]
+#define FIXUP_EH_LP(p) (p) = (*lp_array)[(HOST_WIDE_INT) (intptr_t) (p)]
 
   /* Convert all the index numbers stored in pointer fields into
      pointers to the corresponding slots in the EH region array.  */
-  FOR_EACH_VEC_ELT (eh_region, eh_array, i, r)
+  FOR_EACH_VEC_ELT (*eh_array, i, r)
     {
       /* The array may contain NULL regions.  */
       if (r == NULL)
@@ -451,7 +597,7 @@ fixup_eh_region_pointers (struct function *fn, HOST_WIDE_INT root_region)
 
   /* Convert all the index numbers stored in pointer fields into
      pointers to the corresponding slots in the EH landing pad array.  */
-  FOR_EACH_VEC_ELT (eh_landing_pad, lp_array, i, lp)
+  FOR_EACH_VEC_ELT (*lp_array, i, lp)
     {
       /* The array may contain NULL landing pads.  */
       if (lp == NULL)
@@ -520,11 +666,11 @@ input_eh_regions (struct lto_input_block *ib, struct data_in *data_in,
   gcc_assert (len == (int) len);
   if (len > 0)
     {
-      VEC_safe_grow (eh_region, gc, fn->eh->region_array, len);
+      vec_safe_grow_cleared (fn->eh->region_array, len);
       for (i = 0; i < len; i++)
        {
          eh_region r = input_eh_region (ib, data_in, i);
-         VEC_replace (eh_region, fn->eh->region_array, i, r);
+         (*fn->eh->region_array)[i] = r;
        }
     }
 
@@ -533,11 +679,11 @@ input_eh_regions (struct lto_input_block *ib, struct data_in *data_in,
   gcc_assert (len == (int) len);
   if (len > 0)
     {
-      VEC_safe_grow (eh_landing_pad, gc, fn->eh->lp_array, len);
+      vec_safe_grow_cleared (fn->eh->lp_array, len);
       for (i = 0; i < len; i++)
        {
          eh_landing_pad lp = input_eh_lp (ib, data_in, i);
-         VEC_replace (eh_landing_pad, fn->eh->lp_array, i, lp);
+         (*fn->eh->lp_array)[i] = lp;
        }
     }
 
@@ -546,11 +692,11 @@ input_eh_regions (struct lto_input_block *ib, struct data_in *data_in,
   gcc_assert (len == (int) len);
   if (len > 0)
     {
-      VEC_safe_grow (tree, gc, fn->eh->ttype_data, len);
+      vec_safe_grow_cleared (fn->eh->ttype_data, len);
       for (i = 0; i < len; i++)
        {
          tree ttype = stream_read_tree (ib, data_in);
-         VEC_replace (tree, fn->eh->ttype_data, i, ttype);
+         (*fn->eh->ttype_data)[i] = ttype;
        }
     }
 
@@ -561,20 +707,20 @@ input_eh_regions (struct lto_input_block *ib, struct data_in *data_in,
     {
       if (targetm.arm_eabi_unwinder)
        {
-         VEC_safe_grow (tree, gc, fn->eh->ehspec_data.arm_eabi, len);
+         vec_safe_grow_cleared (fn->eh->ehspec_data.arm_eabi, len);
          for (i = 0; i < len; i++)
            {
              tree t = stream_read_tree (ib, data_in);
-             VEC_replace (tree, fn->eh->ehspec_data.arm_eabi, i, t);
+             (*fn->eh->ehspec_data.arm_eabi)[i] = t;
            }
        }
       else
        {
-         VEC_safe_grow (uchar, gc, fn->eh->ehspec_data.other, len);
+         vec_safe_grow_cleared (fn->eh->ehspec_data.other, len);
          for (i = 0; i < len; i++)
            {
              uchar c = streamer_read_uchar (ib);
-             VEC_replace (uchar, fn->eh->ehspec_data.other, i, c);
+             (*fn->eh->ehspec_data.other)[i] = c;
            }
        }
     }
@@ -595,16 +741,32 @@ make_new_block (struct function *fn, unsigned int index)
 {
   basic_block bb = alloc_block ();
   bb->index = index;
-  SET_BASIC_BLOCK_FOR_FUNCTION (fn, index, bb);
-  n_basic_blocks_for_function (fn)++;
+  SET_BASIC_BLOCK_FOR_FN (fn, index, bb);
+  n_basic_blocks_for_fn (fn)++;
   return bb;
 }
 
 
+/* Read a wide-int.  */
+
+static widest_int
+streamer_read_wi (struct lto_input_block *ib)
+{
+  HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
+  int i;
+  int prec ATTRIBUTE_UNUSED = streamer_read_uhwi (ib);
+  int len = streamer_read_uhwi (ib);
+  for (i = 0; i < len; i++)
+    a[i] = streamer_read_hwi (ib);
+  return widest_int::from_array (a, len);
+}
+
+
 /* Read the CFG for function FN from input block IB.  */
 
 static void
-input_cfg (struct lto_input_block *ib, struct function *fn,
+input_cfg (struct lto_input_block *ib, struct data_in *data_in,
+          struct function *fn,
           int count_materialization_scale)
 {
   unsigned int bb_count;
@@ -615,24 +777,22 @@ input_cfg (struct lto_input_block *ib, struct function *fn,
   init_empty_tree_cfg_for_function (fn);
   init_ssa_operands (fn);
 
-  profile_status_for_function (fn) = streamer_read_enum (ib, profile_status_d,
-                                                        PROFILE_LAST);
+  profile_status_for_fn (fn) = streamer_read_enum (ib, profile_status_d,
+                                                  PROFILE_LAST);
 
   bb_count = streamer_read_uhwi (ib);
 
-  last_basic_block_for_function (fn) = bb_count;
-  if (bb_count > VEC_length (basic_block, basic_block_info_for_function (fn)))
-    VEC_safe_grow_cleared (basic_block, gc,
-                          basic_block_info_for_function (fn), bb_count);
+  last_basic_block_for_fn (fn) = bb_count;
+  if (bb_count > basic_block_info_for_fn (fn)->length ())
+    vec_safe_grow_cleared (basic_block_info_for_fn (fn), bb_count);
 
-  if (bb_count > VEC_length (basic_block, label_to_block_map_for_function (fn)))
-    VEC_safe_grow_cleared (basic_block, gc,
-                          label_to_block_map_for_function (fn), bb_count);
+  if (bb_count > label_to_block_map_for_fn (fn)->length ())
+    vec_safe_grow_cleared (label_to_block_map_for_fn (fn), bb_count);
 
   index = streamer_read_hwi (ib);
   while (index != -1)
     {
-      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
+      basic_block bb = BASIC_BLOCK_FOR_FN (fn, index);
       unsigned int edge_count;
 
       if (bb == NULL)
@@ -652,11 +812,11 @@ input_cfg (struct lto_input_block *ib, struct function *fn,
 
          dest_index = streamer_read_uhwi (ib);
          probability = (int) streamer_read_hwi (ib);
-         count = ((gcov_type) streamer_read_hwi (ib) * count_materialization_scale
-                  + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
+         count = apply_scale ((gcov_type) streamer_read_gcov_count (ib),
+                               count_materialization_scale);
          edge_flags = streamer_read_uhwi (ib);
 
-         dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index);
+         dest = BASIC_BLOCK_FOR_FN (fn, dest_index);
 
          if (dest == NULL)
            dest = make_new_block (fn, dest_index);
@@ -669,16 +829,68 @@ input_cfg (struct lto_input_block *ib, struct function *fn,
       index = streamer_read_hwi (ib);
     }
 
-  p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn);
+  p_bb = ENTRY_BLOCK_PTR_FOR_F(fn);
   index = streamer_read_hwi (ib);
   while (index != -1)
     {
-      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
+      basic_block bb = BASIC_BLOCK_FOR_FN (fn, index);
       bb->prev_bb = p_bb;
       p_bb->next_bb = bb;
       p_bb = bb;
       index = streamer_read_hwi (ib);
     }
+
+  /* ???  The cfgloop interface is tied to cfun.  */
+  gcc_assert (cfun == fn);
+
+  /* Input the loop tree.  */
+  unsigned n_loops = streamer_read_uhwi (ib);
+  if (n_loops == 0)
+    return;
+
+  struct loops *loops = ggc_cleared_alloc<struct loops> ();
+  init_loops_structure (fn, loops, n_loops);
+  set_loops_for_fn (fn, loops);
+
+  /* Input each loop and associate it with its loop header so
+     flow_loops_find can rebuild the loop tree.  */
+  for (unsigned i = 1; i < n_loops; ++i)
+    {
+      int header_index = streamer_read_hwi (ib);
+      if (header_index == -1)
+       {
+         loops->larray->quick_push (NULL);
+         continue;
+       }
+
+      struct loop *loop = alloc_loop ();
+      loop->header = BASIC_BLOCK_FOR_FN (fn, header_index);
+      loop->header->loop_father = loop;
+
+      /* Read everything copy_loop_info copies.  */
+      loop->estimate_state = streamer_read_enum (ib, loop_estimation, EST_LAST);
+      loop->any_upper_bound = streamer_read_hwi (ib);
+      if (loop->any_upper_bound)
+       loop->nb_iterations_upper_bound = streamer_read_wi (ib);
+      loop->any_estimate = streamer_read_hwi (ib);
+      if (loop->any_estimate)
+       loop->nb_iterations_estimate = streamer_read_wi (ib);
+
+      /* Read OMP SIMD related info.  */
+      loop->safelen = streamer_read_hwi (ib);
+      loop->dont_vectorize = streamer_read_hwi (ib);
+      loop->force_vectorize = streamer_read_hwi (ib);
+      loop->simduid = stream_read_tree (ib, data_in);
+
+      place_new_loop (fn, loop);
+
+      /* flow_loops_find doesn't like loops not in the tree, hook them
+         all as siblings of the tree root temporarily.  */
+      flow_loop_tree_node_add (loops->tree_root, loop);
+    }
+
+  /* Rebuild the loop tree.  */
+  flow_loops_find (loops);
 }
 
 
@@ -701,15 +913,15 @@ input_ssa_names (struct lto_input_block *ib, struct data_in *data_in,
       bool is_default_def;
 
       /* Skip over the elements that had been freed.  */
-      while (VEC_length (tree, SSANAMES (fn)) < i)
-       VEC_quick_push (tree, SSANAMES (fn), NULL_TREE);
+      while (SSANAMES (fn)->length () < i)
+       SSANAMES (fn)->quick_push (NULL_TREE);
 
       is_default_def = (streamer_read_uchar (ib) != 0);
       name = stream_read_tree (ib, data_in);
       ssa_name = make_ssa_name_fn (fn, name, gimple_build_nop ());
 
       if (is_default_def)
-       set_default_def (SSA_NAME_VAR (ssa_name), ssa_name);
+       set_ssa_default_def (cfun, SSA_NAME_VAR (ssa_name), ssa_name);
 
       i = streamer_read_uhwi (ib);
     }
@@ -720,30 +932,62 @@ input_ssa_names (struct lto_input_block *ib, struct data_in *data_in,
    so they point to STMTS.  */
 
 static void
-fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts)
+fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts,
+                        struct function *fn)
 {
   struct cgraph_edge *cedge;
+  struct ipa_ref *ref = NULL;
+  unsigned int i;
+
   for (cedge = node->callees; cedge; cedge = cedge->next_callee)
-    cedge->call_stmt = stmts[cedge->lto_stmt_uid];
+    {
+      if (gimple_stmt_max_uid (fn) < cedge->lto_stmt_uid)
+        fatal_error (input_location,
+                    "Cgraph edge statement index out of range");
+      cedge->call_stmt = as_a <gcall *> (stmts[cedge->lto_stmt_uid - 1]);
+      if (!cedge->call_stmt)
+        fatal_error (input_location,
+                    "Cgraph edge statement index not found");
+    }
   for (cedge = node->indirect_calls; cedge; cedge = cedge->next_callee)
-    cedge->call_stmt = stmts[cedge->lto_stmt_uid];
+    {
+      if (gimple_stmt_max_uid (fn) < cedge->lto_stmt_uid)
+        fatal_error (input_location,
+                    "Cgraph edge statement index out of range");
+      cedge->call_stmt = as_a <gcall *> (stmts[cedge->lto_stmt_uid - 1]);
+      if (!cedge->call_stmt)
+        fatal_error (input_location, "Cgraph edge statement index not found");
+    }
+  for (i = 0; node->iterate_reference (i, ref); i++)
+    if (ref->lto_stmt_uid)
+      {
+       if (gimple_stmt_max_uid (fn) < ref->lto_stmt_uid)
+         fatal_error (input_location,
+                      "Reference statement index out of range");
+       ref->stmt = stmts[ref->lto_stmt_uid - 1];
+       if (!ref->stmt)
+         fatal_error (input_location, "Reference statement index not found");
+      }
 }
 
+
 /* Fixup call_stmt pointers in NODE and all clones.  */
 
 static void
 fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts)
 {
   struct cgraph_node *node;
+  struct function *fn;
 
   while (orig->clone_of)
     orig = orig->clone_of;
+  fn = DECL_STRUCT_FUNCTION (orig->decl);
 
-  fixup_call_stmt_edges_1 (orig, stmts);
+  fixup_call_stmt_edges_1 (orig, stmts, fn);
   if (orig->clones)
     for (node = orig->clones; node != orig;)
       {
-       fixup_call_stmt_edges_1 (node, stmts);
+       fixup_call_stmt_edges_1 (node, stmts, fn);
        if (node->clones)
          node = node->clones;
        else if (node->next_sibling_clone)
@@ -778,18 +1022,14 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
   if (len > 0)
     {
       int i;
-      VEC_safe_grow (tree, gc, fn->local_decls, len);
+      vec_safe_grow_cleared (fn->local_decls, len);
       for (i = 0; i < len; i++)
        {
          tree t = stream_read_tree (ib, data_in);
-         VEC_replace (tree, fn->local_decls, i, t);
+         (*fn->local_decls)[i] = t;
        }
     }
 
-  /* Input the function start and end loci.  */
-  fn->function_start_locus = lto_input_location (ib, data_in);
-  fn->function_end_locus = lto_input_location (ib, data_in);
-
   /* Input the current IL state of the function.  */
   fn->curr_properties = streamer_read_uhwi (ib);
 
@@ -807,8 +1047,15 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
   fn->has_nonlocal_label = bp_unpack_value (&bp, 1);
   fn->calls_alloca = bp_unpack_value (&bp, 1);
   fn->calls_setjmp = bp_unpack_value (&bp, 1);
+  fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1);
+  fn->has_simduid_loops = bp_unpack_value (&bp, 1);
   fn->va_list_fpr_size = bp_unpack_value (&bp, 8);
   fn->va_list_gpr_size = bp_unpack_value (&bp, 8);
+  fn->last_clique = bp_unpack_value (&bp, sizeof (short) * 8);
+
+  /* Input the function start and end loci.  */
+  fn->function_start_locus = stream_input_location_now (&bp, data_in);
+  fn->function_end_locus = stream_input_location_now (&bp, data_in);
 }
 
 
@@ -816,39 +1063,40 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
 
 static void
 input_function (tree fn_decl, struct data_in *data_in,
-               struct lto_input_block *ib)
+               struct lto_input_block *ib, struct lto_input_block *ib_cfg)
 {
   struct function *fn;
   enum LTO_tags tag;
   gimple *stmts;
   basic_block bb;
   struct cgraph_node *node;
-  tree args, narg, oarg;
 
-  fn = DECL_STRUCT_FUNCTION (fn_decl);
   tag = streamer_read_record_start (ib);
-  clear_line_info (data_in);
+  lto_tag_check (tag, LTO_function);
+
+  /* Read decls for parameters and args.  */
+  DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
+  DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
+
+  /* Read the tree of lexical scopes for the function.  */
+  DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
+
+  if (!streamer_read_uhwi (ib))
+    return;
+
+  push_struct_function (fn_decl);
+  fn = DECL_STRUCT_FUNCTION (fn_decl);
+  init_tree_ssa (fn);
+  /* We input IL in SSA form.  */
+  cfun->gimple_df->in_ssa_p = true;
 
   gimple_register_cfg_hooks ();
-  lto_tag_check (tag, LTO_function);
 
+  node = cgraph_node::get (fn_decl);
+  if (!node)
+    node = cgraph_node::create (fn_decl);
   input_struct_function_base (fn, data_in, ib);
-
-  /* Read all function arguments.  We need to re-map them here to the
-     arguments of the merged function declaration.  */
-  args = stream_read_tree (ib, data_in);
-  for (oarg = args, narg = DECL_ARGUMENTS (fn_decl);
-       oarg && narg;
-       oarg = TREE_CHAIN (oarg), narg = TREE_CHAIN (narg))
-    {
-      unsigned ix;
-      bool res;
-      res = streamer_tree_cache_lookup (data_in->reader_cache, oarg, &ix);
-      gcc_assert (res);
-      /* Replace the argument in the streamer cache.  */
-      streamer_tree_cache_insert_at (data_in->reader_cache, narg, ix);
-    }
-  gcc_assert (!oarg && !narg);
+  input_cfg (ib_cfg, data_in, fn, node->count_materialization_scale);
 
   /* Read all the SSA names.  */
   input_ssa_names (ib, data_in, fn);
@@ -856,11 +1104,8 @@ input_function (tree fn_decl, struct data_in *data_in,
   /* Read the exception handling regions in the function.  */
   input_eh_regions (ib, data_in, fn);
 
-  /* Read the tree of lexical scopes for the function.  */
-  DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
   gcc_assert (DECL_INITIAL (fn_decl));
   DECL_SAVED_TREE (fn_decl) = NULL_TREE;
-  node = cgraph_get_create_node (fn_decl);
 
   /* Read all the basic blocks.  */
   tag = streamer_read_record_start (ib);
@@ -874,9 +1119,14 @@ input_function (tree fn_decl, struct data_in *data_in,
   /* Fix up the call statements that are mentioned in the callgraph
      edges.  */
   set_gimple_stmt_max_uid (cfun, 0);
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       gimple_stmt_iterator gsi;
+      for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple stmt = gsi_stmt (gsi);
+         gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
+       }
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          gimple stmt = gsi_stmt (gsi);
@@ -884,9 +1134,16 @@ input_function (tree fn_decl, struct data_in *data_in,
        }
     }
   stmts = (gimple *) xcalloc (gimple_stmt_max_uid (fn), sizeof (gimple));
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
-      gimple_stmt_iterator bsi = gsi_start_bb (bb);
+      gimple_stmt_iterator bsi = gsi_start_phis (bb);
+      while (!gsi_end_p (bsi))
+       {
+         gimple stmt = gsi_stmt (bsi);
+         gsi_next (&bsi);
+         stmts[gimple_uid (stmt)] = stmt;
+       }
+      bsi = gsi_start_bb (bb);
       while (!gsi_end_p (bsi))
        {
          gimple stmt = gsi_stmt (bsi);
@@ -895,7 +1152,7 @@ input_function (tree fn_decl, struct data_in *data_in,
             We can't remove them earlier because this would cause uid
             mismatches in fixups, but we can do it at this point, as
             long as debug stmts don't require fixups.  */
-         if (!MAY_HAVE_DEBUG_STMTS && is_gimple_debug (stmt))
+         if (!MAY_HAVE_DEBUG_STMTS && !flag_wpa && is_gimple_debug (stmt))
            {
              gimple_stmt_iterator gsi = bsi;
              gsi_next (&bsi);
@@ -914,7 +1171,7 @@ input_function (tree fn_decl, struct data_in *data_in,
      of a gimple body is used by the cgraph routines, but we should
      really use the presence of the CFG.  */
   {
-    edge_iterator ei = ei_start (ENTRY_BLOCK_PTR->succs);
+    edge_iterator ei = ei_start (ENTRY_BLOCK_PTR_FOR_FN (cfun)->succs);
     gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest));
   }
 
@@ -925,78 +1182,86 @@ input_function (tree fn_decl, struct data_in *data_in,
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
   free (stmts);
+  pop_cfun ();
+}
+
+/* Read the body of function FN_DECL from DATA_IN using input block IB.  */
+
+static void
+input_constructor (tree var, struct data_in *data_in,
+                  struct lto_input_block *ib)
+{
+  DECL_INITIAL (var) = stream_read_tree (ib, data_in);
 }
 
 
-/* Read the body from DATA for function FN_DECL and fill it in.
+/* Read the body from DATA for function NODE and fill it in.
    FILE_DATA are the global decls and types.  SECTION_TYPE is either
    LTO_section_function_body or LTO_section_static_initializer.  If
    section type is LTO_section_function_body, FN must be the decl for
    that function.  */
 
 static void
-lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
-              const char *data, enum lto_section_type section_type)
+lto_read_body_or_constructor (struct lto_file_decl_data *file_data, struct symtab_node *node,
+                             const char *data, enum lto_section_type section_type)
 {
   const struct lto_function_header *header;
   struct data_in *data_in;
   int cfg_offset;
   int main_offset;
   int string_offset;
-  struct lto_input_block ib_cfg;
-  struct lto_input_block ib_main;
+  tree fn_decl = node->decl;
 
   header = (const struct lto_function_header *) data;
-  cfg_offset = sizeof (struct lto_function_header);
-  main_offset = cfg_offset + header->cfg_size;
-  string_offset = main_offset + header->main_size;
-
-  LTO_INIT_INPUT_BLOCK (ib_cfg,
-                       data + cfg_offset,
-                       0,
-                       header->cfg_size);
-
-  LTO_INIT_INPUT_BLOCK (ib_main,
-                       data + main_offset,
-                       0,
-                       header->main_size);
+  if (TREE_CODE (node->decl) == FUNCTION_DECL)
+    {
+      cfg_offset = sizeof (struct lto_function_header);
+      main_offset = cfg_offset + header->cfg_size;
+      string_offset = main_offset + header->main_size;
+    }
+  else
+    {
+      main_offset = sizeof (struct lto_function_header);
+      string_offset = main_offset + header->main_size;
+    }
 
   data_in = lto_data_in_create (file_data, data + string_offset,
-                               header->string_size, NULL);
-
-  /* Make sure the file was generated by the exact same compiler.  */
-  lto_check_version (header->lto_header.major_version,
-                    header->lto_header.minor_version);
+                             header->string_size, vNULL);
 
   if (section_type == LTO_section_function_body)
     {
-      struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
       struct lto_in_decl_state *decl_state;
-      struct cgraph_node *node = cgraph_get_node (fn_decl);
       unsigned from;
 
       gcc_checking_assert (node);
-      push_cfun (fn);
-      init_tree_ssa (fn);
 
       /* Use the function's decl state. */
       decl_state = lto_get_function_in_decl_state (file_data, fn_decl);
       gcc_assert (decl_state);
       file_data->current_decl_state = decl_state;
 
-      input_cfg (&ib_cfg, fn, node->count_materialization_scale);
 
       /* Set up the struct function.  */
-      from = VEC_length (tree, data_in->reader_cache->nodes);
-      input_function (fn_decl, data_in, &ib_main);
+      from = data_in->reader_cache->nodes.length ();
+      lto_input_block ib_main (data + main_offset, header->main_size,
+                              file_data->mode_table);
+      if (TREE_CODE (node->decl) == FUNCTION_DECL)
+       {
+         lto_input_block ib_cfg (data + cfg_offset, header->cfg_size,
+                                 file_data->mode_table);
+         input_function (fn_decl, data_in, &ib_main, &ib_cfg);
+       }
+      else
+        input_constructor (fn_decl, data_in, &ib_main);
+      data_in->location_cache.apply_location_cache ();
       /* And fixup types we streamed locally.  */
        {
          struct streamer_tree_cache_d *cache = data_in->reader_cache;
-         unsigned len = VEC_length (tree, cache->nodes);
+         unsigned len = cache->nodes.length ();
          unsigned i;
          for (i = len; i-- > from;)
            {
-             tree t = VEC_index (tree, cache->nodes, i);
+             tree t = streamer_tree_cache_get_tree (cache, i);
              if (t == NULL_TREE)
                continue;
 
@@ -1015,38 +1280,72 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
            }
        }
 
-      /* We should now be in SSA.  */
-      cfun->gimple_df->in_ssa_p = true;
-
       /* Restore decl state */
       file_data->current_decl_state = file_data->global_decl_state;
-
-      pop_cfun ();
     }
 
-  clear_line_info (data_in);
   lto_data_in_delete (data_in);
 }
 
 
-/* Read the body of FN_DECL using DATA.  FILE_DATA holds the global
+/* Read the body of NODE using DATA.  FILE_DATA holds the global
    decls and types.  */
 
 void
 lto_input_function_body (struct lto_file_decl_data *file_data,
-                        tree fn_decl, const char *data)
+                        struct cgraph_node *node, const char *data)
+{
+  lto_read_body_or_constructor (file_data, node, data, LTO_section_function_body);
+}
+
+/* Read the body of NODE using DATA.  FILE_DATA holds the global
+   decls and types.  */
+
+void
+lto_input_variable_constructor (struct lto_file_decl_data *file_data,
+                               struct varpool_node *node, const char *data)
 {
-  current_function_decl = fn_decl;
-  lto_read_body (file_data, fn_decl, data, LTO_section_function_body);
+  lto_read_body_or_constructor (file_data, node, data, LTO_section_function_body);
 }
 
 
+/* Read the physical representation of a tree node EXPR from
+   input block IB using the per-file context in DATA_IN.  */
+
+static void
+lto_read_tree_1 (struct lto_input_block *ib, struct data_in *data_in, tree expr)
+{
+  /* Read all the bitfield values in EXPR.  Note that for LTO, we
+     only write language-independent bitfields, so no more unpacking is
+     needed.  */
+  streamer_read_tree_bitfields (ib, data_in, expr);
+
+  /* Read all the pointer fields in EXPR.  */
+  streamer_read_tree_body (ib, data_in, expr);
+
+  /* Read any LTO-specific data not read by the tree streamer.  */
+  if (DECL_P (expr)
+      && TREE_CODE (expr) != FUNCTION_DECL
+      && TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
+    DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
+
+  /* We should never try to instantiate an MD or NORMAL builtin here.  */
+  if (TREE_CODE (expr) == FUNCTION_DECL)
+    gcc_assert (!streamer_handle_as_builtin_p (expr));
+
+#ifdef LTO_STREAMER_DEBUG
+  /* Remove the mapping to RESULT's original address set by
+     streamer_alloc_tree.  */
+  lto_orig_address_remove (expr);
+#endif
+}
+
 /* Read the physical representation of a tree node with tag TAG from
    input block IB using the per-file context in DATA_IN.  */
 
 static tree
 lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
-              enum LTO_tags tag)
+              enum LTO_tags tag, hashval_t hash)
 {
   /* Instantiate a new tree node.  */
   tree result = streamer_alloc_tree (ib, data_in, tag);
@@ -1054,35 +1353,70 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
   /* Enter RESULT in the reader cache.  This will make RESULT
      available so that circular references in the rest of the tree
      structure can be resolved in subsequent calls to stream_read_tree.  */
-  streamer_tree_cache_append (data_in->reader_cache, result);
+  streamer_tree_cache_append (data_in->reader_cache, result, hash);
 
-  /* Read all the bitfield values in RESULT.  Note that for LTO, we
-     only write language-independent bitfields, so no more unpacking is
-     needed.  */
-  streamer_read_tree_bitfields (ib, result);
+  lto_read_tree_1 (ib, data_in, result);
 
-  /* Read all the pointer fields in RESULT.  */
-  streamer_read_tree_body (ib, data_in, result);
+  /* end_marker = */ streamer_read_uchar (ib);
 
-  /* Read any LTO-specific data not read by the tree streamer.  */
-  if (DECL_P (result)
-      && TREE_CODE (result) != FUNCTION_DECL
-      && TREE_CODE (result) != TRANSLATION_UNIT_DECL)
-    DECL_INITIAL (result) = stream_read_tree (ib, data_in);
+  return result;
+}
 
-  /* We should never try to instantiate an MD or NORMAL builtin here.  */
-  if (TREE_CODE (result) == FUNCTION_DECL)
-    gcc_assert (!streamer_handle_as_builtin_p (result));
 
-  /* end_marker = */ streamer_read_uchar (ib);
+/* Populate the reader cache with trees materialized from the SCC
+   following in the IB, DATA_IN stream.  */
 
-#ifdef LTO_STREAMER_DEBUG
-  /* Remove the mapping to RESULT's original address set by
-     streamer_alloc_tree.  */
-  lto_orig_address_remove (result);
-#endif
+hashval_t
+lto_input_scc (struct lto_input_block *ib, struct data_in *data_in,
+              unsigned *len, unsigned *entry_len)
+{
+  /* A blob of unnamed tree nodes, fill the cache from it and
+     recurse.  */
+  unsigned size = streamer_read_uhwi (ib);
+  hashval_t scc_hash = streamer_read_uhwi (ib);
+  unsigned scc_entry_len = 1;
 
-  return result;
+  if (size == 1)
+    {
+      enum LTO_tags tag = streamer_read_record_start (ib);
+      lto_input_tree_1 (ib, data_in, tag, scc_hash);
+    }
+  else
+    {
+      unsigned int first = data_in->reader_cache->nodes.length ();
+      tree result;
+
+      scc_entry_len = streamer_read_uhwi (ib);
+
+      /* Materialize size trees by reading their headers.  */
+      for (unsigned i = 0; i < size; ++i)
+       {
+         enum LTO_tags tag = streamer_read_record_start (ib);
+         if (tag == LTO_null
+             || (tag >= LTO_field_decl_ref && tag <= LTO_global_decl_ref)
+             || tag == LTO_tree_pickle_reference
+             || tag == LTO_builtin_decl
+             || tag == LTO_integer_cst
+             || tag == LTO_tree_scc)
+           gcc_unreachable ();
+
+         result = streamer_alloc_tree (ib, data_in, tag);
+         streamer_tree_cache_append (data_in->reader_cache, result, 0);
+       }
+
+      /* Read the tree bitpacks and references.  */
+      for (unsigned i = 0; i < size; ++i)
+       {
+         result = streamer_tree_cache_get_tree (data_in->reader_cache,
+                                                first + i);
+         lto_read_tree_1 (ib, data_in, result);
+         /* end_marker = */ streamer_read_uchar (ib);
+       }
+    }
+
+  *len = size;
+  *entry_len = scc_entry_len;
+  return scc_hash;
 }
 
 
@@ -1091,17 +1425,16 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
    to previously read nodes.  */
 
 tree
-lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
+lto_input_tree_1 (struct lto_input_block *ib, struct data_in *data_in,
+                 enum LTO_tags tag, hashval_t hash)
 {
-  enum LTO_tags tag;
   tree result;
 
-  tag = streamer_read_record_start (ib);
   gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);
 
   if (tag == LTO_null)
     result = NULL_TREE;
-  else if (tag >= LTO_field_decl_ref && tag <= LTO_global_decl_ref)
+  else if (tag >= LTO_field_decl_ref && tag <= LTO_namelist_decl_ref)
     {
       /* If TAG is a reference to an indexable tree, the next value
         in IB is the index into the table where we expect to find
@@ -1120,21 +1453,47 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
         the code and class.  */
       result = streamer_get_builtin_tree (ib, data_in);
     }
-  else if (tag == lto_tree_code_to_tag (INTEGER_CST))
+  else if (tag == LTO_integer_cst)
     {
-      /* For integer constants we only need the type and its hi/low
-        words.  */
-      result = streamer_read_integer_cst (ib, data_in);
+      /* For shared integer constants in singletons we can use the
+         existing tree integer constant merging code.  */
+      tree type = stream_read_tree (ib, data_in);
+      unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
+      unsigned HOST_WIDE_INT i;
+      HOST_WIDE_INT a[WIDE_INT_MAX_ELTS];
+
+      for (i = 0; i < len; i++)
+       a[i] = streamer_read_hwi (ib);
+      gcc_assert (TYPE_PRECISION (type) <= MAX_BITSIZE_MODE_ANY_INT);
+      result = wide_int_to_tree (type, wide_int::from_array
+                                (a, len, TYPE_PRECISION (type)));
+      streamer_tree_cache_append (data_in->reader_cache, result, hash);
     }
+  else if (tag == LTO_tree_scc)
+    gcc_unreachable ();
   else
     {
       /* Otherwise, materialize a new node from IB.  */
-      result = lto_read_tree (ib, data_in, tag);
+      result = lto_read_tree (ib, data_in, tag, hash);
     }
 
   return result;
 }
 
+tree
+lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
+{
+  enum LTO_tags tag;
+
+  /* Input and skip SCCs.  */
+  while ((tag = streamer_read_record_start (ib)) == LTO_tree_scc)
+    {
+      unsigned len, entry_len;
+      lto_input_scc (ib, data_in, &len, &entry_len);
+    }
+  return lto_input_tree_1 (ib, data_in, tag, 0);
+}
+
 
 /* Input toplevel asms.  */
 
@@ -1144,10 +1503,10 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base)
   size_t len;
   const char *data = lto_get_section_data (file_data, LTO_section_asm,
                                           NULL, &len);
-  const struct lto_asm_header *header = (const struct lto_asm_header *) data;
+  const struct lto_simple_header_with_strings *header
+    = (const struct lto_simple_header_with_strings *) data;
   int string_offset;
   struct data_in *data_in;
-  struct lto_input_block ib;
   tree str;
 
   if (! data)
@@ -1155,41 +1514,151 @@ lto_input_toplevel_asms (struct lto_file_decl_data *file_data, int order_base)
 
   string_offset = sizeof (*header) + header->main_size;
 
-  LTO_INIT_INPUT_BLOCK (ib,
-                       data + sizeof (*header),
-                       0,
-                       header->main_size);
+  lto_input_block ib (data + sizeof (*header), header->main_size,
+                     file_data->mode_table);
 
   data_in = lto_data_in_create (file_data, data + string_offset,
-                               header->string_size, NULL);
-
-  /* Make sure the file was generated by the exact same compiler.  */
-  lto_check_version (header->lto_header.major_version,
-                    header->lto_header.minor_version);
+                             header->string_size, vNULL);
 
   while ((str = streamer_read_string_cst (data_in, &ib)))
     {
-      struct asm_node *node = add_asm_node (str);
+      asm_node *node = symtab->finalize_toplevel_asm (str);
       node->order = streamer_read_hwi (&ib) + order_base;
-      if (node->order >= symtab_order)
-       symtab_order = node->order + 1;
+      if (node->order >= symtab->order)
+       symtab->order = node->order + 1;
     }
 
-  clear_line_info (data_in);
   lto_data_in_delete (data_in);
 
   lto_free_section_data (file_data, LTO_section_asm, NULL, data, len);
 }
 
 
+/* Input mode table.  */
+
+void
+lto_input_mode_table (struct lto_file_decl_data *file_data)
+{
+  size_t len;
+  const char *data = lto_get_section_data (file_data, LTO_section_mode_table,
+                                          NULL, &len);
+  if (! data)
+    {
+      internal_error ("cannot read LTO mode table from %s",
+                     file_data->file_name);
+      return;
+    }
+
+  unsigned char *table = ggc_cleared_vec_alloc<unsigned char> (1 << 8);
+  file_data->mode_table = table;
+  const struct lto_simple_header_with_strings *header
+    = (const struct lto_simple_header_with_strings *) data;
+  int string_offset;
+  struct data_in *data_in;
+  string_offset = sizeof (*header) + header->main_size;
+
+  lto_input_block ib (data + sizeof (*header), header->main_size, NULL);
+  data_in = lto_data_in_create (file_data, data + string_offset,
+                               header->string_size, vNULL);
+  bitpack_d bp = streamer_read_bitpack (&ib);
+
+  table[VOIDmode] = VOIDmode;
+  table[BLKmode] = BLKmode;
+  unsigned int m;
+  while ((m = bp_unpack_value (&bp, 8)) != VOIDmode)
+    {
+      enum mode_class mclass
+       = bp_unpack_enum (&bp, mode_class, MAX_MODE_CLASS);
+      unsigned int size = bp_unpack_value (&bp, 8);
+      unsigned int prec = bp_unpack_value (&bp, 16);
+      machine_mode inner = (machine_mode) table[bp_unpack_value (&bp, 8)];
+      unsigned int nunits = bp_unpack_value (&bp, 8);
+      unsigned int ibit = 0, fbit = 0;
+      unsigned int real_fmt_len = 0;
+      const char *real_fmt_name = NULL;
+      switch (mclass)
+       {
+       case MODE_FRACT:
+       case MODE_UFRACT:
+       case MODE_ACCUM:
+       case MODE_UACCUM:
+         ibit = bp_unpack_value (&bp, 8);
+         fbit = bp_unpack_value (&bp, 8);
+         break;
+       case MODE_FLOAT:
+       case MODE_DECIMAL_FLOAT:
+         real_fmt_name = bp_unpack_indexed_string (data_in, &bp,
+                                                   &real_fmt_len);
+         break;
+       default:
+         break;
+       }
+      /* First search just the GET_CLASS_NARROWEST_MODE to wider modes,
+        if not found, fallback to all modes.  */
+      int pass;
+      for (pass = 0; pass < 2; pass++)
+       for (machine_mode mr = pass ? VOIDmode
+                                   : GET_CLASS_NARROWEST_MODE (mclass);
+            pass ? mr < MAX_MACHINE_MODE : mr != VOIDmode;
+            pass ? mr = (machine_mode) (m + 1)
+                 : mr = GET_MODE_WIDER_MODE (mr))
+         if (GET_MODE_CLASS (mr) != mclass
+             || GET_MODE_SIZE (mr) != size
+             || GET_MODE_PRECISION (mr) != prec
+             || GET_MODE_INNER (mr) != inner
+             || GET_MODE_IBIT (mr) != ibit
+             || GET_MODE_FBIT (mr) != fbit
+             || GET_MODE_NUNITS (mr) != nunits)
+           continue;
+         else if ((mclass == MODE_FLOAT || mclass == MODE_DECIMAL_FLOAT)
+                  && strcmp (REAL_MODE_FORMAT (mr)->name, real_fmt_name) != 0)
+           continue;
+         else
+           {
+             table[m] = mr;
+             pass = 2;
+             break;
+           }
+      unsigned int mname_len;
+      const char *mname = bp_unpack_indexed_string (data_in, &bp, &mname_len);
+      if (pass == 2)
+       {
+         switch (mclass)
+           {
+           case MODE_VECTOR_INT:
+           case MODE_VECTOR_FLOAT:
+           case MODE_VECTOR_FRACT:
+           case MODE_VECTOR_UFRACT:
+           case MODE_VECTOR_ACCUM:
+           case MODE_VECTOR_UACCUM:
+             /* For unsupported vector modes just use BLKmode,
+                if the scalar mode is supported.  */
+             if (inner != VOIDmode)
+               {
+                 table[m] = BLKmode;
+                 break;
+               }
+             /* FALLTHRU */
+           default:
+             fatal_error (UNKNOWN_LOCATION, "unsupported mode %s\n", mname);
+             break;
+           }
+       }
+    }
+  lto_data_in_delete (data_in);
+
+  lto_free_section_data (file_data, LTO_section_mode_table, NULL, data, len);
+}
+
+
 /* Initialization for the LTO reader.  */
 
 void
 lto_reader_init (void)
 {
   lto_streamer_init ();
-  file_name_hash_table = htab_create (37, hash_string_slot_node,
-                                     eq_string_slot_node, free);
+  file_name_hash_table
+    = new hash_table<freeing_string_slot_hasher> (37);
 }
 
 
@@ -1200,15 +1669,14 @@ lto_reader_init (void)
 struct data_in *
 lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings,
                    unsigned len,
-                   VEC(ld_plugin_symbol_resolution_t,heap) *resolutions)
+                   vec<ld_plugin_symbol_resolution_t> resolutions)
 {
-  struct data_in *data_in = XCNEW (struct data_in);
+  struct data_in *data_in = new (struct data_in);
   data_in->file_data = file_data;
   data_in->strings = strings;
   data_in->strings_len = len;
   data_in->globals_resolution = resolutions;
-  data_in->reader_cache = streamer_tree_cache_create ();
-
+  data_in->reader_cache = streamer_tree_cache_create (false, false, true);
   return data_in;
 }
 
@@ -1218,8 +1686,7 @@ lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings,
 void
 lto_data_in_delete (struct data_in *data_in)
 {
-  VEC_free (ld_plugin_symbol_resolution_t, heap, data_in->globals_resolution);
+  data_in->globals_resolution.release ();
   streamer_tree_cache_delete (data_in->reader_cache);
-  free (data_in->labels);
-  free (data_in);
+  delete data_in;
 }