ipa-cp.c (ipcp_cloning_candidate_p): Use opt_for_fn.
[gcc.git] / gcc / lto-cgraph.c
index 5feaf1abc7ab8601737390c9cf4a9c87c5a9d467..3ce2367a3bfe8bf88d1f4ca5e684ec31e699f23d 100644 (file)
@@ -1,7 +1,7 @@
 /* Write and read the cgraph to the memory mapped representation of a
    .o file.
 
-   Copyright 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2009-2014 Free Software Foundation, Inc.
    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
 
 This file is part of GCC.
@@ -25,31 +25,49 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "stringpool.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
 #include "expr.h"
 #include "flags.h"
 #include "params.h"
-#include "input.h"
-#include "hashtab.h"
 #include "langhooks.h"
-#include "basic-block.h"
-#include "tree-flow.h"
-#include "cgraph.h"
-#include "function.h"
-#include "ggc.h"
+#include "bitmap.h"
 #include "diagnostic-core.h"
 #include "except.h"
-#include "vec.h"
 #include "timevar.h"
-#include "pointer-set.h"
+#include "hash-map.h"
+#include "plugin-api.h"
+#include "ipa-ref.h"
+#include "cgraph.h"
 #include "lto-streamer.h"
 #include "data-streamer.h"
 #include "tree-streamer.h"
 #include "gcov-io.h"
 #include "tree-pass.h"
 #include "profile.h"
+#include "context.h"
+#include "pass_manager.h"
+#include "ipa-utils.h"
+#include "omp-low.h"
+
+/* True when asm nodes has been output.  */
+bool asm_nodes_output = false;
 
 static void output_cgraph_opt_summary (void);
-static void input_cgraph_opt_summary (vec<symtab_node>  nodes);
+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)
@@ -84,7 +102,7 @@ lto_symtab_encoder_new (bool for_input)
   lto_symtab_encoder_t encoder = XCNEW (struct lto_symtab_encoder_d);
 
   if (!for_input)
-    encoder->map = pointer_map_create ();
+    encoder->map = new hash_map<symtab_node *, size_t>;
   encoder->nodes.create (0);
   return encoder;
 }
@@ -97,7 +115,7 @@ lto_symtab_encoder_delete (lto_symtab_encoder_t encoder)
 {
    encoder->nodes.release ();
    if (encoder->map)
-     pointer_map_destroy (encoder->map);
+     delete encoder->map;
    free (encoder);
 }
 
@@ -108,10 +126,9 @@ lto_symtab_encoder_delete (lto_symtab_encoder_t encoder)
 
 int
 lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
-                          symtab_node node)
+                          symtab_node *node)
 {
   int ref;
-  void **slot;
 
   if (!encoder->map)
     {
@@ -122,18 +139,17 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
       return ref;
     }
 
-  slot = pointer_map_contains (encoder->map, node);
+  size_t *slot = encoder->map->get (node);
   if (!slot || !*slot)
     {
       lto_encoder_entry entry = {node, false, false, false};
       ref = encoder->nodes.length ();
       if (!slot)
-        slot = pointer_map_insert (encoder->map, node);
-      *slot = (void *) (intptr_t) (ref + 1);
+        encoder->map->put (node, ref + 1);
       encoder->nodes.safe_push (entry);
     }
   else
-    ref = (size_t) *slot - 1;
+    ref = *slot - 1;
 
   return ref;
 }
@@ -142,17 +158,16 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
 
 bool
 lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder,
-                               symtab_node node)
+                               symtab_node *node)
 {
-  void **slot, **last_slot;
   int index;
   lto_encoder_entry last_node;
 
-  slot = pointer_map_contains (encoder->map, node);
+  size_t *slot = encoder->map->get (node);
   if (slot == NULL || !*slot)
     return false;
 
-  index = (size_t) *slot - 1;
+  index = *slot - 1;
   gcc_checking_assert (encoder->nodes[index].node == node);
 
   /* Remove from vector. We do this by swapping node with the last element
@@ -160,16 +175,14 @@ lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder,
   last_node = encoder->nodes.pop ();
   if (last_node.node != node)
     {
-      last_slot = pointer_map_contains (encoder->map, last_node.node);
-      gcc_checking_assert (last_slot && *last_slot);
-      *last_slot = (void *)(size_t) (index + 1);
+      gcc_assert (encoder->map->put (last_node.node, index + 1));
 
       /* Move the last element to the original spot of NODE.  */
       encoder->nodes[index] = last_node;
     }
 
   /* Remove element from hash table.  */
-  *slot = NULL;
+  encoder->map->remove (node);
   return true;
 }
 
@@ -180,7 +193,7 @@ bool
 lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder,
                                  struct cgraph_node *node)
 {
-  int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+  int index = lto_symtab_encoder_lookup (encoder, node);
   return encoder->nodes[index].body;
 }
 
@@ -190,8 +203,8 @@ static void
 lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder,
                                    struct cgraph_node *node)
 {
-  int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
-  gcc_checking_assert (encoder->nodes[index].node == (symtab_node)node);
+  int index = lto_symtab_encoder_encode (encoder, node);
+  gcc_checking_assert (encoder->nodes[index].node == node);
   encoder->nodes[index].body = true;
 }
 
@@ -199,9 +212,9 @@ lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder,
 
 bool
 lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder,
-                                        struct varpool_node *node)
+                                        varpool_node *node)
 {
-  int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+  int index = lto_symtab_encoder_lookup (encoder, node);
   if (index == LCC_NOT_FOUND)
     return false;
   return encoder->nodes[index].initializer;
@@ -211,9 +224,9 @@ lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder,
 
 static void
 lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder,
-                                          struct varpool_node *node)
+                                          varpool_node *node)
 {
-  int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+  int index = lto_symtab_encoder_lookup (encoder, node);
   encoder->nodes[index].initializer = true;
 }
 
@@ -221,9 +234,9 @@ lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder,
 
 bool
 lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder,
-                                  symtab_node node)
+                                  symtab_node *node)
 {
-  int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node);
+  int index = lto_symtab_encoder_lookup (encoder, node);
   if (index == LCC_NOT_FOUND)
     return false;
   return encoder->nodes[index].in_partition;
@@ -233,9 +246,9 @@ lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder,
 
 void
 lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder,
-                                    symtab_node node)
+                                    symtab_node *node)
 {
-  int index = lto_symtab_encoder_encode (encoder, (symtab_node)node);
+  int index = lto_symtab_encoder_encode (encoder, node);
   encoder->nodes[index].in_partition = true;
 }
 
@@ -256,29 +269,31 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
     streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
                         LTO_symtab_edge);
 
-  ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->caller);
+  ref = lto_symtab_encoder_lookup (encoder, edge->caller);
   gcc_assert (ref != LCC_NOT_FOUND);
   streamer_write_hwi_stream (ob->main_stream, ref);
 
   if (!edge->indirect_unknown_callee)
     {
-      ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->callee);
+      ref = lto_symtab_encoder_lookup (encoder, edge->callee);
       gcc_assert (ref != LCC_NOT_FOUND);
       streamer_write_hwi_stream (ob->main_stream, ref);
     }
 
-  streamer_write_hwi_stream (ob->main_stream, edge->count);
+  streamer_write_gcov_count_stream (ob->main_stream, edge->count);
 
   bp = bitpack_create (ob->main_stream);
-  uid = (!gimple_has_body_p (edge->caller->symbol.decl)
-        ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt));
-  bp_pack_enum (&bp, cgraph_inline_failed_enum,
+  uid = (!gimple_has_body_p (edge->caller->decl)
+        ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt) + 1);
+  bp_pack_enum (&bp, cgraph_inline_failed_t,
                CIF_N_REASONS, edge->inline_failed);
   bp_pack_var_len_unsigned (&bp, uid);
   bp_pack_var_len_unsigned (&bp, edge->frequency);
   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);
   bp_pack_value (&bp, edge->can_throw_external, 1);
