openmp: Add support for the OpenMP 5.0 task detach clause
[gcc.git] / gcc / lto-cgraph.c
index 67a9024ab28b94c0b1932d66901810898ea4d9cf..7c3e276a8eaf44e4be62270cde4ec0a3ba54beef 100644 (file)
@@ -1,7 +1,7 @@
 /* Write and read the cgraph to the memory mapped representation of a
    .o file.
 
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2021 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
 
 This file is part of GCC.
@@ -36,8 +36,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "context.h"
 #include "pass_manager.h"
 #include "ipa-utils.h"
-#include "omp-low.h"
-#include "ipa-chkp.h"
+#include "omp-offload.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "alloc-pool.h"
+#include "symbol-summary.h"
+#include "symtab-thunks.h"
+#include "symtab-clones.h"
 
 /* True when asm nodes has been output.  */
 bool asm_nodes_output = false;
@@ -48,9 +53,6 @@ static void input_cgraph_opt_summary (vec<symtab_node *>  nodes);
 /* Number of LDPR values known to GCC.  */
 #define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1)
 
-/* All node orders are ofsetted by ORDER_BASE.  */
-static int order_base;
-
 /* Cgraph streaming is organized as set of record whose type
    is indicated by a tag.  */
 enum LTO_symtab_tags
@@ -256,18 +258,21 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
       streamer_write_hwi_stream (ob->main_stream, ref);
     }
 
-  streamer_write_gcov_count_stream (ob->main_stream, edge->count);
+  edge->count.stream_out (ob->main_stream);
 
   bp = bitpack_create (ob->main_stream);
-  uid = (!gimple_has_body_p (edge->caller->decl)
-        ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt) + 1);
+  uid = !edge->call_stmt ? edge->lto_stmt_uid
+                        : gimple_uid (edge->call_stmt) + 1;
   bp_pack_enum (&bp, cgraph_inline_failed_t,
                CIF_N_REASONS, edge->inline_failed);
+  gcc_checking_assert (uid || edge->caller->thunk);
   bp_pack_var_len_unsigned (&bp, uid);
-  bp_pack_var_len_unsigned (&bp, edge->frequency);
+  bp_pack_value (&bp, edge->speculative_id, 16);
   bp_pack_value (&bp, edge->indirect_inlining_edge, 1);
   bp_pack_value (&bp, edge->speculative, 1);
   bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1);
+  gcc_assert (!edge->call_stmt_cannot_inline_p
+             || edge->inline_failed != CIF_BODY_NOT_AVAILABLE);
   bp_pack_value (&bp, edge->can_throw_external, 1);
   bp_pack_value (&bp, edge->in_polymorphic_cdtor, 1);
   if (edge->indirect_unknown_callee)
@@ -285,16 +290,11 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
                             | ECF_SIBCALL
                             | ECF_LEAF
                             | ECF_NOVOPS)));
+
+      bp_pack_value (&bp, edge->indirect_info->num_speculative_call_targets,
+                    16);
     }
   streamer_write_bitpack (&bp);
-  if (edge->indirect_unknown_callee)
-    {
-      streamer_write_hwi_stream (ob->main_stream,
-                                edge->indirect_info->common_target_id);
-      if (edge->indirect_info->common_target_id)
-       streamer_write_hwi_stream
-          (ob->main_stream, edge->indirect_info->common_target_probability);
-    }
 }
 
 /* Return if NODE contain references from other partitions.  */
@@ -327,7 +327,7 @@ reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t
   struct cgraph_edge *e;
   if (!node->definition)
     return false;
