]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/lto-streamer-out.c
Update copyright years.
[thirdparty/gcc.git] / gcc / lto-streamer-out.c
index d007c0af5d66a37edc44b46a7ef5f51970a8086a..a3306e01851c2b4af4e1e664a0293f8ba926853e 100644 (file)
@@ -1,6 +1,6 @@
 /* Write the GIMPLE representation to a file stream.
 
-   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+   Copyright (C) 2009-2020 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
    Re-implemented by Diego Novillo <dnovillo@google.com>
 
@@ -41,6 +41,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "gomp-constants.h"
 #include "debug.h"
+#include "omp-offload.h"
+#include "print-tree.h"
+#include "tree-dfa.h"
 
 
 static void lto_write_tree (struct output_block*, tree, bool);
@@ -64,6 +67,9 @@ struct output_block *
 create_output_block (enum lto_section_type section_type)
 {
   struct output_block *ob = XCNEW (struct output_block);
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "Creating output block for %s\n",
+            lto_section_name [section_type]);
 
   ob->section_type = section_type;
   ob->decl_state = lto_get_out_decl_state ();
@@ -114,6 +120,17 @@ output_type_ref (struct output_block *ob, tree node)
   lto_output_type_ref_index (ob->decl_state, ob->main_stream, node);
 }
 
+/* Wrapper around variably_modified_type_p avoiding type modification
+   during WPA streaming.  */
+
+static bool
+lto_variably_modified_type_p (tree type)
+{
+  return (in_lto_p
+         ? TYPE_LANG_FLAG_0 (TYPE_MAIN_VARIANT (type))
+         : variably_modified_type_p (type, NULL_TREE));
+}
+
 
 /* Return true if tree node T is written to various tables.  For these
    nodes, we sometimes want to write their phyiscal representation
@@ -128,10 +145,13 @@ tree_is_indexable (tree t)
      definition.  */
   if ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
       && DECL_CONTEXT (t))
-    return variably_modified_type_p (TREE_TYPE (DECL_CONTEXT (t)), NULL_TREE);
-  /* IMPORTED_DECL is put into BLOCK and thus it never can be shared.  */
+    return lto_variably_modified_type_p (TREE_TYPE (DECL_CONTEXT (t)));
+  /* IMPORTED_DECL is put into BLOCK and thus it never can be shared.
+     We should no longer need to stream it.  */
   else if (TREE_CODE (t) == IMPORTED_DECL)
-    return false;
+    gcc_unreachable ();
+  else if (TREE_CODE (t) == LABEL_DECL)
+    return FORCED_LABEL (t) || DECL_NONLOCAL (t);
   else if (((VAR_P (t) && !TREE_STATIC (t))
            || TREE_CODE (t) == TYPE_DECL
            || TREE_CODE (t) == CONST_DECL
@@ -145,10 +165,10 @@ tree_is_indexable (tree t)
      them we have to localize their members as well.
      ???  In theory that includes non-FIELD_DECLs as well.  */
   else if (TYPE_P (t)
-          && variably_modified_type_p (t, NULL_TREE))
+          && lto_variably_modified_type_p (t))
     return false;
   else if (TREE_CODE (t) == FIELD_DECL
-          && variably_modified_type_p (DECL_CONTEXT (t), NULL_TREE))
+          && lto_variably_modified_type_p (DECL_CONTEXT (t)))
     return false;
   else
     return (TYPE_P (t) || DECL_P (t) || TREE_CODE (t) == SSA_NAME);
@@ -298,7 +318,6 @@ lto_is_streamable (tree expr)
      name version in lto_output_tree_ref (see output_ssa_names).  */
   return !is_lang_specific (expr)
         && code != SSA_NAME
-        && code != CALL_EXPR
         && code != LANG_TYPE
         && code != MODIFY_EXPR
         && code != INIT_EXPR
@@ -495,7 +514,7 @@ public:
     tree t;
     hashval_t hash;
   };
-  vec<scc_entry> sccstack;
+  auto_vec<scc_entry,32> sccstack;
 
 private:
   struct sccs
@@ -525,7 +544,7 @@ private:
            bool ref_p, bool this_ref_p);
 
   hash_map<tree, sccs *> sccstate;
-  vec<worklist> worklist_vec;
+  auto_vec<worklist, 32> worklist_vec;
   struct obstack sccstate_obstack;
 };
 