+  bp_pack_value (&bp, edge->in_polymorphic_cdtor, 1);
   if (edge->indirect_unknown_callee)
     {
       int flags = edge->indirect_info->ecf_flags;
@@ -296,18 +311,32 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge,
                             | ECF_NOVOPS)));
     }
   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 LIST contain references from other partitions.  */
+/* Return if NODE contain references from other partitions.  */
 
 bool
-referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder_t encoder)
+referenced_from_other_partition_p (symtab_node *node, lto_symtab_encoder_t encoder)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; node->iterate_referring (i, ref); i++)
     {
-      if (ref->referring->symbol.in_other_partition
+      /* Ignore references from non-offloadable nodes while streaming NODE into
+        offload LTO section.  */
+      if (!ref->referring->need_lto_streaming)
+       continue;
+
+      if (ref->referring->in_other_partition
           || !lto_symtab_encoder_in_partition_p (encoder, ref->referring))
        return true;
     }
@@ -320,26 +349,34 @@ bool
 reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder)
 {
   struct cgraph_edge *e;
-  if (!node->analyzed)
+  if (!node->definition)
     return false;
   if (node->global.inlined_to)
     return false;
   for (e = node->callers; e; e = e->next_caller)
-    if (e->caller->symbol.in_other_partition
-       || !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller))
-      return true;
+    {
+      /* Ignore references from non-offloadable nodes while streaming NODE into
+        offload LTO section.  */
+      if (!e->caller->need_lto_streaming)
+       continue;
+
+      if (e->caller->in_other_partition
+         || !lto_symtab_encoder_in_partition_p (encoder, e->caller))
+       return true;
+    }
   return false;
 }
 
-/* Return if LIST contain references from other partitions.  */
+/* Return if NODE contain references from other partitions.  */
 
 bool
-referenced_from_this_partition_p (struct ipa_ref_list *list,
+referenced_from_this_partition_p (symtab_node *node,
                                  lto_symtab_encoder_t encoder)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++)
+  struct ipa_ref *ref = NULL;
+
+  for (i = 0; node->iterate_referring (i, ref); i++)
     if (lto_symtab_encoder_in_partition_p (encoder, ref->referring))
       return true;
   return false;
@@ -352,7 +389,7 @@ reachable_from_this_partition_p (struct cgraph_node *node, lto_symtab_encoder_t
 {
   struct cgraph_edge *e;
   for (e = node->callers; e; e = e->next_caller)
-    if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller))
+    if (lto_symtab_encoder_in_partition_p (encoder, e->caller))
       return true;
   return false;
 }
@@ -374,11 +411,15 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
   bool boundary_p;
   intptr_t ref;
   bool in_other_partition = false;
-  struct cgraph_node *clone_of;
-  struct ipa_opt_pass_d *pass;
+  struct cgraph_node *clone_of, *ultimate_clone_of;
+  ipa_opt_pass_d *pass;
   int i;
+  bool alias_p;
+  const char *comdat;
+  const char *section;
+  tree group;
 
-  boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node);
+  boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
 
   if (node->analyzed && !boundary_p)
     tag = LTO_symtab_analyzed_node;
@@ -387,7 +428,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
   streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
                       tag);
-  streamer_write_hwi_stream (ob->main_stream, node->symbol.order);
+  streamer_write_hwi_stream (ob->main_stream, node->order);
 
   /* In WPA mode, we only output part of the call-graph.  Also, we
      fake cgraph node attributes.  There are two cases that we care.
@@ -399,7 +440,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
      Cherry-picked nodes:  These are nodes we pulled from other
      translation units into SET during IPA-inlining.  We make them as
      local static nodes to prevent clashes with other local statics.  */
-  if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->symbol.decl))
+  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);  
@@ -414,13 +456,22 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
 
   clone_of = node->clone_of;
   while (clone_of
-        && (ref = lto_symtab_encoder_lookup (encoder, (symtab_node)clone_of)) == LCC_NOT_FOUND)
+        && (ref = lto_symtab_encoder_lookup (encoder, clone_of)) == LCC_NOT_FOUND)
     if (clone_of->prev_sibling_clone)
       clone_of = clone_of->prev_sibling_clone;
     else
       clone_of = clone_of->clone_of;
 
-  if (LTO_symtab_analyzed_node)
+  /* See if body of the master function is output.  If not, we are seeing only
+     an declaration and we do not need to pass down clone tree. */
+  ultimate_clone_of = clone_of;
+  while (ultimate_clone_of && ultimate_clone_of->clone_of)
+    ultimate_clone_of = ultimate_clone_of->clone_of;
+
+  if (clone_of && !lto_symtab_encoder_encode_body_p (encoder, ultimate_clone_of))
+    clone_of = NULL;
+
+  if (tag == LTO_symtab_analyzed_node)
     gcc_assert (clone_of || !node->clone_of);
   if (!clone_of)
     streamer_write_hwi_stream (ob->main_stream, LCC_NOT_FOUND);
@@ -428,20 +479,20 @@ 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->symbol.decl);
-  streamer_write_hwi_stream (ob->main_stream, node->count);
+  lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl);
+  streamer_write_gcov_count_stream (ob->main_stream, node->count);
   streamer_write_hwi_stream (ob->main_stream, node->count_materialization_scale);
 
   streamer_write_hwi_stream (ob->main_stream,
                             node->ipa_transforms_to_apply.length ());
   FOR_EACH_VEC_ELT (node->ipa_transforms_to_apply, i, pass)
-    streamer_write_hwi_stream (ob->main_stream, pass->pass.static_pass_number);
+    streamer_write_hwi_stream (ob->main_stream, pass->static_pass_number);
 
   if (tag == LTO_symtab_analyzed_node)
     {
       if (node->global.inlined_to)
        {
-         ref = lto_symtab_encoder_lookup (encoder, (symtab_node)node->global.inlined_to);
+         ref = lto_symtab_encoder_lookup (encoder, node->global.inlined_to);
          gcc_assert (ref != LCC_NOT_FOUND);
        }
       else
@@ -450,32 +501,50 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
       streamer_write_hwi_stream (ob->main_stream, ref);
     }
 
-  if (node->symbol.same_comdat_group && !boundary_p)
+  group = node->get_comdat_group ();
+  if (group)
+    comdat = IDENTIFIER_POINTER (group);
+  else
+    comdat = "";
+  streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
+
+  if (group)
     {
-      ref = lto_symtab_encoder_lookup (encoder,
-                                      node->symbol.same_comdat_group);
-      gcc_assert (ref != LCC_NOT_FOUND);
+      if (node->same_comdat_group && !boundary_p)
+       {
+         ref = lto_symtab_encoder_lookup (encoder,
+                                          node->same_comdat_group);
+         gcc_assert (ref != LCC_NOT_FOUND);
+       }
+      else
+       ref = LCC_NOT_FOUND;
+      streamer_write_hwi_stream (ob->main_stream, ref);
     }
-  else
-    ref = LCC_NOT_FOUND;
-  streamer_write_hwi_stream (ob->main_stream, ref);
+
+  section = node->get_section ();
+  if (!section)
+    section = "";
+
+  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->symbol.externally_visible, 1);
-  bp_pack_value (&bp, node->local.finalized, 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->symbol.force_output, 1);
-  bp_pack_value (&bp, node->symbol.address_taken, 1);
-  bp_pack_value (&bp, node->abstract_and_needed, 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);
+  bp_pack_value (&bp, node->body_removed, 1);
+  bp_pack_value (&bp, node->implicit_section, 1);
+  bp_pack_value (&bp, node->address_taken, 1);
   bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