-  if (node->global.inlined_to)
+  if (node->inlined_to)
     return false;
   for (e = node->callers; e; e = e->next_caller)
     {
@@ -396,7 +396,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
   boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
 
-  if (node->analyzed && (!boundary_p || node->alias || node->thunk.thunk_p))
+  if (node->analyzed && (!boundary_p || node->alias
+                        || (node->thunk && !node->inlined_to)))
     tag = LTO_symtab_analyzed_node;
   else
     tag = LTO_symtab_unavail_node;
@@ -418,8 +419,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   if (boundary_p && node->analyzed
       && node->get_partitioning_class () == SYMBOL_PARTITION)
     {
-      /* Inline clones can not be part of boundary.  
-         gcc_assert (!node->global.inlined_to);  
+      /* Inline clones cannot be part of boundary.  
+        gcc_assert (!node->inlined_to);
 
         FIXME: At the moment they can be, when partition contains an inline
         clone that is clone of inline clone from outside partition.  We can
@@ -454,8 +455,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
     streamer_write_hwi_stream (ob->main_stream, ref);
 
 
-  lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
-  streamer_write_gcov_count_stream (ob->main_stream, node->count);
+  lto_output_fn_decl_ref (ob->decl_state, ob->main_stream, node->decl);
+  node->count.stream_out (ob->main_stream);
   streamer_write_hwi_stream (ob->main_stream, node->count_materialization_scale);
 
   streamer_write_hwi_stream (ob->main_stream,
@@ -465,9 +466,9 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
   if (tag == LTO_symtab_analyzed_node)
     {
-      if (node->global.inlined_to)
+      if (node->inlined_to)
        {
-         ref = lto_symtab_encoder_lookup (encoder, node->global.inlined_to);
+         ref = lto_symtab_encoder_lookup (encoder, node->inlined_to);
          gcc_assert (ref != LCC_NOT_FOUND);
        }
       else
@@ -485,11 +486,12 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
   if (group)
     {
-      if (node->same_comdat_group && !boundary_p)
+      if (node->same_comdat_group)
        {
-         ref = lto_symtab_encoder_lookup (encoder,
-                                          node->same_comdat_group);
-         gcc_assert (ref != LCC_NOT_FOUND);
+         ref = LCC_NOT_FOUND;
+         for (struct symtab_node *n = node->same_comdat_group; 
+              ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
+           ref = lto_symtab_encoder_lookup (encoder, n);
        }
       else
        ref = LCC_NOT_FOUND;
@@ -503,13 +505,13 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   streamer_write_hwi_stream (ob->main_stream, node->tp_first_run);
 
   bp = bitpack_create (ob->main_stream);
-  bp_pack_value (&bp, node->local.local, 1);
+  bp_pack_value (&bp, node->local, 1);
   bp_pack_value (&bp, node->externally_visible, 1);
   bp_pack_value (&bp, node->no_reorder, 1);
   bp_pack_value (&bp, node->definition, 1);
-  bp_pack_value (&bp, node->local.versionable, 1);
-  bp_pack_value (&bp, node->local.can_change_signature, 1);
-  bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
+  bp_pack_value (&bp, node->versionable, 1);
+  bp_pack_value (&bp, node->can_change_signature, 1);
+  bp_pack_value (&bp, node->redefined_extern_inline, 1);
   bp_pack_value (&bp, node->force_output, 1);
   bp_pack_value (&bp, node->forced_by_abi, 1);
   bp_pack_value (&bp, node->unique_name, 1);
@@ -523,7 +525,9 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bp_pack_value (&bp, node->lowered, 1);
   bp_pack_value (&bp, in_other_partition, 1);
   bp_pack_value (&bp, node->alias, 1);
+  bp_pack_value (&bp, node->transparent_alias, 1);
   bp_pack_value (&bp, node->weakref, 1);
+  bp_pack_value (&bp, node->symver, 1);
   bp_pack_value (&bp, node->frequency, 2);
   bp_pack_value (&bp, node->only_called_at_startup, 1);
   bp_pack_value (&bp, node->only_called_at_exit, 1);
@@ -531,33 +535,39 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bp_pack_value (&bp, node->calls_comdat_local, 1);
   bp_pack_value (&bp, node->icf_merged, 1);
   bp_pack_value (&bp, node->nonfreeing_fn, 1);
-  bp_pack_value (&bp, node->thunk.thunk_p, 1);
+  bp_pack_value (&bp, node->merged_comdat, 1);
+  bp_pack_value (&bp, node->merged_extern_inline, 1);
+  bp_pack_value (&bp, node->thunk, 1);
   bp_pack_value (&bp, node->parallelized_function, 1);
+  bp_pack_value (&bp, node->declare_variant_alt, 1);
+  bp_pack_value (&bp, node->calls_declare_variant_alt, 1);
+
+  /* Stream thunk info always because we use it in
+     ipa_polymorphic_call_context::ipa_polymorphic_call_context
+     to properly interpret THIS pointers for thunks that has been converted
+     to Gimple.  */
+  struct thunk_info *thunk = node->definition ? thunk_info::get (node) : NULL;
+
+  bp_pack_value (&bp, thunk != NULL, 1);
+
   bp_pack_enum (&bp, ld_plugin_symbol_resolution,
-               LDPR_NUM_KNOWN, node->resolution);
-  bp_pack_value (&bp, node->instrumentation_clone, 1);
+               LDPR_NUM_KNOWN,
+               /* When doing incremental link, we will get new resolution
+                  info next time we process the file.  */
+               flag_incremental_link ? LDPR_UNKNOWN : node->resolution);
   bp_pack_value (&bp, node->split_part, 1);
   streamer_write_bitpack (&bp);
   streamer_write_data_stream (ob->main_stream, section, strlen (section) + 1);
 
-  if (node->thunk.thunk_p)
-    {
-      streamer_write_uhwi_stream
-        (ob->main_stream,
-         1 + (node->thunk.this_adjusting != 0) * 2
-         + (node->thunk.virtual_offset_p != 0) * 4
-         + (node->thunk.add_pointer_bounds_args != 0) * 8);
-      streamer_write_uhwi_stream (ob->main_stream, node->thunk.fixed_offset);
-      streamer_write_uhwi_stream (ob->main_stream, node->thunk.virtual_value);
-    }
   streamer_write_hwi_stream (ob->main_stream, node->profile_id);
+  streamer_write_hwi_stream (ob->main_stream, node->unit_id);
   if (DECL_STATIC_CONSTRUCTOR (node->decl))
     streamer_write_hwi_stream (ob->main_stream, node->get_init_priority ());
   if (DECL_STATIC_DESTRUCTOR (node->decl))
     streamer_write_hwi_stream (ob->main_stream, node->get_fini_priority ());
 
-  if (node->instrumentation_clone)
-    lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->orig_decl);
+  if (thunk)
+    thunk_info::get (node)->stream_out (ob);
 }
 
 /* Output the varpool NODE to OB. 
@@ -583,7 +593,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
   streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
                       LTO_symtab_variable);
   streamer_write_hwi_stream (ob->main_stream, node->order);
-  lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
+  lto_output_var_decl_ref (ob->decl_state, ob->main_stream, node->decl);
   bp = bitpack_create (ob->main_stream);
   bp_pack_value (&bp, node->externally_visible, 1);
   bp_pack_value (&bp, node->no_reorder, 1);
@@ -599,8 +609,10 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
   bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
                 1);
   bp_pack_value (&bp, node->alias, 1);
+  bp_pack_value (&bp, node->transparent_alias, 1);
   bp_pack_value (&bp, node->weakref, 1);
-  bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
+  bp_pack_value (&bp, node->symver, 1);
+  bp_pack_value (&bp, node->analyzed && (!boundary_p || node->alias), 1);
   gcc_assert (node->definition || !node->analyzed);
   /* Constant pool initializers can be de-unified into individual ltrans units.
      FIXME: Alternatively at -Os we may want to avoid generating for them the local
@@ -620,7 +632,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
     }
   bp_pack_value (&bp, node->tls_model, 3);
   bp_pack_value (&bp, node->used_by_single_function, 1);
-  bp_pack_value (&bp, node->need_bounds_init, 1);
+  bp_pack_value (&bp, node->dynamically_initialized, 1);
   streamer_write_bitpack (&bp);
 
   group = node->get_comdat_group ();
@@ -632,11 +644,12 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
 
   if (group)
     {
-      if (node->same_comdat_group && !boundary_p)
+      if (node->same_comdat_group)
        {
-         ref = lto_symtab_encoder_lookup (encoder,
-                                          node->same_comdat_group);
-         gcc_assert (ref != LCC_NOT_FOUND);
+         ref = LCC_NOT_FOUND;
+         for (struct symtab_node *n = node->same_comdat_group; 
+              ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
+           ref = lto_symtab_encoder_lookup (encoder, n);
        }
       else
        ref = LCC_NOT_FOUND;
@@ -661,7 +674,7 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
 {
   struct bitpack_d bp;
   int nref;
-  int uid = ref->lto_stmt_uid;
+  int uid = !ref->stmt ? ref->lto_stmt_uid : gimple_uid (ref->stmt) + 1;
   struct cgraph_node *node;
 
   bp = bitpack_create (ob->main_stream);
@@ -678,6 +691,8 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
       if (ref->stmt)
        uid = gimple_uid (ref->stmt) + 1;
       streamer_write_hwi_stream (ob->main_stream, uid);
+      bp_pack_value (&bp, ref->speculative_id, 16);
+      streamer_write_bitpack (&bp);
     }
 }
 
@@ -686,39 +701,14 @@ lto_output_ref (struct lto_simple_output_block *ob, struct ipa_ref *ref,
 static void
 output_profile_summary (struct lto_simple_output_block *ob)
 {
-  unsigned h_ix;
-  struct bitpack_d bp;
-
   if (profile_info)
     {
       /* We do not output num and run_max, they are not used by
          GCC profile feedback and they are difficult to merge from multiple
          units.  */
-      gcc_assert (profile_info->runs);
-      streamer_write_uhwi_stream (ob->main_stream, profile_info->runs);
-      streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_max);
+      unsigned runs = (profile_info->runs);
+      streamer_write_uhwi_stream (ob->main_stream, runs);
 
-      /* sum_all is needed for computing the working set with the
-         histogram.  */
-      streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_all);
-
-      /* Create and output a bitpack of non-zero histogram entries indices.  */
-      bp = bitpack_create (ob->main_stream);
-      for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
-        bp_pack_value (&bp, profile_info->histogram[h_ix].num_counters > 0, 1);
-      streamer_write_bitpack (&bp);
-      /* Now stream out only those non-zero entries.  */
-      for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
-        {
-          if (!profile_info->histogram[h_ix].num_counters)
-            continue;
-          streamer_write_gcov_count_stream (ob->main_stream,
-                                      profile_info->histogram[h_ix].num_counters);
-          streamer_write_gcov_count_stream (ob->main_stream,
-                                      profile_info->histogram[h_ix].min_value);
-          streamer_write_gcov_count_stream (ob->main_stream,
-                                      profile_info->histogram[h_ix].cum_value);
-         }
       /* IPA-profile computes hot bb threshold based on cumulated
         whole program profile.  We need to stream it down to ltrans.  */
        if (flag_wpa)