@@ -539,9 +558,7 @@ DFS::DFS (struct output_block *ob, tree expr, bool ref_p, bool this_ref_p,
          bool single_p)
 {
   unsigned int next_dfs_num = 1;
-  sccstack.create (0);
   gcc_obstack_init (&sccstate_obstack);
-  worklist_vec = vNULL;
   DFS_write_tree (ob, NULL, expr, ref_p, this_ref_p);
   while (!worklist_vec.is_empty ())
     {
@@ -716,12 +733,10 @@ DFS::DFS (struct output_block *ob, tree expr, bool ref_p, bool this_ref_p,
        from_state->low = MIN (cstate->dfsnum, from_state->low);
       worklist_vec.pop ();
     }
-  worklist_vec.release ();
 }
 
 DFS::~DFS ()
 {
-  sccstack.release ();
   obstack_free (&sccstate_obstack, NULL);
 }
 
@@ -737,6 +752,14 @@ DFS::DFS_write_tree_body (struct output_block *ob,
 
   enum tree_code code;
 
+  if (streamer_dump_file)
+    {
+      print_node_brief (streamer_dump_file, "    Streaming ",
+                       expr, 4);
+      fprintf (streamer_dump_file, "  to %s\n",
+              lto_section_name [ob->section_type]);
+    }
+
   code = TREE_CODE (expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
@@ -747,10 +770,15 @@ DFS::DFS_write_tree_body (struct output_block *ob,
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
     {
-      for (unsigned i = 0; i < VECTOR_CST_NELTS (expr); ++i)
-       DFS_follow_tree_edge (VECTOR_CST_ELT (expr, i));
+      unsigned int count = vector_cst_encoded_nelts (expr);
+      for (unsigned int i = 0; i < count; ++i)
+       DFS_follow_tree_edge (VECTOR_CST_ENCODED_ELT (expr, i));
     }
 
+  if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST))
+    for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+      DFS_follow_tree_edge (POLY_INT_CST_COEFF (expr, i));
+
   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
     {
       DFS_follow_tree_edge (TREE_REALPART (expr));
@@ -762,7 +790,7 @@ DFS::DFS_write_tree_body (struct output_block *ob,
       /* Drop names that were created for anonymous entities.  */
       if (DECL_NAME (expr)
          && TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
-         && anon_aggrname_p (DECL_NAME (expr)))
+         && IDENTIFIER_ANON_P (DECL_NAME (expr)))
        ;
       else
        DFS_follow_tree_edge (DECL_NAME (expr));
@@ -783,10 +811,7 @@ DFS::DFS_write_tree_body (struct output_block *ob,
 
       DFS_follow_tree_edge (DECL_ATTRIBUTES (expr));
 
-      /* Do not follow DECL_ABSTRACT_ORIGIN.  We cannot handle debug information
-        for early inlining so drop it on the floor instead of ICEing in
-        dwarf2out.c.
-        We however use DECL_ABSTRACT_ORIGIN == error_mark_node to mark
+      /* We use DECL_ABSTRACT_ORIGIN == error_mark_node to mark
         declarations which should be eliminated by decl merging. Be sure none
         leaks to this point.  */
       gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node);
@@ -796,16 +821,11 @@ DFS::DFS_write_tree_body (struct output_block *ob,
           || TREE_CODE (expr) == PARM_DECL)
          && DECL_HAS_VALUE_EXPR_P (expr))
        DFS_follow_tree_edge (DECL_VALUE_EXPR (expr));
-      if (VAR_P (expr))
+      if (VAR_P (expr)
+         && DECL_HAS_DEBUG_EXPR_P (expr))
        DFS_follow_tree_edge (DECL_DEBUG_EXPR (expr));
     }
 
-  if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
-    {
-      if (TREE_CODE (expr) == TYPE_DECL)
-       DFS_follow_tree_edge (DECL_ORIGINAL_TYPE (expr));
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
     {
       /* Make sure we don't inadvertently set the assembler name.  */
@@ -819,12 +839,12 @@ DFS::DFS_write_tree_body (struct output_block *ob,
       DFS_follow_tree_edge (DECL_BIT_FIELD_TYPE (expr));
       DFS_follow_tree_edge (DECL_BIT_FIELD_REPRESENTATIVE (expr));
       DFS_follow_tree_edge (DECL_FIELD_BIT_OFFSET (expr));
-      DFS_follow_tree_edge (DECL_FCONTEXT (expr));
+      gcc_checking_assert (!DECL_FCONTEXT (expr));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     {
-      DFS_follow_tree_edge (DECL_VINDEX (expr));
+      gcc_checking_assert (DECL_VINDEX (expr) == NULL);
       DFS_follow_tree_edge (DECL_FUNCTION_PERSONALITY (expr));
       DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_TARGET (expr));
       DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr));
@@ -844,7 +864,9 @@ DFS::DFS_write_tree_body (struct output_block *ob,
       DFS_follow_tree_edge (TYPE_CONTEXT (expr));
       /* TYPE_CANONICAL is re-computed during type merging, so no need
         to follow it here.  */
-      DFS_follow_tree_edge (TYPE_STUB_DECL (expr));
+      /* Do not stream TYPE_STUB_DECL; it is not needed by LTO but currently
+        it cannot be freed by free_lang_data without triggering ICEs in
+        langhooks.  */
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
@@ -888,30 +910,17 @@ DFS::DFS_write_tree_body (struct output_block *ob,
   if (CODE_CONTAINS_STRUCT (code, TS_BLOCK))
     {
       for (tree t = BLOCK_VARS (expr); t; t = TREE_CHAIN (t))
-       if (VAR_OR_FUNCTION_DECL_P (t)
-           && DECL_EXTERNAL (t))
-         /* We have to stream externals in the block chain as
-            non-references.  See also
-            tree-streamer-out.c:streamer_write_chain.  */
-         DFS_write_tree (ob, expr_state, t, ref_p, false);
-       else
+       {
+         /* We would have to stream externals in the block chain as
+            non-references but we should have dropped them in
+            free-lang-data.  */
+         gcc_assert (!VAR_OR_FUNCTION_DECL_P (t) || !DECL_EXTERNAL (t));
          DFS_follow_tree_edge (t);
+       }
 
       DFS_follow_tree_edge (BLOCK_SUPERCONTEXT (expr));
+      DFS_follow_tree_edge (BLOCK_ABSTRACT_ORIGIN (expr));
 
-      /* Follow BLOCK_ABSTRACT_ORIGIN for the limited cases we can
-        handle - those that represent inlined function scopes.
-        For the drop rest them on the floor instead of ICEing
-        in dwarf2out.c, but keep the notion of whether the block
-        is an inlined block by refering to itself for the sake of
-        tree_nonartificial_location.  */
-      if (inlined_function_outer_scope_p (expr))
-       {
-         tree ultimate_origin = block_ultimate_origin (expr);
-         DFS_follow_tree_edge (ultimate_origin);
-       }
-      else if (BLOCK_ABSTRACT_ORIGIN (expr))
-       DFS_follow_tree_edge (expr);
       /* Do not follow BLOCK_NONLOCALIZED_VARS.  We cannot handle debug
         information for early inlined BLOCKs so drop it on the floor instead
         of ICEing in dwarf2out.c.  */
@@ -935,15 +944,10 @@ DFS::DFS_write_tree_body (struct output_block *ob,
        DFS_follow_tree_edge (t);
       DFS_follow_tree_edge (BINFO_OFFSET (expr));
       DFS_follow_tree_edge (BINFO_VTABLE (expr));
-      DFS_follow_tree_edge (BINFO_VPTR_FIELD (expr));
-
-      /* The number of BINFO_BASE_ACCESSES has already been emitted in
-        EXPR's bitfield section.  */
-      FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (expr), i, t)
-       DFS_follow_tree_edge (t);
 
-      /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
-        and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
+      /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX,
+        BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used
+        by C++ FE only.  */
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
@@ -1028,13 +1032,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
   hstate.commit_flag ();
 
   if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
-    {
-      int i;
-      hstate.add_wide_int (TREE_INT_CST_NUNITS (t));
-      hstate.add_wide_int (TREE_INT_CST_EXT_NUNITS (t));
-      for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
-       hstate.add_wide_int (TREE_INT_CST_ELT (t, i));
-    }
+    hstate.add_wide_int (wi::to_widest (t));
 
   if (CODE_CONTAINS_STRUCT (code, TS_REAL_CST))
     {
@@ -1058,7 +1056,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
 
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
     {
-      hstate.add_wide_int (DECL_MODE (t));
+      hstate.add_hwi (DECL_MODE (t));
       hstate.add_flag (DECL_NONLOCAL (t));
       hstate.add_flag (DECL_VIRTUAL_P (t));
       hstate.add_flag (DECL_IGNORED_P (t));
@@ -1079,6 +1077,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
        {
          hstate.add_flag (DECL_PACKED (t));
          hstate.add_flag (DECL_NONADDRESSABLE_P (t));
+         hstate.add_flag (DECL_PADDING_P (t));
          hstate.add_int (DECL_OFFSET_ALIGN (t));
        }
       else if (code == VAR_DECL)
@@ -1130,12 +1129,12 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       hstate.add_int (DECL_BUILT_IN_CLASS (t));
       hstate.add_flag (DECL_STATIC_CONSTRUCTOR (t));
       hstate.add_flag (DECL_STATIC_DESTRUCTOR (t));
+      hstate.add_flag (FUNCTION_DECL_DECL_TYPE (t));
       hstate.add_flag (DECL_UNINLINABLE (t));
       hstate.add_flag (DECL_POSSIBLY_INLINED (t));
       hstate.add_flag (DECL_IS_NOVOPS (t));
       hstate.add_flag (DECL_IS_RETURNS_TWICE (t));
       hstate.add_flag (DECL_IS_MALLOC (t));
-      hstate.add_flag (DECL_IS_OPERATOR_NEW (t));
       hstate.add_flag (DECL_DECLARED_INLINE_P (t));
       hstate.add_flag (DECL_STATIC_CHAIN (t));
       hstate.add_flag (DECL_NO_INLINE_WARNING_P (t));
@@ -1146,16 +1145,14 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       hstate.add_flag (DECL_LOOPING_CONST_OR_PURE_P (t));
       hstate.commit_flag ();
       if (DECL_BUILT_IN_CLASS (t) != NOT_BUILT_IN)
-       hstate.add_int (DECL_FUNCTION_CODE (t));
+       hstate.add_int (DECL_UNCHECKED_FUNCTION_CODE (t));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_COMMON))
     {
-      hstate.add_wide_int (TYPE_MODE (t));
-      hstate.add_flag (TYPE_STRING_FLAG (t));
+      hstate.add_hwi (TYPE_MODE (t));
       /* TYPE_NO_FORCE_BLK is private to stor-layout and need
         no streaming.  */
-      hstate.add_flag (TYPE_NEEDS_CONSTRUCTING (t));
       hstate.add_flag (TYPE_PACKED (t));
       hstate.add_flag (TYPE_RESTRICT (t));
       hstate.add_flag (TYPE_USER_ALIGN (t));
@@ -1164,14 +1161,18 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
        {
          hstate.add_flag (TYPE_TRANSPARENT_AGGR (t));
          hstate.add_flag (TYPE_FINAL_P (t));
+          hstate.add_flag (TYPE_CXX_ODR_P (t));
        }
       else if (code == ARRAY_TYPE)
        hstate.add_flag (TYPE_NONALIASED_COMPONENT (t));
+      if (code == ARRAY_TYPE || code == INTEGER_TYPE)
+        hstate.add_flag (TYPE_STRING_FLAG (t));
       if (AGGREGATE_TYPE_P (t))
        hstate.add_flag (TYPE_TYPELESS_STORAGE (t));
       hstate.commit_flag ();
       hstate.add_int (TYPE_PRECISION (t));
       hstate.add_int (TYPE_ALIGN (t));
+      hstate.add_int (TYPE_EMPTY_P (t));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
@@ -1181,10 +1182,10 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
   if (CODE_CONTAINS_STRUCT (code, TS_TARGET_OPTION)
       /* We don't stream these when passing things to a different target.  */
       && !lto_stream_offload_p)
-    hstate.add_wide_int (cl_target_option_hash (TREE_TARGET_OPTION (t)));
+    hstate.add_hwi (cl_target_option_hash (TREE_TARGET_OPTION (t)));
 
   if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
-    hstate.add_wide_int (cl_optimization_hash (TREE_OPTIMIZATION (t)));
+    hstate.add_hwi (cl_optimization_hash (TREE_OPTIMIZATION (t)));
 
   if (CODE_CONTAINS_STRUCT (code, TS_IDENTIFIER))
     hstate.merge_hash (IDENTIFIER_HASH_VALUE (t));
@@ -1199,8 +1200,15 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
-    for (unsigned i = 0; i < VECTOR_CST_NELTS (t); ++i)
-      visit (VECTOR_CST_ELT (t, i));
+    {
+      unsigned int count = vector_cst_encoded_nelts (t);
+      for (unsigned int i = 0; i < count; ++i)
+       visit (VECTOR_CST_ENCODED_ELT (t, i));
+    }
+
+  if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST))
+    for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+      visit (POLY_INT_CST_COEFF (t, i));
 
   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
     {
@@ -1213,7 +1221,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       /* Drop names that were created for anonymous entities.  */
       if (DECL_NAME (t)
          && TREE_CODE (DECL_NAME (t)) == IDENTIFIER_NODE
-         && anon_aggrname_p (DECL_NAME (t)))
+         && IDENTIFIER_ANON_P (DECL_NAME (t)))
        ;
       else
        visit (DECL_NAME (t));
@@ -1239,12 +1247,6 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
          be able to call get_symbol_initial_value.  */
     }
 
-  if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
-    {
-      if (code == TYPE_DECL)
-       visit (DECL_ORIGINAL_TYPE (t));
-    }
-
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
     {
       if (DECL_ASSEMBLER_NAME_SET_P (t))
@@ -1257,12 +1259,10 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       visit (DECL_BIT_FIELD_TYPE (t));
       visit (DECL_BIT_FIELD_REPRESENTATIVE (t));
       visit (DECL_FIELD_BIT_OFFSET (t));
-      visit (DECL_FCONTEXT (t));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     {
-      visit (DECL_VINDEX (t));
       visit (DECL_FUNCTION_PERSONALITY (t));
       visit (DECL_FUNCTION_SPECIFIC_TARGET (t));
       visit (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t));
@@ -1279,7 +1279,6 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
        ;
       else
        visit (TYPE_CONTEXT (t));
-      visit (TYPE_STUB_DECL (t));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
@@ -1312,7 +1311,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
 
   if (CODE_CONTAINS_STRUCT (code, TS_EXP))
     {
-      hstate.add_wide_int (TREE_OPERAND_LENGTH (t));
+      hstate.add_hwi (TREE_OPERAND_LENGTH (t));
       for (int i = 0; i < TREE_OPERAND_LENGTH (t); ++i)
        visit (TREE_OPERAND (t, i));
     }
@@ -1325,18 +1324,16 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
        visit (b);
       visit (BINFO_OFFSET (t));
       visit (BINFO_VTABLE (t));
-      visit (BINFO_VPTR_FIELD (t));
-      FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (t), i, b)
-       visit (b);
       /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX
-        and BINFO_VPTR_INDEX; these are used by C++ FE only.  */
+        BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used
+        by C++ FE only.  */
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR))
     {
       unsigned i;
       tree index, value;
-      hstate.add_wide_int (CONSTRUCTOR_NELTS (t));
+      hstate.add_hwi (CONSTRUCTOR_NELTS (t));
       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, index, value)
        {
          visit (index);
@@ -1349,7 +1346,7 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
       int i;
       HOST_WIDE_INT val;
 
-      hstate.add_wide_int (OMP_CLAUSE_CODE (t));
+      hstate.add_hwi (OMP_CLAUSE_CODE (t));
       switch (OMP_CLAUSE_CODE (t))
        {
        case OMP_CLAUSE_DEFAULT:
@@ -1368,13 +1365,15 @@ hash_tree (struct streamer_tree_cache_d *cache, hash_map<tree, hashval_t> *map,
          val = OMP_CLAUSE_PROC_BIND_KIND (t);
          break;
        case OMP_CLAUSE_REDUCTION:
+       case OMP_CLAUSE_TASK_REDUCTION:
+       case OMP_CLAUSE_IN_REDUCTION:
          val = OMP_CLAUSE_REDUCTION_CODE (t);
          break;
        default:
          val = 0;
          break;
        }
-      hstate.add_wide_int (val);
+      hstate.add_hwi (val);
       for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++)
        visit (OMP_CLAUSE_OPERAND (t, i));
       visit (OMP_CLAUSE_CHAIN (t));
@@ -1625,6 +1624,13 @@ lto_output_tree (struct output_block *ob, tree expr,
         we stream out.  */
       gcc_assert (!in_dfs_walk);
 
+      if (streamer_dump_file)
+       {
+         print_node_brief (streamer_dump_file, "   Streaming SCC of ",
+                           expr, 4);
+          fprintf (streamer_dump_file, "\n");
+       }
+
       /* Start the DFS walk.  */
       /* Save ob state ... */
       /* let's see ... */
@@ -1641,6 +1647,12 @@ lto_output_tree (struct output_block *ob, tree expr,
       streamer_write_uhwi (ob, ix);
       streamer_write_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS,
                           lto_tree_code_to_tag (TREE_CODE (expr)));
+      if (streamer_dump_file)
+       {
+         print_node_brief (streamer_dump_file, "   Finished SCC of ",
+                           expr, 4);
+          fprintf (streamer_dump_file, "\n\n");
+       }
       lto_stats.num_pickle_refs_output++;
     }
 }
@@ -1889,7 +1901,7 @@ output_cfg (struct output_block *ob, struct function *fn)
 
   streamer_write_hwi (ob, -1);
 
-  bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+  bb = ENTRY_BLOCK_PTR_FOR_FN (fn);
   while (bb->next_bb)
     {
       streamer_write_hwi (ob, bb->next_bb->index);
@@ -1898,16 +1910,13 @@ output_cfg (struct output_block *ob, struct function *fn)
 
   streamer_write_hwi (ob, -1);
 
-  /* ???  The cfgloop interface is tied to cfun.  */
-  gcc_assert (cfun == fn);
-
   /* Output the number of loops.  */
   streamer_write_uhwi (ob, number_of_loops (fn));
 
   /* Output each loop, skipping the tree root which has number zero.  */
   for (unsigned i = 1; i < number_of_loops (fn); ++i)
     {
-      struct loop *loop = get_loop (fn, i);
+      class loop *loop = get_loop (fn, i);
 
       /* Write the index of the loop header.  That's enough to rebuild
          the loop tree on the reader side.  Stream -1 for an unused
@@ -1935,6 +1944,8 @@ output_cfg (struct output_block *ob, struct function *fn)
 
       /* Write OMP SIMD related info.  */
       streamer_write_hwi (ob, loop->safelen);
+      streamer_write_hwi (ob, loop->unroll);
+      streamer_write_hwi (ob, loop->owned_clique);
       streamer_write_hwi (ob, loop->dont_vectorize);
       streamer_write_hwi (ob, loop->force_vectorize);
       stream_write_tree (ob, loop->simduid, true);
@@ -1957,10 +1968,12 @@ produce_asm (struct output_block *ob, tree fn)
   if (section_type == LTO_section_function_body)
     {
       const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn));
-      section_name = lto_get_section_name (section_type, name, NULL);
+      section_name = lto_get_section_name (section_type, name,
+                                          symtab_node::get (fn)->order,
+                                          NULL);
     }
   else
-    section_name = lto_get_section_name (section_type, NULL, NULL);
+    section_name = lto_get_section_name (section_type, NULL, 0, NULL);
 
   lto_begin_section (section_name, !flag_wpa);
   free (section_name);
@@ -1968,10 +1981,6 @@ produce_asm (struct output_block *ob, tree fn)
   /* The entire header is stream computed here.  */
   memset (&header, 0, sizeof (struct lto_function_header));
 
-  /* Write the header.  */
-  header.major_version = LTO_major_version;
-  header.minor_version = LTO_minor_version;
-
   if (section_type == LTO_section_function_body)
     header.cfg_size = ob->cfg_stream->total_size;
   header.main_size = ob->main_stream->total_size;
@@ -2025,6 +2034,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
   bp_pack_value (&bp, fn->has_forced_label_in_static, 1);
   bp_pack_value (&bp, fn->calls_alloca, 1);
   bp_pack_value (&bp, fn->calls_setjmp, 1);
+  bp_pack_value (&bp, fn->calls_eh_return, 1);
   bp_pack_value (&bp, fn->has_force_vectorize_loops, 1);
   bp_pack_value (&bp, fn->has_simduid_loops, 1);
   bp_pack_value (&bp, fn->va_list_fpr_size, 8);
@@ -2035,6 +2045,14 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
   stream_output_location (ob, &bp, fn->function_start_locus);
   stream_output_location (ob, &bp, fn->function_end_locus);
 
+  /* Save the instance discriminator if present.  */
+  int *instance_number_p = NULL;
+  if (decl_to_instance_map)
+    instance_number_p = decl_to_instance_map->get (fn->decl);
+  bp_pack_value (&bp, !!instance_number_p, 1);
+  if (instance_number_p)
+    bp_pack_value (&bp, *instance_number_p, sizeof (int) * CHAR_BIT);
+
   streamer_write_bitpack (&bp);
 }
 