-                && !DECL_EXTERNAL (node->symbol.decl)
-                && !DECL_COMDAT (node->symbol.decl)
+                && node->get_partitioning_class () == SYMBOL_PARTITION
                 && (reachable_from_other_partition_p (node, encoder)
-                    || referenced_from_other_partition_p (&node->symbol.ref_list,
-                                                          encoder)), 1);
+                    || referenced_from_other_partition_p (node, encoder)), 1);
   bp_pack_value (&bp, node->lowered, 1);
   bp_pack_value (&bp, in_other_partition, 1);
   /* Real aliases in a boundary become non-aliases. However we still stream
@@ -484,91 +553,125 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
      defined in other unit, we may use the info on aliases to resolve 
      symbol1 != symbol2 type tests that we can do only for locally defined objects
      otherwise.  */
-  bp_pack_value (&bp, node->alias && (!boundary_p || DECL_EXTERNAL (node->symbol.decl)), 1);
+  alias_p = node->alias && (!boundary_p || node->weakref);
+  bp_pack_value (&bp, alias_p, 1);
+  bp_pack_value (&bp, node->weakref, 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);
   bp_pack_value (&bp, node->tm_clone, 1);
+  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 && !boundary_p, 1);
   bp_pack_enum (&bp, ld_plugin_symbol_resolution,
-               LDPR_NUM_KNOWN, node->symbol.resolution);
+               LDPR_NUM_KNOWN, node->resolution);
+  bp_pack_value (&bp, node->instrumentation_clone, 1);
   streamer_write_bitpack (&bp);
+  streamer_write_data_stream (ob->main_stream, section, strlen (section) + 1);
 
   if (node->thunk.thunk_p && !boundary_p)
     {
       streamer_write_uhwi_stream
         (ob->main_stream,
          1 + (node->thunk.this_adjusting != 0) * 2
-         + (node->thunk.virtual_offset_p != 0) * 4);
+         + (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);
     }
-  if ((node->alias || node->thunk.thunk_p)
-      && (!boundary_p || (node->alias && DECL_EXTERNAL (node->symbol.decl))))
-    {
-      streamer_write_hwi_in_range (ob->main_stream, 0, 1,
-                                       node->thunk.alias != NULL);
-      if (node->thunk.alias != NULL)
-        lto_output_fn_decl_index (ob->decl_state, ob->main_stream,
-                                 node->thunk.alias);
-    }
+  streamer_write_hwi_stream (ob->main_stream, node->profile_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);
 }
 
 /* Output the varpool NODE to OB. 
    If NODE is not in SET, then NODE is a boundary.  */
 
 static void
-lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
+lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
                         lto_symtab_encoder_t encoder)
 {
-  bool boundary_p = (node->analyzed
-                    && !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node));
+  bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
   struct bitpack_d bp;
   int ref;
+  bool alias_p;
+  const char *comdat;
+  const char *section;
+  tree group;
 
   streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
                       LTO_symtab_variable);
-  streamer_write_hwi_stream (ob->main_stream, node->symbol.order);
-  lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl);
+  streamer_write_hwi_stream (ob->main_stream, node->order);
+  lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
   bp = bitpack_create (ob->main_stream);
-  bp_pack_value (&bp, node->symbol.externally_visible, 1);
-  bp_pack_value (&bp, node->symbol.force_output, 1);
-  bp_pack_value (&bp, node->finalized, 1);
-  bp_pack_value (&bp, node->alias, 1);
-  bp_pack_value (&bp, node->alias_of != NULL, 1);
-  gcc_assert (node->finalized || !node->analyzed);
+  bp_pack_value (&bp, node->externally_visible, 1);
+  bp_pack_value (&bp, node->no_reorder, 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);
+  bp_pack_value (&bp, node->body_removed, 1);
+  bp_pack_value (&bp, node->implicit_section, 1);
+  bp_pack_value (&bp, node->writeonly, 1);
+  bp_pack_value (&bp, node->definition, 1);
+  alias_p = node->alias && (!boundary_p || node->weakref);
+  bp_pack_value (&bp, alias_p, 1);
+  bp_pack_value (&bp, node->weakref, 1);
+  bp_pack_value (&bp, node->analyzed && !boundary_p, 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
      labels and share them across LTRANS partitions.  */
-  if (DECL_IN_CONSTANT_POOL (node->symbol.decl)
-      && !DECL_EXTERNAL (node->symbol.decl)
-      && !DECL_COMDAT (node->symbol.decl))
+  if (node->get_partitioning_class () != SYMBOL_PARTITION)
     {
       bp_pack_value (&bp, 0, 1);  /* used_from_other_parition.  */
       bp_pack_value (&bp, 0, 1);  /* in_other_partition.  */
     }
   else
     {
+      bp_pack_value (&bp, node->definition
+                    && referenced_from_other_partition_p (node, encoder), 1);
       bp_pack_value (&bp, node->analyzed
-                    && referenced_from_other_partition_p (&node->symbol.ref_list,
-                                                          encoder), 1);
-      bp_pack_value (&bp, boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1);
+                    && boundary_p && !DECL_EXTERNAL (node->decl), 1);
          /* in_other_partition.  */
     }
+  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);
   streamer_write_bitpack (&bp);
-  if (node->alias_of)
-    lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of);
-  if (node->symbol.same_comdat_group && !boundary_p)
+
+  group = node->get_comdat_group ();
+  if (group)
+    comdat = IDENTIFIER_POINTER (group);
+  else
+    comdat = "";
+  streamer_write_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
+
+  if (group)
     {
-      ref = lto_symtab_encoder_lookup (encoder,
-                                      node->symbol.same_comdat_group);
-      gcc_assert (ref != LCC_NOT_FOUND);
+      if (node->same_comdat_group && !boundary_p)
+       {
+         ref = lto_symtab_encoder_lookup (encoder,
+                                          node->same_comdat_group);
+         gcc_assert (ref != LCC_NOT_FOUND);
+       }
+      else
+       ref = LCC_NOT_FOUND;
+      streamer_write_hwi_stream (ob->main_stream, ref);
     }
-  else
-    ref = LCC_NOT_FOUND;
-  streamer_write_hwi_stream (ob->main_stream, ref);
+
+  section = node->get_section ();
+  if (!section)
+    section = "";
+  streamer_write_data_stream (ob->main_stream, section, strlen (section) + 1);
+
   streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
-                      LDPR_NUM_KNOWN, node->symbol.resolution);
+                      LDPR_NUM_KNOWN, node->resolution);
 }
 
 /* Output the varpool NODE to OB. 
@@ -580,13 +683,24 @@ 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;
+  struct cgraph_node *node;
 
   bp = bitpack_create (ob->main_stream);
-  bp_pack_value (&bp, ref->use, 2);
+  bp_pack_value (&bp, ref->use, 3);
+  bp_pack_value (&bp, ref->speculative, 1);
   streamer_write_bitpack (&bp);
   nref = lto_symtab_encoder_lookup (encoder, ref->referred);
   gcc_assert (nref != LCC_NOT_FOUND);
   streamer_write_hwi_stream (ob->main_stream, nref);
+  
+  node = dyn_cast <cgraph_node *> (ref->referring);
+  if (node)
+    {
+      if (ref->stmt)
+       uid = gimple_uid (ref->stmt) + 1;
+      streamer_write_hwi_stream (ob->main_stream, uid);
+    }
 }
 
 /* Stream out profile_summary to OB.  */
@@ -604,11 +718,11 @@ output_profile_summary (struct lto_simple_output_block *ob)
          units.  */
       gcc_assert (profile_info->runs);
       streamer_write_uhwi_stream (ob->main_stream, profile_info->runs);
-      streamer_write_uhwi_stream (ob->main_stream, profile_info->sum_max);
+      streamer_write_gcov_count_stream (ob->main_stream, profile_info->sum_max);
 
       /* sum_all is needed for computing the working set with the
          histogram.  */