@@ -763,33 +753,11 @@ output_refs (lto_symtab_encoder_t encoder)
     {
       symtab_node *node = lto_symtab_encoder_deref (encoder, i);
 
-      /* IPA_REF_ALIAS and IPA_REF_CHKP references are always preserved
+      /* IPA_REF_ALIAS references are always preserved
         in the boundary.  Alias node can't have other references and
         can be always handled as if it's not in the boundary.  */
       if (!node->alias && !lto_symtab_encoder_in_partition_p (encoder, node))
-       {
-         cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
-         /* Output IPA_REF_CHKP reference.  */
-         if (cnode
-             && cnode->instrumented_version
-             && !cnode->instrumentation_clone)
-           {
-             for (int i = 0; node->iterate_reference (i, ref); i++)
-               if (ref->use == IPA_REF_CHKP)
-                 {
-                   if (lto_symtab_encoder_lookup (encoder, ref->referred)
-                       != LCC_NOT_FOUND)
-                     {
-                       int nref = lto_symtab_encoder_lookup (encoder, node);
-                       streamer_write_gcov_count_stream (ob->main_stream, 1);
-                       streamer_write_uhwi_stream (ob->main_stream, nref);
-                       lto_output_ref (ob, ref, encoder);
-                     }
-                   break;
-                 }
-           }
-         continue;
-       }
+       continue;
 
       count = node->ref_list.nreferences ();
       if (count)
@@ -800,6 +768,9 @@ output_refs (lto_symtab_encoder_t encoder)
          for (int i = 0; node->iterate_reference (i, ref); i++)
            lto_output_ref (ob, ref, encoder);
        }
+      if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
+       if (cnode->declare_variant_alt)
+         omp_lto_output_declare_variant_alt (ob, cnode, encoder);
     }
 
   streamer_write_uhwi_stream (ob->main_stream, 0);
@@ -901,8 +872,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
              && (((vnode->ctor_useable_for_folding_p ()
                   && (!DECL_VIRTUAL_P (vnode->decl)
                       || !flag_wpa
-                      || flag_ltrans_devirtualize))
-                 || POINTER_BOUNDS_P (vnode->decl))))
+                      || flag_ltrans_devirtualize)))))
            {
              lto_set_symtab_encoder_encode_initializer (encoder, vnode);
              create_references (encoder, vnode);
@@ -922,7 +892,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
          if (!lto_symtab_encoder_in_partition_p (encoder, callee))
            {
              /* We should have moved all the inlines.  */
-             gcc_assert (!callee->global.inlined_to);
+             gcc_assert (!callee->inlined_to);
              add_node_to (encoder, callee, false);
            }
        }
@@ -949,7 +919,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
                          && !lto_symtab_encoder_in_partition_p
                               (encoder, callee))
                        {
-                         gcc_assert (!callee->global.inlined_to);
+                         gcc_assert (!callee->inlined_to);
                          add_node_to (encoder, callee, false);
                        }
                    }
@@ -966,8 +936,17 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
       if (node->alias && node->analyzed)
        create_references (encoder, node);
       if (cnode
-         && cnode->thunk.thunk_p)
+         && cnode->thunk && !cnode->inlined_to)
        add_node_to (encoder, cnode->callees->callee, false);
+      while (node->transparent_alias && node->analyzed)
+       {
+         node = node->get_alias_target ();
+         if (is_a <cgraph_node *> (node))
+           add_node_to (encoder, dyn_cast <cgraph_node *> (node),
+                        false);
+         else
+           lto_symtab_encoder_encode (encoder, node);
+       }
     }
   lto_symtab_encoder_delete (in_encoder);
   return encoder;
@@ -1013,7 +992,7 @@ output_symtab (void)
     {
       node = dyn_cast <cgraph_node *> (lto_symtab_encoder_deref (encoder, i));
       if (node
-         && (node->thunk.thunk_p
+         && ((node->thunk && !node->inlined_to)
              || lto_symtab_encoder_in_partition_p (encoder, node)))
        {
          output_outgoing_cgraph_edges (node->callees, ob, encoder);
@@ -1041,7 +1020,7 @@ output_symtab (void)
 /* Return identifier encoded in IB as a plain string.  */
 
 static tree
-read_identifier (struct lto_input_block *ib)
+read_identifier (class lto_input_block *ib)
 {
   unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
   tree id;
@@ -1061,7 +1040,7 @@ read_identifier (struct lto_input_block *ib)
 /* Return string encoded in IB, NULL if string is empty.  */
 
 static const char *
-read_string (struct lto_input_block *ib)
+read_string (class lto_input_block *ib)
 {
   unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
   const char *str;
@@ -1095,18 +1074,26 @@ output_offload_tables (void)
 
   for (unsigned i = 0; i < vec_safe_length (offload_funcs); i++)
     {
+      symtab_node *node = symtab_node::get ((*offload_funcs)[i]);
+      if (!node)
+       continue;
+      node->force_output = true;
       streamer_write_enum (ob->main_stream, LTO_symtab_tags,
                           LTO_symtab_last_tag, LTO_symtab_unavail_node);
-      lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
-                               (*offload_funcs)[i]);
+      lto_output_fn_decl_ref (ob->decl_state, ob->main_stream,
+                             (*offload_funcs)[i]);
     }
 
   for (unsigned i = 0; i < vec_safe_length (offload_vars); i++)
     {
+      symtab_node *node = symtab_node::get ((*offload_vars)[i]);
+      if (!node)
+       continue;
+      node->force_output = true;
       streamer_write_enum (ob->main_stream, LTO_symtab_tags,
                           LTO_symtab_last_tag, LTO_symtab_variable);
-      lto_output_var_decl_index (ob->decl_state, ob->main_stream,
-                                (*offload_vars)[i]);
+      lto_output_var_decl_ref (ob->decl_state, ob->main_stream,
+                              (*offload_vars)[i]);
     }
 
   streamer_write_uhwi_stream (ob->main_stream, 0);
@@ -1122,29 +1109,60 @@ output_offload_tables (void)
     }
 }
 
+/* Verify the partitioning of NODE.  */
+
+static inline void
+verify_node_partition (symtab_node *node)
+{
+  if (flag_ltrans)
+    return;
+
+#ifdef ACCEL_COMPILER
+  if (node->in_other_partition)
+    {
+      if (TREE_CODE (node->decl) == FUNCTION_DECL)
+       error_at (DECL_SOURCE_LOCATION (node->decl),
+                 "function %qs has been referenced in offloaded code but"
+                 " hasn%'t been marked to be included in the offloaded code",
+                 node->name ());
+      else if (VAR_P (node->decl))
+       error_at (DECL_SOURCE_LOCATION (node->decl),
+                 "variable %qs has been referenced in offloaded code but"
+                 " hasn%'t been marked to be included in the offloaded code",
+                 node->name ());
+      else
+       gcc_unreachable ();
+    }
+#else
+  gcc_assert (!node->in_other_partition
+             && !node->used_from_other_partition);
+#endif
+}
+
 /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
    STACK_SIZE, SELF_TIME and SELF_SIZE.  This is called either to initialize
    NODE or to replace the values in it, for instance because the first
    time we saw it, the function body was not available but now it
    is.  BP is a bitpack with all the bitflags for NODE read from the
-   stream.  */
+   stream.  Initialize HAS_THUNK_INFO to indicate if thunk info should
+   be streamed in.  */
 
 static void
 input_overwrite_node (struct lto_file_decl_data *file_data,
                      struct cgraph_node *node,
                      enum LTO_symtab_tags tag,
-                     struct bitpack_d *bp)
+                     struct bitpack_d *bp, bool *has_thunk_info)
 {
   node->aux = (void *) tag;
   node->lto_file_data = file_data;
 
-  node->local.local = bp_unpack_value (bp, 1);
+  node->local = bp_unpack_value (bp, 1);
   node->externally_visible = bp_unpack_value (bp, 1);
   node->no_reorder = bp_unpack_value (bp, 1);
   node->definition = bp_unpack_value (bp, 1);
-  node->local.versionable = bp_unpack_value (bp, 1);
-  node->local.can_change_signature = bp_unpack_value (bp, 1);
-  node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
+  node->versionable = bp_unpack_value (bp, 1);
+  node->can_change_signature = bp_unpack_value (bp, 1);
+  node->redefined_extern_inline = bp_unpack_value (bp, 1);
   node->force_output = bp_unpack_value (bp, 1);
   node->forced_by_abi = bp_unpack_value (bp, 1);
   node->unique_name = bp_unpack_value (bp, 1);
@@ -1170,7 +1188,9 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
       TREE_STATIC (node->decl) = 0;
     }
   node->alias = bp_unpack_value (bp, 1);
+  node->transparent_alias = bp_unpack_value (bp, 1);
   node->weakref = bp_unpack_value (bp, 1);
+  node->symver = bp_unpack_value (bp, 1);
   node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
   node->only_called_at_startup = bp_unpack_value (bp, 1);
   node->only_called_at_exit = bp_unpack_value (bp, 1);
@@ -1178,15 +1198,17 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
   node->calls_comdat_local = bp_unpack_value (bp, 1);
   node->icf_merged = bp_unpack_value (bp, 1);
   node->nonfreeing_fn = bp_unpack_value (bp, 1);
-  node->thunk.thunk_p = bp_unpack_value (bp, 1);
+  node->merged_comdat = bp_unpack_value (bp, 1);
+  node->merged_extern_inline = bp_unpack_value (bp, 1);
+  node->thunk = bp_unpack_value (bp, 1);
   node->parallelized_function = bp_unpack_value (bp, 1);
+  node->declare_variant_alt = bp_unpack_value (bp, 1);
+  node->calls_declare_variant_alt = bp_unpack_value (bp, 1);
+  *has_thunk_info = bp_unpack_value (bp, 1);
   node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
                                     LDPR_NUM_KNOWN);