@@ -2051,6 +2069,62 @@ collect_block_tree_leafs (tree root, vec<tree> &leafs)
       collect_block_tree_leafs (BLOCK_SUBBLOCKS (root), leafs);
 }
 
+/* This performs function body modifications that are needed for streaming
+   to work.  */
+
+void
+lto_prepare_function_for_streaming (struct cgraph_node *node)
+{
+  struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
+  basic_block bb;
+
+  if (number_of_loops (fn))
+    {
+      push_cfun (fn);
+      loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+      loop_optimizer_finalize ();
+      pop_cfun ();
+    }
+  /* We will renumber the statements.  The code that does this uses
+     the same ordering that we use for serializing them so we can use
+     the same code on the other end and not have to write out the
+     statement numbers.  We do not assign UIDs to PHIs here because
+     virtual PHIs get re-computed on-the-fly which would make numbers
+     inconsistent.  */
+  set_gimple_stmt_max_uid (fn, 0);
+  FOR_ALL_BB_FN (bb, fn)
+    {
+      for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+          gsi_next (&gsi))
+       {
+         gphi *stmt = gsi.phi ();
+
+         /* Virtual PHIs are not going to be streamed.  */
+         if (!virtual_operand_p (gimple_phi_result (stmt)))
+           gimple_set_uid (stmt, inc_gimple_stmt_max_uid (fn));
+       }
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+          gsi_next (&gsi))
+       {
+         gimple *stmt = gsi_stmt (gsi);
+         gimple_set_uid (stmt, inc_gimple_stmt_max_uid (fn));
+       }
+    }
+  /* To avoid keeping duplicate gimple IDs in the statements, renumber
+     virtual phis now.  */
+  FOR_ALL_BB_FN (bb, fn)
+    {
+      for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+          gsi_next (&gsi))
+       {
+         gphi *stmt = gsi.phi ();
+         if (virtual_operand_p (gimple_phi_result (stmt)))
+           gimple_set_uid (stmt, inc_gimple_stmt_max_uid (fn));
+       }
+    }
+
+}
+
 /* Output the body of function NODE->DECL.  */
 
 static void