-      streamer_write_uhwi_stream (ob->main_stream, profile_info->sum_all);
+      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);
@@ -620,13 +734,18 @@ output_profile_summary (struct lto_simple_output_block *ob)
         {
           if (!profile_info->histogram[h_ix].num_counters)
             continue;
-          streamer_write_uhwi_stream (ob->main_stream,
+          streamer_write_gcov_count_stream (ob->main_stream,
                                       profile_info->histogram[h_ix].num_counters);
-          streamer_write_uhwi_stream (ob->main_stream,
+          streamer_write_gcov_count_stream (ob->main_stream,
                                       profile_info->histogram[h_ix].min_value);
-          streamer_write_uhwi_stream (ob->main_stream,
+          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)
+         streamer_write_gcov_count_stream (ob->main_stream,
+                                          get_hot_bb_threshold ());
     }
   else
     streamer_write_uhwi_stream (ob->main_stream, 0);
@@ -667,16 +786,15 @@ output_refs (lto_symtab_encoder_t encoder)
   for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei);
        lsei_next_in_partition (&lsei))
     {
-      symtab_node node = lsei_node (lsei);
+      symtab_node *node = lsei_node (lsei);
 
-      count = ipa_ref_list_nreferences (&node->symbol.ref_list);
+      count = node->ref_list.nreferences ();
       if (count)
        {
-         streamer_write_uhwi_stream (ob->main_stream, count);
+         streamer_write_gcov_count_stream (ob->main_stream, count);
          streamer_write_uhwi_stream (ob->main_stream,
                                     lto_symtab_encoder_lookup (encoder, node));
-         for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list,
-                                                     i, ref); i++)
+         for (i = 0; node->iterate_reference (i, ref); i++)
            lto_output_ref (ob, ref, encoder);
        }
     }
@@ -697,24 +815,33 @@ add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
     add_node_to (encoder, node->clone_of, include_body);
   else if (include_body)
     lto_set_symtab_encoder_encode_body (encoder, node);
-  lto_symtab_encoder_encode (encoder, (symtab_node)node);
+  lto_symtab_encoder_encode (encoder, node);
 }
 
-/* Add all references in LIST to encoders.  */
+/* Add all references in NODE to encoders.  */
 
 static void
-add_references (lto_symtab_encoder_t encoder,
-               struct ipa_ref_list *list)
+create_references (lto_symtab_encoder_t encoder, symtab_node *node)
 {
   int i;
-  struct ipa_ref *ref;
-  for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
-    if (is_a <cgraph_node> (ref->referred))
-      add_node_to (encoder, ipa_ref_node (ref), false);
+  struct ipa_ref *ref = NULL;
+  for (i = 0; node->iterate_reference (i, ref); i++)
+    if (is_a <cgraph_node *> (ref->referred))
+      add_node_to (encoder, dyn_cast <cgraph_node *> (ref->referred), false);
     else
       lto_symtab_encoder_encode (encoder, ref->referred);
 }
 
+/* Select what needs to be streamed out.  In regular lto mode stream everything.
+   In offload lto mode stream only nodes marked as offloadable.  */
+void
+select_what_to_stream (bool offload_lto_mode)
+{
+  struct symtab_node *snode;
+  FOR_EACH_SYMBOL (snode)
+    snode->need_lto_streaming = !offload_lto_mode || snode->offloadable;
+}
+
 /* Find all symbols we want to stream into given partition and insert them
    to encoders.
 
@@ -726,11 +853,11 @@ add_references (lto_symtab_encoder_t encoder,
 lto_symtab_encoder_t 
 compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
 {
-  struct cgraph_node *node;
   struct cgraph_edge *edge;
   int i;
   lto_symtab_encoder_t encoder;
   lto_symtab_encoder_iterator lsei;
+  hash_set<void *> reachable_call_targets;
 
   encoder = lto_symtab_encoder_new (false);
 
@@ -740,35 +867,53 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
   for (lsei = lsei_start_function_in_partition (in_encoder);
        !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
     {
-      node = lsei_cgraph_node (lsei);
+      struct cgraph_node *node = lsei_cgraph_node (lsei);
+      if (!node->need_lto_streaming)
+       continue;
       add_node_to (encoder, node, true);
-      lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
-      add_references (encoder, &node->symbol.ref_list);
+      lto_set_symtab_encoder_in_partition (encoder, node);
+      create_references (encoder, node);
+      /* For proper debug info, we need to ship the origins, too.  */
+      if (DECL_ABSTRACT_ORIGIN (node->decl))
+       {
+         struct cgraph_node *origin_node
+         = cgraph_node::get (DECL_ABSTRACT_ORIGIN (node->decl));
+         add_node_to (encoder, origin_node, true);
+       }
     }
   for (lsei = lsei_start_variable_in_partition (in_encoder);
        !lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
     {
-      struct varpool_node *vnode = lsei_varpool_node (lsei);
-      gcc_assert (!vnode->alias || vnode->alias_of);
-      lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
+      varpool_node *vnode = lsei_varpool_node (lsei);
+
+      if (!vnode->need_lto_streaming)
+       continue;
+      lto_set_symtab_encoder_in_partition (encoder, vnode);
       lto_set_symtab_encoder_encode_initializer (encoder, vnode);
-      add_references (encoder, &vnode->symbol.ref_list);
+      create_references (encoder, vnode);
+      /* For proper debug info, we need to ship the origins, too.  */
+      if (DECL_ABSTRACT_ORIGIN (vnode->decl))
+       {
+         varpool_node *origin_node
+           = varpool_node::get (DECL_ABSTRACT_ORIGIN (vnode->decl));
+         lto_set_symtab_encoder_in_partition (encoder, origin_node);
+       }
     }
   /* Pickle in also the initializer of all referenced readonly variables
      to help folding.  Constant pool variables are not shared, so we must
      pickle those too.  */
   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
     {
-      symtab_node node = lto_symtab_encoder_deref (encoder, i);
-      if (varpool_node *vnode = dyn_cast <varpool_node> (node))
+      symtab_node *node = lto_symtab_encoder_deref (encoder, i);
+      if (varpool_node *vnode = dyn_cast <varpool_node *> (node))
        {
-         if (DECL_INITIAL (vnode->symbol.decl)
-             && !lto_symtab_encoder_encode_initializer_p (encoder,
-                                                          vnode)
-             && const_value_known_p (vnode->symbol.decl))
+         if (!lto_symtab_encoder_encode_initializer_p (encoder,
+                                                       vnode)
+             && (vnode->ctor_useable_for_folding_p ()
+                 || POINTER_BOUNDS_P (vnode->decl)))
            {
              lto_set_symtab_encoder_encode_initializer (encoder, vnode);
-             add_references (encoder, &vnode->symbol.ref_list);
+             create_references (encoder, vnode);
            }
        }
     }
@@ -778,20 +923,49 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
   for (lsei = lsei_start_function_in_partition (encoder);
        !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei))
     {
-      node = lsei_cgraph_node (lsei);
+      struct cgraph_node *node = lsei_cgraph_node (lsei);
       for (edge = node->callees; edge; edge = edge->next_callee)
        {
          struct cgraph_node *callee = edge->callee;
-         if (!lto_symtab_encoder_in_partition_p (encoder, (symtab_node)callee))
+         if (!lto_symtab_encoder_in_partition_p (encoder, callee))
            {
              /* We should have moved all the inlines.  */
              gcc_assert (!callee->global.inlined_to);
              add_node_to (encoder, callee, false);
            }
        }
+      /* Add all possible targets for late devirtualization.  */
+      if (flag_devirtualize)
+       for (edge = node->indirect_calls; edge; edge = edge->next_callee)
+         if (edge->indirect_info->polymorphic)
+           {
+             unsigned int i;
+             void *cache_token;
+             bool final;
+             vec <cgraph_node *>targets
+               = possible_polymorphic_call_targets
+                   (edge, &final, &cache_token);
+             if (!reachable_call_targets.add (cache_token))
+               {
+                 for (i = 0; i < targets.length (); i++)
+                   {
+                     struct cgraph_node *callee = targets[i];
+
+                     /* Adding an external declarations into the unit serves
+                        no purpose and just increases its boundary.  */
+                     if (callee->definition
+                         && !lto_symtab_encoder_in_partition_p
+                              (encoder, callee))
+                       {
+                         gcc_assert (!callee->global.inlined_to);
+                         add_node_to (encoder, callee, false);
+                       }
+                   }
+               }
+           }
     }