-  node->instrumentation_clone = bp_unpack_value (bp, 1);
   node->split_part = bp_unpack_value (bp, 1);
-  gcc_assert (flag_ltrans
-             || (!node->in_other_partition
-                 && !node->used_from_other_partition));
+  verify_node_partition (node);
 }
 
 /* Return string alias is alias of.  */
@@ -1204,7 +1226,7 @@ get_alias_symbol (tree decl)
 
 static struct cgraph_node *
 input_node (struct lto_file_decl_data *file_data,
-           struct lto_input_block *ib,
+           class lto_input_block *ib,
            enum LTO_symtab_tags tag,
            vec<symtab_node *> nodes)
 {
@@ -1212,23 +1234,22 @@ input_node (struct lto_file_decl_data *file_data,
   tree fn_decl;
   struct cgraph_node *node;
   struct bitpack_d bp;
-  unsigned decl_index;
   int ref = LCC_NOT_FOUND, ref2 = LCC_NOT_FOUND;
   int clone_ref;
   int order;
   int i, count;
   tree group;
   const char *section;
-  order = streamer_read_hwi (ib) + order_base;
+  order = streamer_read_hwi (ib) + file_data->order_base;
   clone_ref = streamer_read_hwi (ib);
+  bool has_thunk_info;
 
-  decl_index = streamer_read_uhwi (ib);
-  fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
+  fn_decl = lto_input_fn_decl_ref (ib, file_data);
 
   if (clone_ref != LCC_NOT_FOUND)
     {
       node = dyn_cast<cgraph_node *> (nodes[clone_ref])->create_clone (fn_decl,
-       0, CGRAPH_FREQ_BASE, false,
+       profile_count::uninitialized (), false,
        vNULL, false, NULL, NULL);
     }
   else
@@ -1238,6 +1259,8 @@ input_node (struct lto_file_decl_data *file_data,
         of ipa passes is done.  Alays forcingly create a fresh node.  */
       node = symtab->create_empty ();
       node->decl = fn_decl;
+      if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (fn_decl)))
+       node->ifunc_resolver = 1;
       node->register_symbol ();
     }
 