@@ -2061,6 +2135,10 @@ output_function (struct cgraph_node *node)
   basic_block bb;
   struct output_block *ob;
 
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "\nStreaming body of %s\n",
+            node->name ());
+
   function = node->decl;
   fn = DECL_STRUCT_FUNCTION (function);
   ob = create_output_block (LTO_section_function_body);
@@ -2070,9 +2148,6 @@ output_function (struct cgraph_node *node)
 
   gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
 
-  /* Set current_function_decl and cfun.  */
-  push_cfun (fn);
-
   /* Make string 0 be a NULL string.  */
   streamer_write_char_stream (ob->string_stream, 0);
 
@@ -2118,45 +2193,6 @@ output_function (struct cgraph_node *node)
       /* Output any exception handling regions.  */
       output_eh_regions (ob, fn);
 
-
-      /* We will renumber the statements.  The code that does this uses
-        the same ordering that we use for serializing them so we can use
-        the same code on the other end and not have to write out the
-        statement numbers.  We do not assign UIDs to PHIs here because
-        virtual PHIs get re-computed on-the-fly which would make numbers
-        inconsistent.  */
-      set_gimple_stmt_max_uid (cfun, 0);
-      FOR_ALL_BB_FN (bb, cfun)
-       {
-         for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
-              gsi_next (&gsi))
-           {
-             gphi *stmt = gsi.phi ();
-
-             /* Virtual PHIs are not going to be streamed.  */
-             if (!virtual_operand_p (gimple_phi_result (stmt)))
-               gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
-           }
-         for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
-              gsi_next (&gsi))
-           {
-             gimple *stmt = gsi_stmt (gsi);
-             gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
-           }
-       }
-      /* To avoid keeping duplicate gimple IDs in the statements, renumber
-        virtual phis now.  */
-      FOR_ALL_BB_FN (bb, cfun)
-       {
-         for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
-              gsi_next (&gsi))
-           {
-             gphi *stmt = gsi.phi ();
-             if (virtual_operand_p (gimple_phi_result (stmt)))
-               gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
-           }
-       }
-
       /* Output the code for the function.  */
       FOR_ALL_BB_FN (bb, fn)
        output_bb (ob, bb, fn);