- lto_symtab_encoder_delete (in_encoder);
- return encoder;
 lto_symtab_encoder_delete (in_encoder);
 return encoder;
 }
 
 /* Output the part of the symtab in SET and VSET.  */
@@ -804,7 +978,6 @@ output_symtab (void)
   lto_symtab_encoder_iterator lsei;
   int i, n_nodes;
   lto_symtab_encoder_t encoder;
-  static bool asm_nodes_output = false;
 
   if (flag_wpa)
     output_cgraph_opt_summary ();
@@ -824,12 +997,11 @@ output_symtab (void)
   n_nodes = lto_symtab_encoder_size (encoder);
   for (i = 0; i < n_nodes; i++)
     {
-      symtab_node node = lto_symtab_encoder_deref (encoder, i);
-      if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
+      symtab_node *node = lto_symtab_encoder_deref (encoder, i);
+      if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
         lto_output_node (ob, cnode, encoder);
       else
-        lto_output_varpool_node (ob, varpool (node), encoder);
-       
+       lto_output_varpool_node (ob, dyn_cast<varpool_node *> (node), encoder);
     }
 
   /* Go over the nodes in SET again to write edges.  */
@@ -858,6 +1030,90 @@ output_symtab (void)
   output_refs (encoder);
 }
 
+/* Return identifier encoded in IB as a plain string.  */
+
+static tree
+read_identifier (struct lto_input_block *ib)
+{
+  unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
+  tree id;
+
+  if (ib->data[ib->p + len])
+    lto_section_overrun (ib);
+  if (!len)
+    {
+      ib->p++;
+      return NULL;
+    }
+  id = get_identifier (ib->data + ib->p);
+  ib->p += len + 1;
+  return id;
+}
+
+/* Return string encoded in IB, NULL if string is empty.  */
+
+static const char *
+read_string (struct lto_input_block *ib)
+{
+  unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
+  const char *str;
+
+  if (ib->data[ib->p + len])
+    lto_section_overrun (ib);
+  if (!len)
+    {
+      ib->p++;
+      return NULL;
+    }
+  str = ib->data + ib->p;
+  ib->p += len + 1;
+  return str;
+}
+
+/* Output function/variable tables that will allow libgomp to look up offload
+   target code.
+   OFFLOAD_FUNCS is filled in expand_omp_target, OFFLOAD_VARS is filled in
+   varpool_node::get_create.  In WHOPR (partitioned) mode during the WPA stage
+   both OFFLOAD_FUNCS and OFFLOAD_VARS are filled by input_offload_tables.  */
+
+void
+output_offload_tables (void)
+{
+  if (vec_safe_is_empty (offload_funcs) && vec_safe_is_empty (offload_vars))
+    return;
+
+  struct lto_simple_output_block *ob
+    = lto_create_simple_output_block (LTO_section_offload_table);
+
+  for (unsigned i = 0; i < vec_safe_length (offload_funcs); i++)
+    {
+      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]);
+    }
+
+  for (unsigned i = 0; i < vec_safe_length (offload_vars); i++)
+    {
+      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]);
+    }
+
+  streamer_write_uhwi_stream (ob->main_stream, 0);
+  lto_destroy_simple_output_block (ob);
+
+  /* In WHOPR mode during the WPA stage the joint offload tables need to be
+     streamed to one partition only.  That's why we free offload_funcs and
+     offload_vars after the first call of output_offload_tables.  */
+  if (flag_wpa)
+    {
+      vec_free (offload_funcs);
+      vec_free (offload_vars);
+    }
+}
+
 /* 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
@@ -871,23 +1127,27 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
                      enum LTO_symtab_tags tag,
                      struct bitpack_d *bp)
 {
-  node->symbol.aux = (void *) tag;
-  node->symbol.lto_file_data = file_data;
+  node->aux = (void *) tag;
+  node->lto_file_data = file_data;
 
   node->local.local = bp_unpack_value (bp, 1);
-  node->symbol.externally_visible = bp_unpack_value (bp, 1);
-  node->local.finalized = 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->symbol.force_output = bp_unpack_value (bp, 1);
-  node->symbol.address_taken = bp_unpack_value (bp, 1);
-  node->abstract_and_needed = bp_unpack_value (bp, 1);
-  node->symbol.used_from_other_partition = 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);
+  node->body_removed = bp_unpack_value (bp, 1);
+  node->implicit_section = bp_unpack_value (bp, 1);
+  node->address_taken = bp_unpack_value (bp, 1);
+  node->used_from_other_partition = bp_unpack_value (bp, 1);
   node->lowered = bp_unpack_value (bp, 1);
   node->analyzed = tag == LTO_symtab_analyzed_node;
-  node->symbol.in_other_partition = bp_unpack_value (bp, 1);
-  if (node->symbol.in_other_partition
+  node->in_other_partition = bp_unpack_value (bp, 1);
+  if (node->in_other_partition
       /* Avoid updating decl when we are seeing just inline clone.
         When inlining function that has functions already inlined into it,
         we produce clones of inline clones.
@@ -896,19 +1156,37 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
         we might end up streaming inline clone from other partition
         to support clone we are interested in. */
       && (!node->clone_of
-         || node->clone_of->symbol.decl != node->symbol.decl))
+         || node->clone_of->decl != node->decl))
     {
-      DECL_EXTERNAL (node->symbol.decl) = 1;
-      TREE_STATIC (node->symbol.decl) = 0;
+      DECL_EXTERNAL (node->decl) = 1;
+      TREE_STATIC (node->decl) = 0;
     }
   node->alias = bp_unpack_value (bp, 1);
+  node->weakref = 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);
   node->tm_clone = bp_unpack_value (bp, 1);
+  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->symbol.resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
+  node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
                                     LDPR_NUM_KNOWN);
+  node->instrumentation_clone = bp_unpack_value (bp, 1);
+  gcc_assert (flag_ltrans
+             || (!node->in_other_partition
+                 && !node->used_from_other_partition));
+}
+
+/* Return string alias is alias of.  */
+
+static tree
+get_alias_symbol (tree decl)
+{
+  tree alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl));
+  return get_identifier (TREE_STRING_POINTER
+                         (TREE_VALUE (TREE_VALUE (alias))));
 }
 
 /* Read a node from input_block IB.  TAG is the node's tag just read.
@@ -918,8 +1196,9 @@ static struct cgraph_node *
 input_node (struct lto_file_decl_data *file_data,
            struct lto_input_block *ib,
            enum LTO_symtab_tags tag,
-           vec<symtab_node> nodes)
+           vec<symtab_node *> nodes)
 {
+  gcc::pass_manager *passes = g->get_passes ();
   tree fn_decl;
   struct cgraph_node *node;
   struct bitpack_d bp;
@@ -928,7 +1207,8 @@ input_node (struct lto_file_decl_data *file_data,
   int clone_ref;
   int order;
   int i, count;
-
+  tree group;
+  const char *section;
   order = streamer_read_hwi (ib) + order_base;
   clone_ref = streamer_read_hwi (ib);
 
@@ -937,53 +1217,74 @@ input_node (struct lto_file_decl_data *file_data,
 
   if (clone_ref != LCC_NOT_FOUND)
     {
-      node = cgraph_clone_node (cgraph (nodes[clone_ref]), fn_decl,
-                               0, CGRAPH_FREQ_BASE, false,
-                               vNULL, false);
+      node = dyn_cast<cgraph_node *> (nodes[clone_ref])->create_clone (fn_decl,
+       0, CGRAPH_FREQ_BASE, false,
+       vNULL, false, NULL, NULL);
     }
   else
-    node = cgraph_get_create_node (fn_decl);
+    {
+      /* Declaration of functions can be already merged with a declaration
+        from other input file.  We keep cgraph unmerged until after streaming
+        of ipa passes is done.  Alays forcingly create a fresh node.  */
+      node = symtab->create_empty ();
+      node->decl = fn_decl;
+      node->register_symbol ();
+    }
 