@@ -1245,7 +1268,7 @@ input_node (struct lto_file_decl_data *file_data,
   if (order >= symtab->order)
     symtab->order = order + 1;
 
-  node->count = streamer_read_gcov_count (ib);
+  node->count = profile_count::stream_in (ib);
   node->count_materialization_scale = streamer_read_hwi (ib);
 
   count = streamer_read_hwi (ib);
@@ -1271,18 +1294,18 @@ input_node (struct lto_file_decl_data *file_data,
      have already been read will have their tag stored in the 'aux'
      field.  Since built-in functions can be referenced in multiple
      functions, they are expected to be read more than once.  */
-  if (node->aux && !DECL_BUILT_IN (node->decl))
+  if (node->aux && !fndecl_built_in_p (node->decl))
     internal_error ("bytecode stream: found multiple instances of cgraph "
-                   "node with uid %d", node->uid);
+                   "node with uid %d", node->get_uid ());
 
   node->tp_first_run = streamer_read_uhwi (ib);
 
   bp = streamer_read_bitpack (ib);
 
-  input_overwrite_node (file_data, node, tag, &bp);
+  input_overwrite_node (file_data, node, tag, &bp, &has_thunk_info);
 
   /* Store a reference for now, and fix up later to be a pointer.  */
-  node->global.inlined_to = (cgraph_node *) (intptr_t) ref;
+  node->inlined_to = (cgraph_node *) (intptr_t) ref;
 
   if (group)
     {
@@ -1296,32 +1319,19 @@ input_node (struct lto_file_decl_data *file_data,
   if (section)
     node->set_section_for_node (section);
 
-  if (node->thunk.thunk_p)
-    {
-      int type = streamer_read_uhwi (ib);
-      HOST_WIDE_INT fixed_offset = streamer_read_uhwi (ib);
-      HOST_WIDE_INT virtual_value = streamer_read_uhwi (ib);
-
-      node->thunk.fixed_offset = fixed_offset;
-      node->thunk.this_adjusting = (type & 2);
-      node->thunk.virtual_value = virtual_value;
-      node->thunk.virtual_offset_p = (type & 4);
-      node->thunk.add_pointer_bounds_args = (type & 8);
-    }
   if (node->alias && !node->analyzed && node->weakref)
     node->alias_target = get_alias_symbol (node->decl);
   node->profile_id = streamer_read_hwi (ib);
+  node->unit_id = streamer_read_hwi (ib) + file_data->unit_base;
+  if (symtab->max_unit < node->unit_id)
+    symtab->max_unit = node->unit_id;
   if (DECL_STATIC_CONSTRUCTOR (node->decl))
     node->set_init_priority (streamer_read_hwi (ib));
   if (DECL_STATIC_DESTRUCTOR (node->decl))
     node->set_fini_priority (streamer_read_hwi (ib));
 
-  if (node->instrumentation_clone)
-    {
-      decl_index = streamer_read_uhwi (ib);
-      fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
-      node->orig_decl = fn_decl;
-    }
+  if (has_thunk_info)
+    thunk_info::get_create (node)->stream_in (ib);
 
   return node;
 }
@@ -1331,9 +1341,8 @@ input_node (struct lto_file_decl_data *file_data,
 
 static varpool_node *
 input_varpool_node (struct lto_file_decl_data *file_data,
-                   struct lto_input_block *ib)
+                   class lto_input_block *ib)
 {
-  int decl_index;
   tree var_decl;
   varpool_node *node;
   struct bitpack_d bp;
@@ -1342,9 +1351,8 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   tree group;
   const char *section;
 
-  order = streamer_read_hwi (ib) + order_base;
-  decl_index = streamer_read_uhwi (ib);
-  var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
+  order = streamer_read_hwi (ib) + file_data->order_base;
+  var_decl = lto_input_var_decl_ref (ib, file_data);
 
   /* Declaration of functions can be already merged with a declaration
      from other input file.  We keep cgraph unmerged until after streaming
@@ -1369,7 +1377,9 @@ input_varpool_node (struct lto_file_decl_data *file_data,
   node->writeonly = bp_unpack_value (&bp, 1);
   node->definition = bp_unpack_value (&bp, 1);
   node->alias = bp_unpack_value (&bp, 1);
+  node->transparent_alias = bp_unpack_value (&bp, 1);
   node->weakref = bp_unpack_value (&bp, 1);
+  node->symver = bp_unpack_value (&bp, 1);
   node->analyzed = bp_unpack_value (&bp, 1);
   node->used_from_other_partition = bp_unpack_value (&bp, 1);
   node->in_other_partition = bp_unpack_value (&bp, 1);
@@ -1382,7 +1392,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
     node->alias_target = get_alias_symbol (node->decl);
   node->tls_model = (enum tls_model)bp_unpack_value (&bp, 3);
   node->used_by_single_function = (enum tls_model)bp_unpack_value (&bp, 1);
-  node->need_bounds_init = bp_unpack_value (&bp, 1);
+  node->dynamically_initialized = bp_unpack_value (&bp, 1);
   group = read_identifier (ib);
   if (group)
     {
@@ -1398,10 +1408,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
     node->set_section_for_node (section);
   node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
                                                LDPR_NUM_KNOWN);
-  gcc_assert (flag_ltrans
-             || (!node->in_other_partition
-                 && !node->used_from_other_partition));
-
+  verify_node_partition (node);
   return node;
 }
 
@@ -1409,7 +1416,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
    Return the node read or overwriten.  */
 
 static void
-input_ref (struct lto_input_block *ib,
+input_ref (class lto_input_block *ib,
           symtab_node *referring_node,
           vec<symtab_node *> nodes)
 {
@@ -1426,7 +1433,11 @@ input_ref (struct lto_input_block *ib,
   ref = referring_node->create_reference (node, use);
   ref->speculative = speculative;
   if (is_a <cgraph_node *> (referring_node))
-    ref->lto_stmt_uid = streamer_read_hwi (ib);
+    {
+      ref->lto_stmt_uid = streamer_read_hwi (ib);
+      bp = streamer_read_bitpack (ib);
+      ref->speculative_id = bp_unpack_value (&bp, 16);
+    }
 }
 
 /* Read an edge from IB.  NODES points to a vector of previously read nodes for
@@ -1435,14 +1446,13 @@ input_ref (struct lto_input_block *ib,
    indirect_unknown_callee set).  */
 
 static void
-input_edge (struct lto_input_block *ib, vec<symtab_node *> nodes,
+input_edge (class lto_input_block *ib, vec<symtab_node *> nodes,
            bool indirect)
 {
   struct cgraph_node *caller, *callee;
   struct cgraph_edge *edge;
-  unsigned int stmt_id;
-  gcov_type count;
-  int freq;
+  unsigned int stmt_id, speculative_id;
+  profile_count count;
   cgraph_inline_failed_t inline_failed;
   struct bitpack_d bp;
   int ecf_flags = 0;
@@ -1460,21 +1470,22 @@ input_edge (struct lto_input_block *ib, vec<symtab_node *> nodes,
   else
     callee = NULL;
 
-  count = streamer_read_gcov_count (ib);
+  count = profile_count::stream_in (ib);
 
   bp = streamer_read_bitpack (ib);
   inline_failed = bp_unpack_enum (&bp, cgraph_inline_failed_t, CIF_N_REASONS);
   stmt_id = bp_unpack_var_len_unsigned (&bp);
-  freq = (int) bp_unpack_var_len_unsigned (&bp);
+  speculative_id = bp_unpack_value (&bp, 16);
 
   if (indirect)
-    edge = caller->create_indirect_edge (NULL, 0, count, freq);
+    edge = caller->create_indirect_edge (NULL, 0, count);
   else
-    edge = caller->create_edge (callee, NULL, count, freq);
+    edge = caller->create_edge (callee, NULL, count);
 
   edge->indirect_inlining_edge = bp_unpack_value (&bp, 1);
   edge->speculative = bp_unpack_value (&bp, 1);
   edge->lto_stmt_uid = stmt_id;
+  edge->speculative_id = speculative_id;
   edge->inline_failed = inline_failed;
   edge->call_stmt_cannot_inline_p = bp_unpack_value (&bp, 1);
   edge->can_throw_external = bp_unpack_value (&bp, 1);
@@ -1494,9 +1505,9 @@ input_edge (struct lto_input_block *ib, vec<symtab_node *> nodes,
       if (bp_unpack_value (&bp, 1))
        ecf_flags |= ECF_RETURNS_TWICE;
       edge->indirect_info->ecf_flags = ecf_flags;
-      edge->indirect_info->common_target_id = streamer_read_hwi (ib);
-      if (edge->indirect_info->common_target_id)
-        edge->indirect_info->common_target_probability = streamer_read_hwi (ib);
+
+      edge->indirect_info->num_speculative_call_targets
+       = bp_unpack_value (&bp, 16);
     }
 }
 
@@ -1505,7 +1516,7 @@ input_edge (struct lto_input_block *ib, vec<symtab_node *> nodes,
 
 static vec<symtab_node *> 
 input_cgraph_1 (struct lto_file_decl_data *file_data,
-               struct lto_input_block *ib)
+               class lto_input_block *ib)
 {
   enum LTO_symtab_tags tag;
   vec<symtab_node *> nodes = vNULL;
@@ -1513,7 +1524,8 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
   unsigned i;
 
   tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
-  order_base = symtab->order;
+  file_data->order_base = symtab->order;
+  file_data->unit_base = symtab->max_unit + 1;
   while (tag)
     {
       if (tag == LTO_symtab_edge)
@@ -1538,7 +1550,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
       tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
     }
 
-  lto_input_toplevel_asms (file_data, order_base);
+  lto_input_toplevel_asms (file_data, file_data->order_base);
 
   /* AUX pointers should be all non-zero for function nodes read from the stream.  */
   if (flag_checking)
@@ -1551,7 +1563,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
       int ref;
       if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
        {
-         ref = (int) (intptr_t) cnode->global.inlined_to;
+         ref = (int) (intptr_t) cnode->inlined_to;
 
          /* We share declaration of builtins, so we may read same node twice.  */
          if (!node->aux)
@@ -1560,39 +1572,10 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
 
          /* Fixup inlined_to from reference to pointer.  */
          if (ref != LCC_NOT_FOUND)
-           dyn_cast<cgraph_node *> (node)->global.inlined_to
+           dyn_cast<cgraph_node *> (node)->inlined_to
              = dyn_cast<cgraph_node *> (nodes[ref]);
          else
-           cnode->global.inlined_to = NULL;
-
-         /* Compute instrumented_version.  */
-         if (cnode->instrumentation_clone)
-           {
-             gcc_assert (cnode->orig_decl);
-
-             cnode->instrumented_version = cgraph_node::get (cnode->orig_decl);
-             if (cnode->instrumented_version)
-               {
-                 /* We may have multiple nodes for a single function which
-                    will be merged later.  To have a proper merge we need
-                    to keep instrumentation_version reference between nodes
-                    consistent: each instrumented_version reference should
-                    have proper reverse reference.  Thus don't break existing
-                    instrumented_version reference if it already exists.  */
-                 if (cnode->instrumented_version->instrumented_version)
-                   cnode->instrumented_version = NULL;
-                 else
-                   cnode->instrumented_version->instrumented_version = cnode;
-               }
-
-             /* Restore decl names reference except for wrapper functions.  */
-             if (!chkp_wrap_function (cnode->orig_decl))
-               {
-                 tree name = DECL_ASSEMBLER_NAME (cnode->decl);
-                 IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
-                 TREE_CHAIN (name) = DECL_ASSEMBLER_NAME (cnode->orig_decl);
-               }
-           }
+           cnode->inlined_to = NULL;
        }
 
       ref = (int) (intptr_t) node->same_comdat_group;
@@ -1611,7 +1594,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
 /* Input ipa_refs.  */
 
 static void
-input_refs (struct lto_input_block *ib,
+input_refs (class lto_input_block *ib,
            vec<symtab_node *> nodes)
 {
   int count;
@@ -1629,49 +1612,22 @@ input_refs (struct lto_input_block *ib,
          input_ref (ib, node, nodes);
          count--;
        }
+      if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
+       if (cnode->declare_variant_alt)
+         omp_lto_input_declare_variant_alt (ib, cnode, nodes);
     }
 }
            
-
-static struct gcov_ctr_summary lto_gcov_summary;
-
 /* Input profile_info from IB.  */
 static void
-input_profile_summary (struct lto_input_block *ib,
+input_profile_summary (class lto_input_block *ib,
                       struct lto_file_decl_data *file_data)
 {
-  unsigned h_ix;
-  struct bitpack_d bp;
   unsigned int runs = streamer_read_uhwi (ib);
   if (runs)
     {
       file_data->profile_info.runs = runs;
-      file_data->profile_info.sum_max = streamer_read_gcov_count (ib);
-      file_data->profile_info.sum_all = streamer_read_gcov_count (ib);
 
-      memset (file_data->profile_info.histogram, 0,
-              sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
-      /* Input the bitpack of non-zero histogram indices.  */
-      bp = streamer_read_bitpack (ib);
-      /* Read in and unpack the full bitpack, flagging non-zero
-         histogram entries by setting the num_counters non-zero.  */
-      for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
-        {
-          file_data->profile_info.histogram[h_ix].num_counters
-              = bp_unpack_value (&bp, 1);
-        }
-      for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
-        {
-          if (!file_data->profile_info.histogram[h_ix].num_counters)
-            continue;
-
-          file_data->profile_info.histogram[h_ix].num_counters
-              = streamer_read_gcov_count (ib);
-          file_data->profile_info.histogram[h_ix].min_value
-              = streamer_read_gcov_count (ib);
-          file_data->profile_info.histogram[h_ix].cum_value
-              = streamer_read_gcov_count (ib);
-        }
       /* IPA-profile computes hot bb threshold based on cumulated
         whole program profile.  We need to stream it down to ltrans.  */
       if (flag_ltrans)
@@ -1686,13 +1642,10 @@ static void
 merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
 {
   struct lto_file_decl_data *file_data;
-  unsigned int j, h_ix;
+  unsigned int j;
   gcov_unsigned_t max_runs = 0;
   struct cgraph_node *node;
   struct cgraph_edge *edge;
-  gcov_type saved_sum_all = 0;
-  gcov_ctr_summary *saved_profile_info = 0;
-  int saved_scale = 0;
 
   /* Find unit with maximal number of runs.  If we ever get serious about
      roundoff errors, we might also consider computing smallest common
@@ -1713,70 +1666,8 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
       return;
     }
 
-  profile_info = &lto_gcov_summary;
-  lto_gcov_summary.runs = max_runs;
-  lto_gcov_summary.sum_max = 0;
-  memset (lto_gcov_summary.histogram, 0,
-          sizeof (gcov_bucket_type) * GCOV_HISTOGRAM_SIZE);
-
-  /* Rescale all units to the maximal number of runs.
-     sum_max can not be easily merged, as we have no idea what files come from
-     the same run.  We do not use the info anyway, so leave it 0.  */
-  for (j = 0; (file_data = file_data_vec[j]) != NULL; j++)
-    if (file_data->profile_info.runs)
-      {
-       int scale = GCOV_COMPUTE_SCALE (max_runs,
-                                        file_data->profile_info.runs);
-       lto_gcov_summary.sum_max
-            = MAX (lto_gcov_summary.sum_max,
-                   apply_scale (file_data->profile_info.sum_max, scale));
-       lto_gcov_summary.sum_all
-            = MAX (lto_gcov_summary.sum_all,
-                   apply_scale (file_data->profile_info.sum_all, scale));
-        /* Save a pointer to the profile_info with the largest
-           scaled sum_all and the scale for use in merging the
-           histogram.  */
-        if (!saved_profile_info
-            || lto_gcov_summary.sum_all > saved_sum_all)
-          {
-            saved_profile_info = &file_data->profile_info;
-            saved_sum_all = lto_gcov_summary.sum_all;
-            saved_scale = scale;
-          }
-      }
-
-  gcc_assert (saved_profile_info);
-
-  /* Scale up the histogram from the profile that had the largest
-     scaled sum_all above.  */
-  for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++)
-    {
-      /* Scale up the min value as we did the corresponding sum_all
-         above. Use that to find the new histogram index.  */
-      gcov_type scaled_min
-          = apply_scale (saved_profile_info->histogram[h_ix].min_value,
-                         saved_scale);
-      /* The new index may be shared with another scaled histogram entry,
-         so we need to account for a non-zero histogram entry at new_ix.  */
-      unsigned new_ix = gcov_histo_index (scaled_min);
-      lto_gcov_summary.histogram[new_ix].min_value
-          = (lto_gcov_summary.histogram[new_ix].num_counters
-             ? MIN (lto_gcov_summary.histogram[new_ix].min_value, scaled_min)
-             : scaled_min);
-      /* Some of the scaled counter values would ostensibly need to be placed
-         into different (larger) histogram buckets, but we keep things simple
-         here and place the scaled cumulative counter value in the bucket
-         corresponding to the scaled minimum counter value.  */
-      lto_gcov_summary.histogram[new_ix].cum_value
-          += apply_scale (saved_profile_info->histogram[h_ix].cum_value,
-                          saved_scale);
-      lto_gcov_summary.histogram[new_ix].num_counters
-          += saved_profile_info->histogram[h_ix].num_counters;
-    }
-
-  /* Watch roundoff errors.  */
-  if (lto_gcov_summary.sum_max < max_runs)
-    lto_gcov_summary.sum_max = max_runs;
+  profile_info = XCNEW (gcov_summary);
+  profile_info->runs = max_runs;
 
   /* If merging already happent at WPA time, we are done.  */
   if (flag_ltrans)
@@ -1801,8 +1692,13 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
        if (scale == REG_BR_PROB_BASE)
          continue;
        for (edge = node->callees; edge; edge = edge->next_callee)
-         edge->count = apply_scale (edge->count, scale);
-       node->count = apply_scale (node->count, scale);
+         if (edge->count.ipa ().nonzero_p ())
+           edge->count = edge->count.apply_scale (scale, REG_BR_PROB_BASE);
+       for (edge = node->indirect_calls; edge; edge = edge->next_callee)
+         if (edge->count.ipa ().nonzero_p ())
+           edge->count = edge->count.apply_scale (scale, REG_BR_PROB_BASE);
+       if (node->count.ipa ().nonzero_p ())
+         node->count = node->count.apply_scale (scale, REG_BR_PROB_BASE);
       }
 }
 
@@ -1821,7 +1717,7 @@ input_symtab (void)
     {
       const char *data;
       size_t len;
-      struct lto_input_block *ib;
+      class lto_input_block *ib;
       vec<symtab_node *> nodes;
 
       ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes,
@@ -1849,8 +1745,6 @@ input_symtab (void)
     }
 
   merge_profile_summaries (file_data_vec);
-  get_working_sets ();
-
 
   /* Clear out the aux field that was used to store enough state to
      tell which nodes should be overwritten.  */
@@ -1870,7 +1764,7 @@ input_symtab (void)
    target code, and store them into OFFLOAD_FUNCS and OFFLOAD_VARS.  */
 
 void
-input_offload_tables (void)
+input_offload_tables (bool do_force_output)
 {
   struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
   struct lto_file_decl_data *file_data;
@@ -1880,7 +1774,7 @@ input_offload_tables (void)
     {
       const char *data;
       size_t len;
-      struct lto_input_block *ib
+      class lto_input_block *ib
        = lto_create_simple_input_block (file_data, LTO_section_offload_table,
                                         &data, &len);
       if (!ib)
@@ -1892,17 +1786,26 @@ input_offload_tables (void)
        {
          if (tag == LTO_symtab_unavail_node)
            {
-             int decl_index = streamer_read_uhwi (ib);
              tree fn_decl
-               = lto_file_decl_data_get_fn_decl (file_data, decl_index);
+               = lto_input_fn_decl_ref (ib, file_data);
              vec_safe_push (offload_funcs, fn_decl);
+
+             /* Prevent IPA from removing fn_decl as unreachable, since there
+                may be no refs from the parent function to child_fn in offload
+                LTO mode.  */
+             if (do_force_output)
+               cgraph_node::get (fn_decl)->mark_force_output ();
            }
          else if (tag == LTO_symtab_variable)
            {
-             int decl_index = streamer_read_uhwi (ib);
              tree var_decl
-               = lto_file_decl_data_get_var_decl (file_data, decl_index);
+               = lto_input_var_decl_ref (ib, file_data);
              vec_safe_push (offload_vars, var_decl);
+
+             /* Prevent IPA from removing var_decl as unused, since there
+                may be no refs to var_decl in offload LTO mode.  */
+             if (do_force_output)
+               varpool_node::get (var_decl)->force_output = 1;
            }
          else
            fatal_error (input_location,
@@ -1921,10 +1824,10 @@ input_offload_tables (void)
 static int
 output_cgraph_opt_summary_p (struct cgraph_node *node)
 {
-  return (node->clone_of
-         && (node->clone.tree_map
-             || node->clone.args_to_skip
-             || node->clone.combined_args_to_skip));
+  if (node->clone_of || node->former_clone_of)
+    return true;
+  clone_info *info = clone_info::get (node);
+  return info && (info->tree_map || info->param_adjustments);
 }
 
 /* Output optimization summary for EDGE to OB.  */
@@ -1941,44 +1844,59 @@ output_node_opt_summary (struct output_block *ob,
                         struct cgraph_node *node,
                         lto_symtab_encoder_t encoder)
 {
-  unsigned int index;
-  bitmap_iterator bi;
   struct ipa_replace_map *map;
-  struct bitpack_d bp;
   int i;
   struct cgraph_edge *e;
 
-  if (node->clone.args_to_skip)
-    {
-      streamer_write_uhwi (ob, bitmap_count_bits (node->clone.args_to_skip));
-      EXECUTE_IF_SET_IN_BITMAP (node->clone.args_to_skip, 0, index, bi)
-       streamer_write_uhwi (ob, index);
-    }
-  else
-    streamer_write_uhwi (ob, 0);
-  if (node->clone.combined_args_to_skip)
-    {
-      streamer_write_uhwi (ob, bitmap_count_bits (node->clone.combined_args_to_skip));
-      EXECUTE_IF_SET_IN_BITMAP (node->clone.combined_args_to_skip, 0, index, bi)
-       streamer_write_uhwi (ob, index);
-    }
-  else
-    streamer_write_uhwi (ob, 0);
-  streamer_write_uhwi (ob, vec_safe_length (node->clone.tree_map));
-  FOR_EACH_VEC_SAFE_ELT (node->clone.tree_map, i, map)
+  /* TODO: Should this code be moved to ipa-param-manipulation?  */
+  struct bitpack_d bp;
+  bp = bitpack_create (ob->main_stream);
+  clone_info *info = clone_info::get (node);
+  
+  bp_pack_value (&bp, (info && info->param_adjustments != NULL), 1);
+  streamer_write_bitpack (&bp);
+  if (ipa_param_adjustments *adjustments
+                = info ? info->param_adjustments : NULL)
     {
-      /* At the moment we assume all old trees to be PARM_DECLs, because we have no
-         mechanism to store function local declarations into summaries.  */
-      gcc_assert (!map->old_tree);
-      streamer_write_uhwi (ob, map->parm_num);
-      gcc_assert (EXPR_LOCATION (map->new_tree) == UNKNOWN_LOCATION);
-      stream_write_tree (ob, map->new_tree, true);
+      streamer_write_uhwi (ob, vec_safe_length (adjustments->m_adj_params));
+      ipa_adjusted_param *adj;
+      FOR_EACH_VEC_SAFE_ELT (adjustments->m_adj_params, i, adj)
+       {
+         bp = bitpack_create (ob->main_stream);
+         bp_pack_value (&bp, adj->base_index, IPA_PARAM_MAX_INDEX_BITS);
+         bp_pack_value (&bp, adj->prev_clone_index, IPA_PARAM_MAX_INDEX_BITS);
+         bp_pack_value (&bp, adj->op, 2);
+         bp_pack_value (&bp, adj->param_prefix_index, 2);
+         bp_pack_value (&bp, adj->prev_clone_adjustment, 1);
+         bp_pack_value (&bp, adj->reverse, 1);
+         bp_pack_value (&bp, adj->user_flag, 1);
+         streamer_write_bitpack (&bp);
+         if (adj->op == IPA_PARAM_OP_SPLIT
+             || adj->op == IPA_PARAM_OP_NEW)
+           {
+             stream_write_tree (ob, adj->type, true);
+             if (adj->op == IPA_PARAM_OP_SPLIT)
+               {
+                 stream_write_tree (ob, adj->alias_ptr_type, true);
+                 streamer_write_uhwi (ob, adj->unit_offset);
+               }
+           }
+       }
+      streamer_write_hwi (ob, adjustments->m_always_copy_start);
       bp = bitpack_create (ob->main_stream);
-      bp_pack_value (&bp, map->replace_p, 1);
-      bp_pack_value (&bp, map->ref_p, 1);
+      bp_pack_value (&bp, info->param_adjustments->m_skip_return, 1);
       streamer_write_bitpack (&bp);
     }
 
+  streamer_write_uhwi (ob, info ? vec_safe_length (info->tree_map) : 0);
+  if (info)
+    FOR_EACH_VEC_SAFE_ELT (info->tree_map, i, map)
+      {
+       streamer_write_uhwi (ob, map->parm_num);
+       gcc_assert (EXPR_LOCATION (map->new_tree) == UNKNOWN_LOCATION);
+       stream_write_tree (ob, map->new_tree, true);
+      }
+
   if (lto_symtab_encoder_in_partition_p (encoder, node))
     {
       for (e = node->callees; e; e = e->next_callee)
@@ -2028,7 +1946,7 @@ output_cgraph_opt_summary (void)
 
 static void
 input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED,
-                       struct lto_input_block *ib_main ATTRIBUTE_UNUSED)
+                       class lto_input_block *ib_main ATTRIBUTE_UNUSED)
 {
 }
 
@@ -2036,43 +1954,64 @@ input_edge_opt_summary (struct cgraph_edge *edge ATTRIBUTE_UNUSED,
 
 static void
 input_node_opt_summary (struct cgraph_node *node,
-                       struct lto_input_block *ib_main,
-                       struct data_in *data_in)
+                       class lto_input_block *ib_main,
+                       class data_in *data_in)
 {
   int i;
   int count;
-  int bit;
-  struct bitpack_d bp;
   struct cgraph_edge *e;
 
-  count = streamer_read_uhwi (ib_main);
-  if (count)
-    node->clone.args_to_skip = BITMAP_GGC_ALLOC ();
-  for (i = 0; i < count; i++)
-    {
-      bit = streamer_read_uhwi (ib_main);
-      bitmap_set_bit (node->clone.args_to_skip, bit);
-    }
-  count = streamer_read_uhwi (ib_main);
-  if (count)
-    node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC ();
-  for (i = 0; i < count; i++)
+  /* TODO: Should this code be moved to ipa-param-manipulation?  */
+  struct bitpack_d bp;
+  bp = streamer_read_bitpack (ib_main);
+  bool have_adjustments = bp_unpack_value (&bp, 1);
+  clone_info *info = clone_info::get_create (node);
+
+  if (have_adjustments)
     {
-      bit = streamer_read_uhwi (ib_main);
-      bitmap_set_bit (node->clone.combined_args_to_skip, bit);
+      count = streamer_read_uhwi (ib_main);
+      vec<ipa_adjusted_param, va_gc> *new_params = NULL;
+      for (i = 0; i < count; i++)
+       {
+         ipa_adjusted_param adj;
+         memset (&adj, 0, sizeof (adj));
+         bp = streamer_read_bitpack (ib_main);
+         adj.base_index = bp_unpack_value (&bp, IPA_PARAM_MAX_INDEX_BITS);
+         adj.prev_clone_index
+           = bp_unpack_value (&bp, IPA_PARAM_MAX_INDEX_BITS);
+         adj.op = (enum ipa_parm_op) bp_unpack_value (&bp, 2);
+         adj.param_prefix_index = bp_unpack_value (&bp, 2);
+         adj.prev_clone_adjustment = bp_unpack_value (&bp, 1);
+         adj.reverse = bp_unpack_value (&bp, 1);
+         adj.user_flag = bp_unpack_value (&bp, 1);
+         if (adj.op == IPA_PARAM_OP_SPLIT
+             || adj.op == IPA_PARAM_OP_NEW)
+           {
+             adj.type = stream_read_tree (ib_main, data_in);
+             if (adj.op == IPA_PARAM_OP_SPLIT)
+               {
+                 adj.alias_ptr_type = stream_read_tree (ib_main, data_in);
+                 adj.unit_offset = streamer_read_uhwi (ib_main);
+               }
+           }
+         vec_safe_push (new_params, adj);
+       }
+      int always_copy_start = streamer_read_hwi (ib_main);
+      bp = streamer_read_bitpack (ib_main);
+      bool skip_return = bp_unpack_value (&bp, 1);
+      info->param_adjustments
+       = (new (ggc_alloc <ipa_param_adjustments> ())
+          ipa_param_adjustments (new_params, always_copy_start, skip_return));
     }
+
   count = streamer_read_uhwi (ib_main);
   for (i = 0; i < count; i++)
     {
       struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
 
-      vec_safe_push (node->clone.tree_map, map);
+      vec_safe_push (info->tree_map, map);
       map->parm_num = streamer_read_uhwi (ib_main);
-      map->old_tree = NULL;
       map->new_tree = stream_read_tree (ib_main, data_in);
-      bp = streamer_read_bitpack (ib_main);
-      map->replace_p = bp_unpack_value (&bp, 1);
-      map->ref_p = bp_unpack_value (&bp, 1);
     }
   for (e = node->callees; e; e = e->next_callee)
     input_edge_opt_summary (e, ib_main);
@@ -2092,7 +2031,7 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data,
   const int cfg_offset = sizeof (struct lto_function_header);
   const int main_offset = cfg_offset + header->cfg_size;
   const int string_offset = main_offset + header->main_size;
-  struct data_in *data_in;
+  class data_in *data_in;
   unsigned int i;
   unsigned int count;
 
@@ -2127,10 +2066,9 @@ input_cgraph_opt_summary (vec<symtab_node *> nodes)
   while ((file_data = file_data_vec[j++]))
     {
       size_t len;
-      const char *data =
-       lto_get_section_data (file_data, LTO_section_cgraph_opt_sum, NULL,
-                             &len);
-
+      const char *data
+       = lto_get_summary_section_data (file_data, LTO_section_cgraph_opt_sum,
+                                       &len);
       if (data)
        input_cgraph_opt_section (file_data, data, len, nodes);
     }