@@ -2165,8 +2201,6 @@ output_function (struct cgraph_node *node)
       streamer_write_record_start (ob, LTO_null);
 
       output_cfg (ob, fn);
-
-      pop_cfun ();
    }
   else
     streamer_write_uhwi (ob, 0);
@@ -2175,6 +2209,9 @@ output_function (struct cgraph_node *node)
   produce_asm (ob, function);
 
   destroy_output_block (ob);
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "Finished streaming %s\n",
+            node->name ());
 }
 
 /* Output the body of function NODE->DECL.  */
@@ -2185,6 +2222,11 @@ output_constructor (struct varpool_node *node)
   tree var = node->decl;
   struct output_block *ob;
 
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "\nStreaming constructor of %s\n",
+            node->name ());
+
+  timevar_push (TV_IPA_LTO_CTORS_OUT);
   ob = create_output_block (LTO_section_function_body);
 
   clear_line_info (ob);
@@ -2201,6 +2243,10 @@ output_constructor (struct varpool_node *node)
   produce_asm (ob, var);
 
   destroy_output_block (ob);
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "Finished streaming %s\n",
+            node->name ());
+  timevar_pop (TV_IPA_LTO_CTORS_OUT);
 }
 
 
@@ -2230,17 +2276,13 @@ lto_output_toplevel_asms (void)
 
   streamer_write_string_cst (ob, ob->main_stream, NULL_TREE);
 