-  node->symbol.order = order;
-  if (order >= symtab_order)
-    symtab_order = order + 1;
+  node->order = order;
+  if (order >= symtab->order)
+    symtab->order = order + 1;
 
-  node->count = streamer_read_hwi (ib);
+  node->count = streamer_read_gcov_count (ib);
   node->count_materialization_scale = streamer_read_hwi (ib);
 
   count = streamer_read_hwi (ib);
   node->ipa_transforms_to_apply = vNULL;
   for (i = 0; i < count; i++)
     {
-      struct opt_pass *pass;
+      opt_pass *pass;
       int pid = streamer_read_hwi (ib);
 
-      gcc_assert (pid < passes_by_id_size);
-      pass = passes_by_id[pid];
-      node->ipa_transforms_to_apply.safe_push ((struct ipa_opt_pass_d *) pass);
+      gcc_assert (pid < passes->passes_by_id_size);
+      pass = passes->passes_by_id[pid];
+      node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass_d *) pass);
     }
 
   if (tag == LTO_symtab_analyzed_node)
     ref = streamer_read_hwi (ib);
 
-  ref2 = streamer_read_hwi (ib);
+  group = read_identifier (ib);
+  if (group)
+    ref2 = streamer_read_hwi (ib);
 
   /* Make sure that we have not read this node before.  Nodes that
      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->symbol.aux && !DECL_BUILT_IN (node->symbol.decl))
+  if (node->aux && !DECL_BUILT_IN (node->decl))
     internal_error ("bytecode stream: found multiple instances of cgraph "
-                   "node %d", node->uid);
+                   "node with uid %d", node->uid);
+
+  node->tp_first_run = streamer_read_uhwi (ib);
 
   bp = streamer_read_bitpack (ib);
+
   input_overwrite_node (file_data, node, tag, &bp);
 
   /* Store a reference for now, and fix up later to be a pointer.  */
-  node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref;
+  node->global.inlined_to = (cgraph_node *) (intptr_t) ref;
 
-  /* Store a reference for now, and fix up later to be a pointer.  */
-  node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref2;
+  if (group)
+    {
+      node->set_comdat_group (group);
+      /* Store a reference for now, and fix up later to be a pointer.  */
+      node->same_comdat_group = (symtab_node *) (intptr_t) ref2;
+    }
+  else
+    node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
+  section = read_string (ib);
+  if (section)
+    node->set_section_for_node (section);
 
   if (node->thunk.thunk_p)
     {
@@ -995,67 +1296,101 @@ input_node (struct lto_file_decl_data *file_data,
       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->thunk.thunk_p || node->alias)
+  if (node->alias && !node->analyzed && node->weakref)
+    node->alias_target = get_alias_symbol (node->decl);
+  node->profile_id = streamer_read_hwi (ib);
+  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)
     {
-      if (streamer_read_hwi_in_range (ib, "alias nonzero flag", 0, 1))
-       {
-          decl_index = streamer_read_uhwi (ib);
-          node->thunk.alias = lto_file_decl_data_get_fn_decl (file_data,
-                                                             decl_index);
-       }
+      decl_index = streamer_read_uhwi (ib);
+      fn_decl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
+      node->orig_decl = fn_decl;
     }
+
   return node;
 }
 
 /* Read a node from input_block IB.  TAG is the node's tag just read.
    Return the node read or overwriten.  */
 
-static struct varpool_node *
+static varpool_node *
 input_varpool_node (struct lto_file_decl_data *file_data,
                    struct lto_input_block *ib)
 {
   int decl_index;
   tree var_decl;
-  struct varpool_node *node;
+  varpool_node *node;
   struct bitpack_d bp;
   int ref = LCC_NOT_FOUND;
-  bool non_null_aliasof;
   int order;
+  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);
-  node = varpool_node_for_decl (var_decl);
-  node->symbol.order = order;
-  if (order >= symtab_order)
-    symtab_order = order + 1;
-  node->symbol.lto_file_data = file_data;
+
+  /* Declaration of functions can be already merged with a declaration
+     from other input file.  We keep cgraph unmerged until after streaming
+     of ipa passes is done.  Alays forcingly create a fresh node.  */
+  node = varpool_node::create_empty ();
+  node->decl = var_decl;
+  node->register_symbol ();
+
+  node->order = order;
+  if (order >= symtab->order)
+    symtab->order = order + 1;
+  node->lto_file_data = file_data;
 
   bp = streamer_read_bitpack (ib);
-  node->symbol.externally_visible = bp_unpack_value (&bp, 1);
-  node->symbol.force_output = bp_unpack_value (&bp, 1);
-  node->finalized = bp_unpack_value (&bp, 1);
+  node->externally_visible = bp_unpack_value (&bp, 1);
+  node->no_reorder = 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);
+  node->body_removed = bp_unpack_value (&bp, 1);
+  node->implicit_section = bp_unpack_value (&bp, 1);
+  node->writeonly = bp_unpack_value (&bp, 1);
+  node->definition = bp_unpack_value (&bp, 1);
   node->alias = bp_unpack_value (&bp, 1);
-  non_null_aliasof = bp_unpack_value (&bp, 1);
-  node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1);
-  node->symbol.in_other_partition = bp_unpack_value (&bp, 1);
-  node->analyzed = (node->finalized && (!node->alias || !node->symbol.in_other_partition)); 
-  if (node->symbol.in_other_partition)
+  node->weakref = 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);
+  if (node->in_other_partition)
     {
-      DECL_EXTERNAL (node->symbol.decl) = 1;
-      TREE_STATIC (node->symbol.decl) = 0;
+      DECL_EXTERNAL (node->decl) = 1;
+      TREE_STATIC (node->decl) = 0;
     }
-  if (non_null_aliasof)
+  if (node->alias && !node->analyzed && node->weakref)
+    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);
+  group = read_identifier (ib);
+  if (group)
     {
-      decl_index = streamer_read_uhwi (ib);
-      node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index);
+      node->set_comdat_group (group);
+      ref = streamer_read_hwi (ib);
+      /* Store a reference for now, and fix up later to be a pointer.  */
+      node->same_comdat_group = (symtab_node *) (intptr_t) ref;
     }
-  ref = streamer_read_hwi (ib);
-  /* Store a reference for now, and fix up later to be a pointer.  */
-  node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref;
-  node->symbol.resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
+  else
+    node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
+  section = read_string (ib);
+  if (section)
+    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));
 
   return node;
 }