-  section_name = lto_get_section_name (LTO_section_asm, NULL, NULL);
+  section_name = lto_get_section_name (LTO_section_asm, NULL, 0, NULL);
   lto_begin_section (section_name, !flag_wpa);
   free (section_name);
 
   /* The entire header stream is computed here.  */
   memset (&header, 0, sizeof (header));
 
-  /* Write the header.  */
-  header.major_version = LTO_major_version;
-  header.minor_version = LTO_minor_version;
-
   header.main_size = ob->main_stream->total_size;
   header.string_size = ob->string_stream->total_size;
   lto_write_data (&header, sizeof header);
@@ -2267,11 +2309,13 @@ copy_function_or_variable (struct symtab_node *node)
   size_t len;
   const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function));
   char *section_name =
-    lto_get_section_name (LTO_section_function_body, name, NULL);
+    lto_get_section_name (LTO_section_function_body, name, node->order, NULL);
   size_t i, j;
   struct lto_in_decl_state *in_state;
   struct lto_out_decl_state *out_state = lto_get_out_decl_state ();
 
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "Copying section for %s\n", name);
   lto_begin_section (section_name, false);
   free (section_name);
 
@@ -2279,7 +2323,8 @@ copy_function_or_variable (struct symtab_node *node)
   name = lto_get_decl_name_mapping (file_data, name);
 
   data = lto_get_raw_section_data (file_data, LTO_section_function_body,
-                                   name, &len);
+                                  name, node->order - file_data->order_base,
+                                  &len);
   gcc_assert (data);
 
   /* Do a bit copy of the function body.  */
@@ -2336,6 +2381,82 @@ wrap_refs (tree *tp, int *ws, void *)
   return NULL_TREE;
 }
 
+/* Remove functions that are no longer used from offload_funcs, and mark the
+   remaining ones with DECL_PRESERVE_P.  */
+
+static void
+prune_offload_funcs (void)
+{
+  if (!offload_funcs)
+    return;
+
+  unsigned ix, ix2;
+  tree *elem_ptr;
+  VEC_ORDERED_REMOVE_IF (*offload_funcs, ix, ix2, elem_ptr,
+                        cgraph_node::get (*elem_ptr) == NULL);
+
+  tree fn_decl;
+  FOR_EACH_VEC_ELT (*offload_funcs, ix, fn_decl)
+    DECL_PRESERVE_P (fn_decl) = 1;
+}
+
+/* Produce LTO section that contains global information
+   about LTO bytecode.  */
+
+static void
+produce_lto_section ()
+{
+  /* Stream LTO meta section.  */
+  output_block *ob = create_output_block (LTO_section_lto);
+
+  char * section_name = lto_get_section_name (LTO_section_lto, NULL, 0, NULL);
+  lto_begin_section (section_name, false);
+  free (section_name);
+
+#ifdef HAVE_ZSTD_H
+  lto_compression compression = ZSTD;
+#else
+  lto_compression compression = ZLIB;
+#endif
+
+  bool slim_object = flag_generate_lto && !flag_fat_lto_objects;
+  lto_section s
+    = { LTO_major_version, LTO_minor_version, slim_object, 0 };
+  s.set_compression (compression);
+  lto_write_data (&s, sizeof s);
+  lto_end_section ();
+  destroy_output_block (ob);
+}
+
+/* Compare symbols to get them sorted by filename (to optimize streaming)  */
+
+static int
+cmp_symbol_files (const void *pn1, const void *pn2)
+{
+  const symtab_node *n1 = *(const symtab_node * const *)pn1;
+  const symtab_node *n2 = *(const symtab_node * const *)pn2;
+
+  int file_order1 = n1->lto_file_data ? n1->lto_file_data->order : -1;
+  int file_order2 = n2->lto_file_data ? n2->lto_file_data->order : -1;
+
+  /* Order files same way as they appeared in the command line to reduce
+     seeking while copying sections.  */
+  if (file_order1 != file_order2)
+    return file_order1 - file_order2;
+
+  /* Order within static library.  */
+  if (n1->lto_file_data && n1->lto_file_data->id != n2->lto_file_data->id)
+    {
+      if (n1->lto_file_data->id > n2->lto_file_data->id)
+       return 1;
+      if (n1->lto_file_data->id < n2->lto_file_data->id)
+       return -1;
+    }
+
+  /* And finaly order by the definition order.  */
+  return n1->order - n2->order;
+}
+
 /* Main entry point from the pass manager.  */
 
 void
@@ -2343,44 +2464,36 @@ lto_output (void)
 {
   struct lto_out_decl_state *decl_state;
   bitmap output = NULL;
-  int i, n_nodes;
+  bitmap_obstack output_obstack;
+  unsigned int i, n_nodes;
   lto_symtab_encoder_t encoder = lto_get_out_decl_state ()->symtab_node_encoder;
+  auto_vec<symtab_node *> symbols_to_copy;
+
+  prune_offload_funcs ();
 
   if (flag_checking)
-    output = lto_bitmap_alloc ();
+    {
+      bitmap_obstack_initialize (&output_obstack);
+      output = BITMAP_ALLOC (&output_obstack);
+    }
 
   /* Initialize the streamer.  */
   lto_streamer_init ();
 
+  produce_lto_section ();
+
   n_nodes = lto_symtab_encoder_size (encoder);
-  /* Process only the functions with bodies.  */
+  /* Prepare vector of functions to output and then sort it to optimize
+     section copying.  */
   for (i = 0; i < n_nodes; i++)
     {
       symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
+      if (snode->alias)
+       continue;
       if (cgraph_node *node = dyn_cast <cgraph_node *> (snode))
        {
-         if (lto_symtab_encoder_encode_body_p (encoder, node)
-             && !node->alias
-             && (!node->thunk.thunk_p || !node->thunk.add_pointer_bounds_args))
-           {
-             if (flag_checking)
-               {
-                 gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
-                 bitmap_set_bit (output, DECL_UID (node->decl));
-               }
-             decl_state = lto_new_out_decl_state ();
-             lto_push_out_decl_state (decl_state);
-             if (gimple_has_body_p (node->decl) || !flag_wpa
-                 /* Thunks have no body but they may be synthetized
-                    at WPA time.  */
-                 || DECL_ARGUMENTS (node->decl))
-               output_function (node);
-             else
-               copy_function_or_variable (node);
-             gcc_assert (lto_get_out_decl_state () == decl_state);
-             lto_pop_out_decl_state ();
-             lto_record_function_out_decl_state (node->decl, decl_state);
-           }
+         if (lto_symtab_encoder_encode_body_p (encoder, node))
+           symbols_to_copy.safe_push (node);
        }
       else if (varpool_node *node = dyn_cast <varpool_node *> (snode))
        {
@@ -2390,29 +2503,42 @@ lto_output (void)
          if (ctor && !in_lto_p)
            walk_tree (&ctor, wrap_refs, NULL, NULL);
          if (get_symbol_initial_value (encoder, node->decl) == error_mark_node
-             && lto_symtab_encoder_encode_initializer_p (encoder, node)
-             && !node->alias)
-           {
-             timevar_push (TV_IPA_LTO_CTORS_OUT);
-             if (flag_checking)
-               {
-                 gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl)));
-                 bitmap_set_bit (output, DECL_UID (node->decl));
-               }
-             decl_state = lto_new_out_decl_state ();
-             lto_push_out_decl_state (decl_state);
-             if (DECL_INITIAL (node->decl) != error_mark_node
-                 || !flag_wpa)
-               output_constructor (node);
-             else
-               copy_function_or_variable (node);
-             gcc_assert (lto_get_out_decl_state () == decl_state);
-             lto_pop_out_decl_state ();
-             lto_record_function_out_decl_state (node->decl, decl_state);
-             timevar_pop (TV_IPA_LTO_CTORS_OUT);
-           }
+             && lto_symtab_encoder_encode_initializer_p (encoder, node))
+           symbols_to_copy.safe_push (node);
        }
     }
+  symbols_to_copy.qsort (cmp_symbol_files);
+  for (i = 0; i < symbols_to_copy.length (); i++)
+    {
+      symtab_node *snode = symbols_to_copy[i];
+      cgraph_node *cnode;
+      varpool_node *vnode;
+
+      if (flag_checking)
+       gcc_assert (bitmap_set_bit (output, DECL_UID (snode->decl)));
+
+      decl_state = lto_new_out_decl_state ();
+      lto_push_out_decl_state (decl_state);
+
+      if ((cnode = dyn_cast <cgraph_node *> (snode))
+         && (gimple_has_body_p (cnode->decl)
+             || (!flag_wpa
+                 && flag_incremental_link != INCREMENTAL_LINK_LTO)
+             /* Thunks have no body but they may be synthetized
+                at WPA time.  */
+             || DECL_ARGUMENTS (cnode->decl)))
+       output_function (cnode);
+      else if ((vnode = dyn_cast <varpool_node *> (snode))
+              && (DECL_INITIAL (vnode->decl) != error_mark_node
+                  || (!flag_wpa
+                      && flag_incremental_link != INCREMENTAL_LINK_LTO)))
+       output_constructor (vnode);
+      else
+       copy_function_or_variable (snode);
+      gcc_assert (lto_get_out_decl_state () == decl_state);
+      lto_pop_out_decl_state ();
+      lto_record_function_out_decl_state (snode->decl, decl_state);
+    }
 
   /* Emit the callgraph after emitting function bodies.  This needs to
      be done now to make sure that all the statements in every function
@@ -2422,9 +2548,11 @@ lto_output (void)
 
   output_offload_tables ();
 
-#if CHECKING_P
-  lto_bitmap_free (output);
-#endif
+  if (flag_checking)
+    {
+      BITMAP_FREE (output);
+      bitmap_obstack_release (&output_obstack);
+    }
 }
 
 /* Write each node in encoded by ENCODER to OB, as well as those reachable
@@ -2446,6 +2574,12 @@ write_global_stream (struct output_block *ob,
   for (index = 0; index < size; index++)
     {
       t = lto_tree_ref_encoder_get_tree (encoder, index);
+      if (streamer_dump_file)
+       {
+          fprintf (streamer_dump_file, " %i:", (int)index);
+         print_node_brief (streamer_dump_file, "", t, 4);
+          fprintf (streamer_dump_file, "\n");
+       }
       if (!streamer_tree_cache_lookup (ob->writer_cache, t, NULL))
        stream_write_tree (ob, t, false);
     }
@@ -2556,14 +2690,6 @@ write_symbol (struct streamer_tree_cache_d *cache,
   const char *comdat;
   unsigned char c;
 
-  /* None of the following kinds of symbols are needed in the
-     symbol table.  */
-  if (!TREE_PUBLIC (t)
-      || is_builtin_fn (t)
-      || DECL_ABSTRACT_P (t)
-      || (VAR_P (t) && DECL_HARD_REGISTER (t)))
-    return;
-
   gcc_assert (VAR_OR_FUNCTION_DECL_P (t));
 
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
@@ -2650,45 +2776,6 @@ write_symbol (struct streamer_tree_cache_d *cache,
   lto_write_data (&slot_num, 4);
 }
 