@@ -1065,17 +1400,23 @@ input_varpool_node (struct lto_file_decl_data *file_data,
 
 static void
 input_ref (struct lto_input_block *ib,
-          symtab_node referring_node,
-          vec<symtab_node> nodes)
+          symtab_node *referring_node,
+          vec<symtab_node *> nodes)
 {
-  symtab_node node = NULL;
+  symtab_node *node = NULL;
   struct bitpack_d bp;
   enum ipa_ref_use use;
+  bool speculative;
+  struct ipa_ref *ref;
 
   bp = streamer_read_bitpack (ib);
-  use = (enum ipa_ref_use) bp_unpack_value (&bp, 2);
+  use = (enum ipa_ref_use) bp_unpack_value (&bp, 3);
+  speculative = (enum ipa_ref_use) bp_unpack_value (&bp, 1);
   node = nodes[streamer_read_hwi (ib)];
-  ipa_record_reference (referring_node, node, use, NULL);
+  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);
 }
 
 /* Read an edge from IB.  NODES points to a vector of previously read nodes for
@@ -1084,7 +1425,7 @@ 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 (struct lto_input_block *ib, vec<symtab_node *> nodes,
            bool indirect)
 {
   struct cgraph_node *caller, *callee;
@@ -1096,36 +1437,38 @@ input_edge (struct lto_input_block *ib, vec<symtab_node> nodes,
   struct bitpack_d bp;
   int ecf_flags = 0;
 
-  caller = cgraph (nodes[streamer_read_hwi (ib)]);
-  if (caller == NULL || caller->symbol.decl == NULL_TREE)
+  caller = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
+  if (caller == NULL || caller->decl == NULL_TREE)
     internal_error ("bytecode stream: no caller found while reading edge");
 
   if (!indirect)
     {
-      callee = cgraph (nodes[streamer_read_hwi (ib)]);
-      if (callee == NULL || callee->symbol.decl == NULL_TREE)
+      callee = dyn_cast<cgraph_node *> (nodes[streamer_read_hwi (ib)]);
+      if (callee == NULL || callee->decl == NULL_TREE)
        internal_error ("bytecode stream: no callee found while reading edge");
     }
   else
     callee = NULL;
 
-  count = (gcov_type) streamer_read_hwi (ib);
+  count = streamer_read_gcov_count (ib);
 
   bp = streamer_read_bitpack (ib);
-  inline_failed = bp_unpack_enum (&bp, cgraph_inline_failed_enum, CIF_N_REASONS);
+  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);
 
   if (indirect)
-    edge = cgraph_create_indirect_edge (caller, NULL, 0, count, freq);
+    edge = caller->create_indirect_edge (NULL, 0, count, freq);
   else
-    edge = cgraph_create_edge (caller, callee, NULL, count, freq);
+    edge = caller->create_edge (callee, NULL, count, freq);
 
   edge->indirect_inlining_edge = bp_unpack_value (&bp, 1);
+  edge->speculative = bp_unpack_value (&bp, 1);
   edge->lto_stmt_uid = stmt_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);
+  edge->in_polymorphic_cdtor = bp_unpack_value (&bp, 1);
   if (indirect)
     {
       if (bp_unpack_value (&bp, 1))
@@ -1141,23 +1484,26 @@ 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);
     }
 }
 
 
 /* Read a cgraph from IB using the info in FILE_DATA.  */
 
-static vec<symtab_node> 
+static vec<symtab_node *
 input_cgraph_1 (struct lto_file_decl_data *file_data,
                struct lto_input_block *ib)
 {
   enum LTO_symtab_tags tag;
-  vec<symtab_node> nodes = vNULL;
-  symtab_node node;
+  vec<symtab_node *> nodes = vNULL;
+  symtab_node *node;
   unsigned i;
 
   tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
-  order_base = symtab_order;
+  order_base = symtab->order;
   while (tag)
     {
       if (tag == LTO_symtab_edge)
@@ -1166,14 +1512,14 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
         input_edge (ib, nodes, true);
       else if (tag == LTO_symtab_variable)
         {
-         node = (symtab_node)input_varpool_node (file_data, ib);
+         node = input_varpool_node (file_data, ib);
           nodes.safe_push (node);
          lto_symtab_encoder_encode (file_data->symtab_node_encoder, node);
         }
       else
        {
-         node = (symtab_node)input_node (file_data, ib, tag, nodes);
-         if (node == NULL || node->symbol.decl == NULL_TREE)
+         node = input_node (file_data, ib, tag, nodes);
+         if (node == NULL || node->decl == NULL_TREE)
            internal_error ("bytecode stream: found empty cgraph node");
          nodes.safe_push (node);
          lto_symtab_encoder_encode (file_data->symtab_node_encoder, node);
@@ -1187,37 +1533,54 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
   /* AUX pointers should be all non-zero for function nodes read from the stream.  */
 #ifdef ENABLE_CHECKING
   FOR_EACH_VEC_ELT (nodes, i, node)
-    gcc_assert (node->symbol.aux || !is_a <cgraph_node> (node));
+    gcc_assert (node->aux || !is_a <cgraph_node *> (node));
 #endif
   FOR_EACH_VEC_ELT (nodes, i, node)
     {
       int ref;
-      if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
+      if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
        {
          ref = (int) (intptr_t) cnode->global.inlined_to;
 
          /* We share declaration of builtins, so we may read same node twice.  */
-         if (!node->symbol.aux)
+         if (!node->aux)
            continue;
-         node->symbol.aux = NULL;
+         node->aux = NULL;
 
          /* Fixup inlined_to from reference to pointer.  */
          if (ref != LCC_NOT_FOUND)
-           cgraph (node)->global.inlined_to = cgraph (nodes[ref]);
+           dyn_cast<cgraph_node *> (node)->global.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)
+               cnode->instrumented_version->instrumented_version = cnode;
+
+             /* Restore decl names reference.  */
+             if (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (cnode->decl))
+                 && !TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl)))
+               TREE_CHAIN (DECL_ASSEMBLER_NAME (cnode->decl))
+                 = DECL_ASSEMBLER_NAME (cnode->orig_decl);
+           }
        }
 
-      ref = (int) (intptr_t) node->symbol.same_comdat_group;
+      ref = (int) (intptr_t) node->same_comdat_group;
 
       /* Fixup same_comdat_group from reference to pointer.  */
       if (ref != LCC_NOT_FOUND)
-       node->symbol.same_comdat_group = nodes[ref];
+       node->same_comdat_group = nodes[ref];
       else
-       node->symbol.same_comdat_group = NULL;
+       node->same_comdat_group = NULL;
     }
   FOR_EACH_VEC_ELT (nodes, i, node)
-    node->symbol.aux = is_a <cgraph_node> (node) ? (void *)1 : NULL;
+    node->aux = is_a <cgraph_node *> (node) ? (void *)1 : NULL;
   return nodes;
 }
 
@@ -1225,13 +1588,13 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
 
 static void
 input_refs (struct lto_input_block *ib,
-           vec<symtab_node> nodes)
+           vec<symtab_node *> nodes)
 {
   int count;
   int idx;
   while (true)
     {
-      symtab_node node;
+      symtab_node *node;
       count = streamer_read_uhwi (ib);
       if (!count)
        break;
@@ -1259,8 +1622,8 @@ input_profile_summary (struct lto_input_block *ib,
   if (runs)
     {
       file_data->profile_info.runs = runs;
-      file_data->profile_info.sum_max = streamer_read_uhwi (ib);
-      file_data->profile_info.sum_all = streamer_read_uhwi (ib);
+      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);
@@ -1279,12 +1642,16 @@ input_profile_summary (struct lto_input_block *ib,
             continue;
 
           file_data->profile_info.histogram[h_ix].num_counters
-              = streamer_read_uhwi (ib);
+              = streamer_read_gcov_count (ib);
           file_data->profile_info.histogram[h_ix].min_value
-              = streamer_read_uhwi (ib);
+              = streamer_read_gcov_count (ib);
           file_data->profile_info.histogram[h_ix].cum_value
-              = streamer_read_uhwi (ib);
+              = 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)
+       set_hot_bb_threshold (streamer_read_gcov_count (ib));
     }
 
 }
@@ -1334,18 +1701,19 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
   for (j = 0; (file_data = file_data_vec[j]) != NULL; j++)
     if (file_data->profile_info.runs)
       {
-       int scale = RDIV (REG_BR_PROB_BASE * max_runs,
-                          file_data->profile_info.runs);
-       lto_gcov_summary.sum_max = MAX (lto_gcov_summary.sum_max,
-                                       RDIV (file_data->profile_info.sum_max
-                                              * scale, REG_BR_PROB_BASE));
-       lto_gcov_summary.sum_all = MAX (lto_gcov_summary.sum_all,
-                                       RDIV (file_data->profile_info.sum_all
-                                              * scale, REG_BR_PROB_BASE));
+       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 (lto_gcov_summary.sum_all > saved_sum_all)
+        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;
@@ -1361,19 +1729,25 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
     {
       /* Scale up the min value as we did the corresponding sum_all
          above. Use that to find the new histogram index.  */
-      int scaled_min = RDIV (saved_profile_info->histogram[h_ix].min_value
-                             * saved_scale, REG_BR_PROB_BASE);
+      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 = 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
-          = RDIV (saved_profile_info->histogram[h_ix].cum_value
-                  * saved_scale, REG_BR_PROB_BASE);
+          += 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;
+          += saved_profile_info->histogram[h_ix].num_counters;
     }
 
   /* Watch roundoff errors.  */
@@ -1388,13 +1762,13 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec)
      During LTRANS we already have values of count_materialization_scale
      computed, so just update them.  */
   FOR_EACH_FUNCTION (node)
-    if (node->symbol.lto_file_data
-       && node->symbol.lto_file_data->profile_info.runs)
+    if (node->lto_file_data
+       && node->lto_file_data->profile_info.runs)
       {
        int scale;
 
        scale = RDIV (node->count_materialization_scale * max_runs,
-                      node->symbol.lto_file_data->profile_info.runs);
+                      node->lto_file_data->profile_info.runs);
        node->count_materialization_scale = scale;
        if (scale < 0)
          fatal_error ("Profile information in %s corrupted",
@@ -1403,8 +1777,8 @@ 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 = RDIV (edge->count * scale, REG_BR_PROB_BASE);
-       node->count = RDIV (node->count * scale, REG_BR_PROB_BASE);
+         edge->count = apply_scale (edge->count, scale);
+       node->count = apply_scale (node->count, scale);
       }
 }
 