-/* Return true if NODE should appear in the plugin symbol table.  */
-
-bool
-output_symbol_p (symtab_node *node)
-{
-  struct cgraph_node *cnode;
-  if (!node->real_symbol_p ())
-    return false;
-  /* We keep external functions in symtab for sake of inlining
-     and devirtualization.  We do not want to see them in symbol table as
-     references unless they are really used.  */
-  cnode = dyn_cast <cgraph_node *> (node);
-  if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl))
-      && cnode->callers)
-    return true;
-
- /* Ignore all references from external vars initializers - they are not really
-    part of the compilation unit until they are used by folding.  Some symbols,
-    like references to external construction vtables can not be referred to at all.
-    We decide this at can_refer_decl_in_current_unit_p.  */
- if (!node->definition || DECL_EXTERNAL (node->decl))
-    {
-      int i;
-      struct ipa_ref *ref;
-      for (i = 0; node->iterate_referring (i, ref); i++)
-       {
-         if (ref->use == IPA_REF_ALIAS)
-           continue;
-          if (is_a <cgraph_node *> (ref->referring))
-           return true;
-         if (!DECL_EXTERNAL (ref->referring->decl))
-           return true;
-       }
-      return false;
-    }
-  return true;
-}
-
-
 /* Write an IL symbol table to OB.
    SET and VSET are cgraph/varpool node sets we are outputting.  */
 
@@ -2696,7 +2783,7 @@ static void
 produce_symtab (struct output_block *ob)
 {
   struct streamer_tree_cache_d *cache = ob->writer_cache;
-  char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL);
+  char *section_name = lto_get_section_name (LTO_section_symtab, NULL, 0, NULL);
   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
   lto_symtab_encoder_iterator lsei;
 
@@ -2713,7 +2800,7 @@ produce_symtab (struct output_block *ob)
     {
       symtab_node *node = lsei_node (lsei);
 
-      if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl))
+      if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
        continue;
       write_symbol (cache, node->decl, &seen, false);
     }
@@ -2722,7 +2809,7 @@ produce_symtab (struct output_block *ob)
     {
       symtab_node *node = lsei_node (lsei);
 
-      if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl))
+      if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ())
        continue;
       write_symbol (cache, node->decl, &seen, false);
     }
@@ -2769,10 +2856,10 @@ lto_write_mode_table (void)
            continue;
          bp_pack_value (&bp, m, 8);
          bp_pack_enum (&bp, mode_class, MAX_MODE_CLASS, GET_MODE_CLASS (m));
-         bp_pack_value (&bp, GET_MODE_SIZE (m), 8);
-         bp_pack_value (&bp, GET_MODE_PRECISION (m), 16);
+         bp_pack_poly_value (&bp, GET_MODE_SIZE (m), 16);
+         bp_pack_poly_value (&bp, GET_MODE_PRECISION (m), 16);
          bp_pack_value (&bp, GET_MODE_INNER (m), 8);
-         bp_pack_value (&bp, GET_MODE_NUNITS (m), 8);
+         bp_pack_poly_value (&bp, GET_MODE_NUNITS (m), 16);
          switch (GET_MODE_CLASS (m))
            {
            case MODE_FRACT:
@@ -2796,7 +2883,7 @@ lto_write_mode_table (void)
   streamer_write_bitpack (&bp);
 
   char *section_name
-    = lto_get_section_name (LTO_section_mode_table, NULL, NULL);
+    = lto_get_section_name (LTO_section_mode_table, NULL, 0, NULL);
   lto_begin_section (section_name, !flag_wpa);
   free (section_name);
 
@@ -2804,10 +2891,6 @@ lto_write_mode_table (void)
   struct lto_simple_header_with_strings header;
   memset (&header, 0, sizeof (header));
 
-  /* Write the header.  */
-  header.major_version = LTO_major_version;
-  header.minor_version = LTO_minor_version;
-
   header.main_size = ob->main_stream->total_size;
   header.string_size = ob->string_stream->total_size;
   lto_write_data (&header, sizeof header);
@@ -2844,7 +2927,7 @@ produce_asm_for_decls (void)
 
   memset (&header, 0, sizeof (struct lto_decl_header));
 
-  section_name = lto_get_section_name (LTO_section_decls, NULL, NULL);
+  section_name = lto_get_section_name (LTO_section_decls, NULL, 0, NULL);
   lto_begin_section (section_name, !flag_wpa);
   free (section_name);
 
@@ -2863,18 +2946,21 @@ produce_asm_for_decls (void)
       }
 
   /* Write the global symbols.  */
+  if (streamer_dump_file)
+    fprintf (streamer_dump_file, "Outputting global stream\n");
   lto_output_decl_state_streams (ob, out_state);
   num_fns = lto_function_decl_states.length ();
   for (idx = 0; idx < num_fns; idx++)
     {
       fn_out_state =
        lto_function_decl_states[idx];
+      if (streamer_dump_file)
+        fprintf (streamer_dump_file, "Outputting stream for %s\n",
+                IDENTIFIER_POINTER
+                   (DECL_ASSEMBLER_NAME (fn_out_state->fn_decl)));
       lto_output_decl_state_streams (ob, fn_out_state);
     }
 
-  header.major_version = LTO_major_version;
-  header.minor_version = LTO_minor_version;
-
   /* Currently not used.  This field would allow us to preallocate
      the globals vector, so that it need not be resized as it is extended.  */
   header.num_nodes = -1;