@@ -1419,14 +1793,12 @@ input_symtab (void)
   unsigned int j = 0;
   struct cgraph_node *node;
 
-  cgraph_state = CGRAPH_STATE_IPA_SSA;
-
   while ((file_data = file_data_vec[j++]))
     {
       const char *data;
       size_t len;
       struct lto_input_block *ib;
-      vec<symtab_node> nodes;
+      vec<symtab_node *> nodes;
 
       ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes,
                                          &data, &len);
@@ -1441,7 +1813,8 @@ input_symtab (void)
       ib = lto_create_simple_input_block (file_data, LTO_section_refs,
                                          &data, &len);
       if (!ib)
-       fatal_error("cannot find LTO section refs in %s", file_data->file_name);
+       fatal_error ("cannot find LTO section refs in %s",
+                    file_data->file_name);
       input_refs (ib, nodes);
       lto_destroy_simple_input_block (file_data, LTO_section_refs,
                                      ib, data, len);
@@ -1451,7 +1824,7 @@ input_symtab (void)
     }
 
   merge_profile_summaries (file_data_vec);
-  compute_working_sets ();
+  get_working_sets ();
 
 
   /* Clear out the aux field that was used to store enough state to
@@ -1463,8 +1836,57 @@ input_symtab (void)
         node for the parent function was never emitted to the gimple
         file, cgraph_node will create a node for it when setting the
         context of the nested function.  */
-      if (node->symbol.lto_file_data)
-       node->symbol.aux = NULL;
+      if (node->lto_file_data)
+       node->aux = NULL;
+    }
+}
+
+/* Input function/variable tables that will allow libgomp to look up offload
+   target code, and store them into OFFLOAD_FUNCS and OFFLOAD_VARS.  */
+
+void
+input_offload_tables (void)
+{
+  struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
+  struct lto_file_decl_data *file_data;
+  unsigned int j = 0;
+
+  while ((file_data = file_data_vec[j++]))
+    {
+      const char *data;
+      size_t len;
+      struct lto_input_block *ib
+       = lto_create_simple_input_block (file_data, LTO_section_offload_table,
+                                        &data, &len);
+      if (!ib)
+       continue;
+
+      enum LTO_symtab_tags tag
+       = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
+      while (tag)
+       {
+         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);
+             vec_safe_push (offload_funcs, fn_decl);
+           }
+         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);
+             vec_safe_push (offload_vars, var_decl);
+           }
+         else
+           fatal_error ("invalid offload table in %s", file_data->file_name);
+
+         tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
+       }
+
+      lto_destroy_simple_input_block (file_data, LTO_section_offload_table,
+                                     ib, data, len);
     }
 }
 
@@ -1519,17 +1941,10 @@ output_node_opt_summary (struct output_block *ob,
   streamer_write_uhwi (ob, vec_safe_length (node->clone.tree_map));
   FOR_EACH_VEC_SAFE_ELT (node->clone.tree_map, i, map)
     {
-      int parm_num;
-      tree parm;
-
-      for (parm_num = 0, parm = DECL_ARGUMENTS (node->symbol.decl); parm;
-          parm = DECL_CHAIN (parm), parm_num++)
-       if (map->old_tree == parm)
-         break;
       /* 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 (parm);
-      streamer_write_uhwi (ob, parm_num);
+      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);
       bp = bitpack_create (ob->main_stream);
@@ -1538,7 +1953,7 @@ output_node_opt_summary (struct output_block *ob,
       streamer_write_bitpack (&bp);
     }
 
-  if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node) node))
+  if (lto_symtab_encoder_in_partition_p (encoder, node))
     {
       for (e = node->callees; e; e = e->next_callee)
        output_edge_opt_summary (ob, e);
@@ -1558,21 +1973,21 @@ output_cgraph_opt_summary (void)
   struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
   unsigned count = 0;
 
-  ob->cgraph_node = NULL;
+  ob->symbol = NULL;
   encoder = ob->decl_state->symtab_node_encoder;
   n_nodes = lto_symtab_encoder_size (encoder);
   for (i = 0; i < n_nodes; i++)
     {
-      symtab_node node = lto_symtab_encoder_deref (encoder, i);
-      cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+      symtab_node *node = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
       if (cnode && output_cgraph_opt_summary_p (cnode))
        count++;
     }
   streamer_write_uhwi (ob, count);
   for (i = 0; i < n_nodes; i++)
     {
-      symtab_node node = lto_symtab_encoder_deref (encoder, i);
-      cgraph_node *cnode = dyn_cast <cgraph_node> (node);
+      symtab_node *node = lto_symtab_encoder_deref (encoder, i);
+      cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
       if (cnode && output_cgraph_opt_summary_p (cnode))
        {
          streamer_write_uhwi (ob, i);
@@ -1623,7 +2038,7 @@ input_node_opt_summary (struct cgraph_node *node,
   count = streamer_read_uhwi (ib_main);
   for (i = 0; i < count; i++)
     {
-      struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
+      struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
 
       vec_safe_push (node->clone.tree_map, map);
       map->parm_num = streamer_read_uhwi (ib_main);
@@ -1644,7 +2059,7 @@ input_node_opt_summary (struct cgraph_node *node,
 static void
 input_cgraph_opt_section (struct lto_file_decl_data *file_data,
                          const char *data, size_t len,
-                         vec<symtab_node> nodes)
+                         vec<symtab_node *> nodes)
 {
   const struct lto_function_header *header =
     (const struct lto_function_header *) data;
@@ -1652,12 +2067,11 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data,
   const int main_offset = cfg_offset + header->cfg_size;
   const int string_offset = main_offset + header->main_size;
   struct data_in *data_in;
-  struct lto_input_block ib_main;
   unsigned int i;
   unsigned int count;
 
-  LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
-                       header->main_size);
+  lto_input_block ib_main ((const char *) data + main_offset,
+                          header->main_size);
 
   data_in =
     lto_data_in_create (file_data, (const char *) data + string_offset,
@@ -1667,7 +2081,7 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data,
   for (i = 0; i < count; i++)
     {
       int ref = streamer_read_uhwi (&ib_main);
-      input_node_opt_summary (cgraph (nodes[ref]),
+      input_node_opt_summary (dyn_cast<cgraph_node *> (nodes[ref]),
                              &ib_main, data_in);
     }
   lto_free_section_data (file_data, LTO_section_cgraph_opt_sum, NULL, data,
@@ -1678,7 +2092,7 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data,
 /* Input optimization summary of cgraph.  */
 
 static void
-input_cgraph_opt_summary (vec<symtab_node> nodes)
+input_cgraph_opt_summary (vec<symtab_node *> nodes)
 {
   struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
   struct lto_file_decl_data *file_data;