]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cgraph.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / cgraph.c
index 33fba5a8f1c7e0cb216293995de34b50f726e6fd..de0786537814690bf7e841500be532e96f62132a 100644 (file)
@@ -1,5 +1,5 @@
 /* Callgraph handling code.
-   Copyright (C) 2003-2019 Free Software Foundation, Inc.
+   Copyright (C) 2003-2021 Free Software Foundation, Inc.
    Contributed by Jan Hubicka
 
 This file is part of GCC.
@@ -57,12 +57,16 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-pretty-print.h"
 #include "tree-dfa.h"
 #include "profile.h"
-#include "params.h"
 #include "context.h"
 #include "gimplify.h"
 #include "stringpool.h"
 #include "attribs.h"
 #include "selftest.h"
+#include "tree-into-ssa.h"
+#include "ipa-inline.h"
+#include "tree-nested.h"
+#include "symtab-thunks.h"
+#include "symtab-clones.h"
 
 /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this.  */
 #include "tree-pass.h"
@@ -197,6 +201,9 @@ delete_function_version (cgraph_function_version_info *decl_v)
   if (decl_v == NULL)
     return;
 
+  if (version_info_node == decl_v)
+    version_info_node = NULL;
+
   if (decl_v->prev != NULL)
     decl_v->prev->next = decl_v->next;
 
@@ -280,14 +287,8 @@ symbol_table::initialize (void)
 cgraph_node *
 symbol_table::create_empty (void)
 {
-  cgraph_node *node = allocate_cgraph_symbol ();
-
-  node->type = SYMTAB_FUNCTION;
-  node->frequency = NODE_FREQUENCY_NORMAL;
-  node->count_materialization_scale = REG_BR_PROB_BASE;
   cgraph_count++;
-
-  return node;
+  return new (ggc_alloc<cgraph_node> ()) cgraph_node (cgraph_max_uid++);
 }
 
 /* Register HOOK to be called with DATA on each removed edge.  */
@@ -507,8 +508,6 @@ cgraph_node::create (tree decl)
 
   node->decl = decl;
 
-  node->count = profile_count::uninitialized ();
-
   if ((flag_openacc || flag_openmp)
       && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl)))
     {
@@ -521,13 +520,8 @@ cgraph_node::create (tree decl)
     node->ifunc_resolver = true;
 
   node->register_symbol ();
+  maybe_record_nested_function (node);
 
-  if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
-    {
-      node->origin = cgraph_node::get_create (DECL_CONTEXT (decl));
-      node->next_nested = node->origin->nested;
-      node->origin->nested = node;
-    }
   return node;
 }
 
@@ -547,6 +541,7 @@ cgraph_node::get_create (tree decl)
     {
       first_clone->clone_of = node;
       node->clones = first_clone;
+      node->order = first_clone->order;
       symtab->symtab_prevail_in_asm_name_hash (node);
       node->decl->decl_with_vis.symtab_node = node;
       if (dump_file)
@@ -561,7 +556,8 @@ cgraph_node::get_create (tree decl)
 }
 
 /* Mark ALIAS as an alias to DECL.  DECL_NODE is cgraph node representing
-   the function body is associated with (not necessarily cgraph_node (DECL).  */
+   the function body is associated with
+   (not necessarily cgraph_node (DECL)).  */
 
 cgraph_node *
 cgraph_node::create_alias (tree alias, tree target)
@@ -635,15 +631,24 @@ cgraph_node::create_thunk (tree alias, tree, bool this_adjusting,
                       ? virtual_value == wi::to_wide (virtual_offset)
                       : virtual_value == 0);
 
-  node->thunk.fixed_offset = fixed_offset;
-  node->thunk.virtual_value = virtual_value;
-  node->thunk.indirect_offset = indirect_offset;
-  node->thunk.alias = real_alias;
-  node->thunk.this_adjusting = this_adjusting;
-  node->thunk.virtual_offset_p = virtual_offset != NULL;
-  node->thunk.thunk_p = true;
+  node->thunk = true;
   node->definition = true;
 
+  thunk_info *i;
+  thunk_info local_info;
+  if (symtab->state < CONSTRUCTION)
+    i = &local_info;
+  else
+    i = thunk_info::get_create (node);
+  i->fixed_offset = fixed_offset;
+  i->virtual_value = virtual_value;
+  i->indirect_offset = indirect_offset;
+  i->alias = real_alias;
+  i->this_adjusting = this_adjusting;
+  i->virtual_offset_p = virtual_offset != NULL;
+  if (symtab->state < CONSTRUCTION)
+    i->register_early (node);
+
   return node;
 }
 
@@ -717,7 +722,9 @@ cgraph_add_edge_to_call_site_hash (cgraph_edge *e)
   if (*slot)
     {
       gcc_assert (((cgraph_edge *)*slot)->speculative);
-      if (e->callee)
+      if (e->callee && (!e->prev_callee
+                       || !e->prev_callee->speculative
+                       || e->prev_callee->call_stmt != e->call_stmt))
        *slot = e;
       return;
     }
@@ -771,55 +778,88 @@ cgraph_node::get_edge (gimple *call_stmt)
 }
 
 
-/* Change field call_stmt of edge to NEW_STMT.
-   If UPDATE_SPECULATIVE and E is any component of speculative
-   edge, then update all components.  */
+/* Change field call_stmt of edge E to NEW_STMT.  If UPDATE_SPECULATIVE and E
+   is any component of speculative edge, then update all components.
+   Speculations can be resolved in the process and EDGE can be removed and
+   deallocated.  Return the edge that now represents the call.  */
 
-void
-cgraph_edge::set_call_stmt (gcall *new_stmt, bool update_speculative)
+cgraph_edge *
+cgraph_edge::set_call_stmt (cgraph_edge *e, gcall *new_stmt,
+                           bool update_speculative)
 {
   tree decl;
 
+  cgraph_node *new_direct_callee = NULL;
+  if ((e->indirect_unknown_callee || e->speculative)
+      && (decl = gimple_call_fndecl (new_stmt)))
+    {
+      /* Constant propagation and especially inlining can turn an indirect call
+        into a direct one.  */
+      new_direct_callee = cgraph_node::get (decl);
+      gcc_checking_assert (new_direct_callee);
+    }
+
   /* Speculative edges has three component, update all of them
      when asked to.  */
-  if (update_speculative && speculative)
+  if (update_speculative && e->speculative
+      /* If we are about to resolve the speculation by calling make_direct
+        below, do not bother going over all the speculative edges now.  */
+      && !new_direct_callee)
     {
-      cgraph_edge *direct, *indirect;
+      cgraph_edge *direct, *indirect, *next;
       ipa_ref *ref;
+      bool e_indirect = e->indirect_unknown_callee;
+      int n = 0;
 
-      speculative_call_info (direct, indirect, ref);
-      direct->set_call_stmt (new_stmt, false);
-      indirect->set_call_stmt (new_stmt, false);
-      ref->stmt = new_stmt;
-      return;
-    }
+      direct = e->first_speculative_call_target ();
+      indirect = e->speculative_call_indirect_edge ();
 
-  /* Only direct speculative edges go to call_site_hash.  */
-  if (caller->call_site_hash
-      && (!speculative || !indirect_unknown_callee))
-    {
-      caller->call_site_hash->remove_elt_with_hash
-       (call_stmt, cgraph_edge_hasher::hash (call_stmt));
+      gcall *old_stmt = direct->call_stmt;
+      for (cgraph_edge *d = direct; d; d = next)
+       {
+         next = d->next_speculative_call_target ();
+         cgraph_edge *d2 = set_call_stmt (d, new_stmt, false);
+         gcc_assert (d2 == d);
+         n++;
+       }
+      gcc_checking_assert (indirect->num_speculative_call_targets_p () == n);
+      for (unsigned int i = 0; e->caller->iterate_reference (i, ref); i++)
+       if (ref->speculative && ref->stmt == old_stmt)
+         {
+           ref->stmt = new_stmt;
+           n--;
+         }
+
+      indirect = set_call_stmt (indirect, new_stmt, false);
+      return e_indirect ? indirect : direct;
     }
 
-  cgraph_edge *e = this;
+  if (new_direct_callee)
+    e = make_direct (e, new_direct_callee);
 
-  call_stmt = new_stmt;
-  if (indirect_unknown_callee
-      && (decl = gimple_call_fndecl (new_stmt)))
-    {
-      /* Constant propagation (and possibly also inlining?) can turn an
-        indirect call into a direct one.  */
-      cgraph_node *new_callee = cgraph_node::get (decl);
+  /* Only direct speculative edges go to call_site_hash.  */
+  if (e->caller->call_site_hash
+      && (!e->speculative || !e->indirect_unknown_callee)
+      /* It is possible that edge was previously speculative.  In this case
+        we have different value in call stmt hash which needs preserving.  */
+      && e->caller->get_edge (e->call_stmt) == e)
+    e->caller->call_site_hash->remove_elt_with_hash
+      (e->call_stmt, cgraph_edge_hasher::hash (e->call_stmt));
 
-      gcc_checking_assert (new_callee);
-      e = make_direct (new_callee);
-    }
+  e->call_stmt = new_stmt;
 
   function *fun = DECL_STRUCT_FUNCTION (e->caller->decl);
   e->can_throw_external = stmt_can_throw_external (fun, new_stmt);
-  if (e->caller->call_site_hash)
+  /* Update call stite hash.  For speculative calls we only record the first
+     direct edge.  */
+  if (e->caller->call_site_hash
+      && (!e->speculative
+         || (e->callee
+             && (!e->prev_callee || !e->prev_callee->speculative
+                 || e->prev_callee->call_stmt != e->call_stmt))
+         || (e->speculative && !e->callee)))
     cgraph_add_edge_to_call_site_hash (e);
+  return e;
 }
 
 /* Allocate a cgraph_edge structure and fill it with data according to the
@@ -861,6 +901,7 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
   edge->prev_callee = NULL;
   edge->next_callee = NULL;
   edge->lto_stmt_uid = 0;
+  edge->speculative_id = 0;
 
   edge->count = count;
   edge->call_stmt = call_stmt;
@@ -877,19 +918,8 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
   edge->can_throw_external
     = call_stmt ? stmt_can_throw_external (DECL_STRUCT_FUNCTION (caller->decl),
                                           call_stmt) : false;
-  if (call_stmt
-      && callee && callee->decl
-      && !gimple_check_call_matching_types (call_stmt, callee->decl,
-                                           false))
-    {
-      edge->inline_failed = CIF_MISMATCHED_ARGUMENTS;
-      edge->call_stmt_cannot_inline_p = true;
-    }
-  else
-    {
-      edge->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
-      edge->call_stmt_cannot_inline_p = false;
-    }
+  edge->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+  edge->call_stmt_cannot_inline_p = false;
 
   if (opt_for_fn (edge->caller->decl, flag_devirtualize)
       && call_stmt && DECL_STRUCT_FUNCTION (caller->decl))
@@ -897,7 +927,13 @@ symbol_table::create_edge (cgraph_node *caller, cgraph_node *callee,
       = decl_maybe_in_construction_p (NULL, NULL, call_stmt,
                                      caller->decl);
   else
-    edge->in_polymorphic_cdtor = caller->thunk.thunk_p;
+    edge->in_polymorphic_cdtor = caller->thunk;
+  if (callee)
+    caller->calls_declare_variant_alt |= callee->declare_variant_alt;
+
+  if (callee && symtab->state != LTO_STREAMING
+      && edge->callee->comdat_local_p ())
+    edge->caller->calls_comdat_local = true;
 
   return edge;
 }
@@ -1004,7 +1040,8 @@ cgraph_edge::remove_caller (void)
       else
        caller->callees = next_callee;
     }
-  if (caller->call_site_hash)
+  if (caller->call_site_hash
+      && this == caller->get_edge (call_stmt))
     caller->call_site_hash->remove_elt_with_hash
        (call_stmt, cgraph_edge_hasher::hash (call_stmt));
 }
@@ -1026,20 +1063,20 @@ symbol_table::free_edge (cgraph_edge *e)
 /* Remove the edge in the cgraph.  */
 
 void
-cgraph_edge::remove (void)
+cgraph_edge::remove (cgraph_edge *edge)
 {
   /* Call all edge removal hooks.  */
-  symtab->call_edge_removal_hooks (this);
+  symtab->call_edge_removal_hooks (edge);
 
-  if (!indirect_unknown_callee)
+  if (!edge->indirect_unknown_callee)
     /* Remove from callers list of the callee.  */
-    remove_callee ();
+    edge->remove_callee ();
 
   /* Remove from callees list of the callers.  */
-  remove_caller ();
+  edge->remove_caller ();
 
   /* Put the edge onto the free list.  */
-  symtab->free_edge (this);
+  symtab->free_edge (edge);
 }
 
 /* Turn edge into speculative call calling N2. Update
@@ -1055,13 +1092,17 @@ cgraph_edge::remove (void)
      call call_dest
 
    At this time the function just creates the direct call,
-   the referencd representing the if conditional and attaches
-   them all to the orginal indirect call statement.  
+   the reference representing the if conditional and attaches
+   them all to the original indirect call statement.  
+
+   speculative_id is used to link direct calls with their corresponding
+   IPA_REF_ADDR references when representing speculative calls.
 
    Return direct edge created.  */
 
 cgraph_edge *
-cgraph_edge::make_speculative (cgraph_node *n2, profile_count direct_count)
+cgraph_edge::make_speculative (cgraph_node *n2, profile_count direct_count,
+                              unsigned int speculative_id)
 {
   cgraph_node *n = caller;
   ipa_ref *ref = NULL;
@@ -1079,90 +1120,102 @@ cgraph_edge::make_speculative (cgraph_node *n2, profile_count direct_count)
   else
     e2->can_throw_external = can_throw_external;
   e2->lto_stmt_uid = lto_stmt_uid;
+  e2->speculative_id = speculative_id;
   e2->in_polymorphic_cdtor = in_polymorphic_cdtor;
+  indirect_info->num_speculative_call_targets++;
   count -= e2->count;
   symtab->call_edge_duplication_hooks (this, e2);
   ref = n->create_reference (n2, IPA_REF_ADDR, call_stmt);
   ref->lto_stmt_uid = lto_stmt_uid;
+  ref->speculative_id = speculative_id;
   ref->speculative = speculative;
   n2->mark_address_taken ();
   return e2;
 }
 
-/* Speculative call consist of three components:
-   1) an indirect edge representing the original call
-   2) an direct edge representing the new call
-   3) ADDR_EXPR reference representing the speculative check.
-   All three components are attached to single statement (the indirect
-   call) and if one of them exists, all of them must exist.
+/* Speculative call consists of an indirect edge and one or more
+   direct edge+ref pairs.
 
-   Given speculative call edge, return all three components.
- */
+   Given an edge which is part of speculative call, return the first
  direct call edge in the speculative call sequence.  */
 
-void
-cgraph_edge::speculative_call_info (cgraph_edge *&direct,
-                                   cgraph_edge *&indirect,
-                                   ipa_ref *&reference)
+cgraph_edge *
+cgraph_edge::first_speculative_call_target ()
 {
-  ipa_ref *ref;
-  int i;
-  cgraph_edge *e2;
   cgraph_edge *e = this;
 
-  if (!e->indirect_unknown_callee)
-    for (e2 = e->caller->indirect_calls;
-        e2->call_stmt != e->call_stmt || e2->lto_stmt_uid != e->lto_stmt_uid;
-        e2 = e2->next_callee)
-      ;
-  else
+  gcc_checking_assert (e->speculative);
+  if (e->callee)
     {
-      e2 = e;
-      /* We can take advantage of the call stmt hash.  */
-      if (e2->call_stmt)
+      while (e->prev_callee && e->prev_callee->speculative
+            && e->prev_callee->call_stmt == e->call_stmt
+            && e->prev_callee->lto_stmt_uid == e->lto_stmt_uid)
+       e = e->prev_callee;
+      return e;
+    }
+  /* Call stmt site hash always points to the first target of the
+     speculative call sequence.  */
+  if (e->call_stmt)
+    return e->caller->get_edge (e->call_stmt);
+  for (cgraph_edge *e2 = e->caller->callees; true; e2 = e2->next_callee)
+    if (e2->speculative
+       && e->call_stmt == e2->call_stmt
+       && e->lto_stmt_uid == e2->lto_stmt_uid)
+      return e2;
+}
+
+/* We always maintain first direct edge in the call site hash, if one
+   exists.  E is going to be removed.  See if it is first one and update
+   hash accordingly.  INDIRECT is the indirect edge of speculative call.
+   We assume that INDIRECT->num_speculative_call_targets_p () is already
+   updated for removal of E.  */
+static void
+update_call_stmt_hash_for_removing_direct_edge (cgraph_edge *e,
+                                               cgraph_edge *indirect)
+{
+  if (e->caller->call_site_hash)
+    {
+      if (e->caller->get_edge (e->call_stmt) != e)
+       ;
+      else if (!indirect->num_speculative_call_targets_p ())
+       cgraph_update_edge_in_call_site_hash (indirect);
+      else
        {
-         e = e->caller->get_edge (e2->call_stmt);
-         gcc_assert (e->speculative && !e->indirect_unknown_callee);
+         gcc_checking_assert (e->next_callee && e->next_callee->speculative
+                              && e->next_callee->call_stmt == e->call_stmt);
+         cgraph_update_edge_in_call_site_hash (e->next_callee);
        }
-      else
-       for (e = e->caller->callees; 
-            e2->call_stmt != e->call_stmt
-            || e2->lto_stmt_uid != e->lto_stmt_uid;
-            e = e->next_callee)
-         ;
-    }
-  gcc_assert (e->speculative && e2->speculative);
-  direct = e;
-  indirect = e2;
-
-  reference = NULL;
-  for (i = 0; e->caller->iterate_reference (i, ref); i++)
-    if (ref->speculative
-       && ((ref->stmt && ref->stmt == e->call_stmt)
-           || (!ref->stmt && ref->lto_stmt_uid == e->lto_stmt_uid)))
-      {
-       reference = ref;
-       break;
-      }
-
-  /* Speculative edge always consist of all three components - direct edge,
-     indirect and reference.  */
-  
-  gcc_assert (e && e2 && ref);
+    }
 }
 
-/* Speculative call edge turned out to be direct call to CALLE_DECL.
-   Remove the speculative call sequence and return edge representing the call.
-   It is up to caller to redirect the call as appropriate. */
+/* Speculative call EDGE turned out to be direct call to CALLEE_DECL.  Remove
+   the speculative call sequence and return edge representing the call, the
+   original EDGE can be removed and deallocated.  Return the edge that now
+   represents the call.
+
+   For "speculative" indirect call that contains multiple "speculative"
+   targets (i.e. edge->indirect_info->num_speculative_call_targets > 1),
+   decrease the count and only remove current direct edge.
+
+   If no speculative direct call left to the speculative indirect call, remove
+   the speculative of both the indirect call and corresponding direct edge.
+
+   It is up to caller to iteratively resolve each "speculative" direct call and
+   redirect the call as appropriate.  */
 
 cgraph_edge *
-cgraph_edge::resolve_speculation (tree callee_decl)
+cgraph_edge::resolve_speculation (cgraph_edge *edge, tree callee_decl)
 {
-  cgraph_edge *edge = this;
   cgraph_edge *e2;
   ipa_ref *ref;
 
-  gcc_assert (edge->speculative);
-  edge->speculative_call_info (e2, edge, ref);
+  gcc_assert (edge->speculative && (!callee_decl || edge->callee));
+  if (!edge->callee)
+    e2 = edge->first_speculative_call_target ();
+  else
+    e2 = edge;
+  ref = e2->speculative_call_target_ref ();
+  edge = edge->speculative_call_indirect_edge ();
   if (!callee_decl
       || !ref->referred->semantically_equivalent_p
           (symtab_node::get (callee_decl)))
@@ -1190,124 +1243,192 @@ cgraph_edge::resolve_speculation (tree callee_decl)
     {
       cgraph_edge *tmp = edge;
       if (dump_file)
-        fprintf (dump_file, "Speculative call turned into direct call.\n");
+       fprintf (dump_file, "Speculative call turned into direct call.\n");
       edge = e2;
       e2 = tmp;
-      /* FIXME:  If EDGE is inlined, we should scale up the frequencies and counts
-         in the functions inlined through it.  */
+      /* FIXME:  If EDGE is inlined, we should scale up the frequencies
+        and counts in the functions inlined through it.  */
     }
   edge->count += e2->count;
-  edge->speculative = false;
+  if (edge->num_speculative_call_targets_p ())
+    {
+      /* The indirect edge has multiple speculative targets, don't remove
+        speculative until all related direct edges are resolved.  */
+      edge->indirect_info->num_speculative_call_targets--;
+      if (!edge->indirect_info->num_speculative_call_targets)
+       edge->speculative = false;
+    }
+  else
+    edge->speculative = false;
   e2->speculative = false;
+  update_call_stmt_hash_for_removing_direct_edge (e2, edge);
   ref->remove_reference ();
   if (e2->indirect_unknown_callee || e2->inline_failed)
-    e2->remove ();
+    remove (e2);
   else
     e2->callee->remove_symbol_and_inline_clones ();
-  if (edge->caller->call_site_hash)
-    cgraph_update_edge_in_call_site_hash (edge);
   return edge;
 }
 
-/* Make an indirect edge with an unknown callee an ordinary edge leading to
-   CALLEE.  DELTA is an integer constant that is to be added to the this
-   pointer (first parameter) to compensate for skipping a thunk adjustment.  */
+/* Return edge corresponding to speculative call to a given target.
+   NULL if speculative call does not have one.  */
 
 cgraph_edge *
-cgraph_edge::make_direct (cgraph_node *callee)
+cgraph_edge::speculative_call_for_target (cgraph_node *target)
 {
-  cgraph_edge *edge = this;
-  gcc_assert (indirect_unknown_callee);
+  for (cgraph_edge *direct = first_speculative_call_target ();
+       direct;
+       direct = direct->next_speculative_call_target ())
+    if (direct->speculative_call_target_ref ()
+       ->referred->semantically_equivalent_p (target))
+      return direct;
+  return NULL;
+}
+
+/* Make an indirect or speculative EDGE with an unknown callee an ordinary edge
+   leading to CALLEE.  Speculations can be resolved in the process and EDGE can
+   be removed and deallocated.  Return the edge that now represents the
+   call.  */
+
+cgraph_edge *
+cgraph_edge::make_direct (cgraph_edge *edge, cgraph_node *callee)
+{
+  gcc_assert (edge->indirect_unknown_callee || edge->speculative);
 
   /* If we are redirecting speculative call, make it non-speculative.  */
-  if (indirect_unknown_callee && speculative)
+  if (edge->speculative)
     {
-      edge = edge->resolve_speculation (callee->decl);
+      cgraph_edge *found = NULL;
+      cgraph_edge *direct, *next;
+
+      edge = edge->speculative_call_indirect_edge ();
 
-      /* On successful speculation just return the pre existing direct edge.  */
-      if (!edge->indirect_unknown_callee)
-        return edge;
+      /* Look all speculative targets and remove all but one corresponding
+        to callee (if it exists).  */
+      for (direct = edge->first_speculative_call_target ();
+          direct;
+          direct = next)
+       {
+         next = direct->next_speculative_call_target ();
+
+         /* Compare ref not direct->callee.  Direct edge is possibly
+            inlined or redirected.  */
+         if (!direct->speculative_call_target_ref ()
+              ->referred->semantically_equivalent_p (callee))
+           edge = direct->resolve_speculation (direct, NULL);
+         else
+           {
+             gcc_checking_assert (!found);
+             found = direct;
+           }
+       }
+
+      /* On successful speculation just remove the indirect edge and
+        return the pre existing direct edge.
+        It is important to not remove it and redirect because the direct
+        edge may be inlined or redirected.  */
+      if (found)
+       {
+         cgraph_edge *e2 = resolve_speculation (found, callee->decl);
+         gcc_checking_assert (!found->speculative && e2 == found);
+         return found;
+       }
+      gcc_checking_assert (!edge->speculative);
     }
 
-  indirect_unknown_callee = 0;
-  ggc_free (indirect_info);
-  indirect_info = NULL;
+  edge->indirect_unknown_callee = 0;
+  ggc_free (edge->indirect_info);
+  edge->indirect_info = NULL;
 
   /* Get the edge out of the indirect edge list. */
-  if (prev_callee)
-    prev_callee->next_callee = next_callee;
-  if (next_callee)
-    next_callee->prev_callee = prev_callee;
-  if (!prev_callee)
-    caller->indirect_calls = next_callee;
+  if (edge->prev_callee)
+    edge->prev_callee->next_callee = edge->next_callee;
+  if (edge->next_callee)
+    edge->next_callee->prev_callee = edge->prev_callee;
+  if (!edge->prev_callee)
+    edge->caller->indirect_calls = edge->next_callee;
 
   /* Put it into the normal callee list */
-  prev_callee = NULL;
-  next_callee = caller->callees;
-  if (caller->callees)
-    caller->callees->prev_callee = edge;
-  caller->callees = edge;
+  edge->prev_callee = NULL;
+  edge->next_callee = edge->caller->callees;
+  if (edge->caller->callees)
+    edge->caller->callees->prev_callee = edge;
+  edge->caller->callees = edge;
 
   /* Insert to callers list of the new callee.  */
   edge->set_callee (callee);
 
-  if (call_stmt
-      && !gimple_check_call_matching_types (call_stmt, callee->decl, false))
-    {
-      call_stmt_cannot_inline_p = true;
-      inline_failed = CIF_MISMATCHED_ARGUMENTS;
-    }
-
   /* We need to re-determine the inlining status of the edge.  */
   initialize_inline_failed (edge);
   return edge;
 }
 
+/* Redirect callee of the edge to N.  The function does not update underlying
+   call expression.  */
+
+void
+cgraph_edge::redirect_callee (cgraph_node *n)
+{
+  bool loc = callee->comdat_local_p ();
+  /* Remove from callers list of the current callee.  */
+  remove_callee ();
+
+  /* Insert to callers list of the new callee.  */
+  set_callee (n);
+
+  if (!inline_failed)
+    return;
+  if (!loc && n->comdat_local_p ())
+    {
+      cgraph_node *to = caller->inlined_to ? caller->inlined_to : caller;
+      to->calls_comdat_local = true;
+    }
+  else if (loc && !n->comdat_local_p ())
+    {
+      cgraph_node *to = caller->inlined_to ? caller->inlined_to : caller;
+      gcc_checking_assert (to->calls_comdat_local);
+      to->calls_comdat_local = to->check_calls_comdat_local_p ();
+    }
+}
+
 /* If necessary, change the function declaration in the call statement
-   associated with E so that it corresponds to the edge callee.  */
+   associated with E so that it corresponds to the edge callee.  Speculations
+   can be resolved in the process and EDGE can be removed and deallocated.
+
+   The edge could be one of speculative direct call generated from speculative
+   indirect call.  In this circumstance, decrease the speculative targets
+   count (i.e. num_speculative_call_targets) and redirect call stmt to the
+   corresponding i-th target.  If no speculative direct call left to the
+   speculative indirect call, remove "speculative" of the indirect call and
+   also redirect stmt to it's final direct target.
+
+   It is up to caller to iteratively transform each "speculative"
+   direct call as appropriate.  */
 
 gimple *
-cgraph_edge::redirect_call_stmt_to_callee (void)
+cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
 {
-  cgraph_edge *e = this;
-
   tree decl = gimple_call_fndecl (e->call_stmt);
   gcall *new_stmt;
   gimple_stmt_iterator gsi;
 
   if (e->speculative)
     {
-      cgraph_edge *e2;
-      gcall *new_stmt;
-      ipa_ref *ref;
-
-      e->speculative_call_info (e, e2, ref);
       /* If there already is an direct call (i.e. as a result of inliner's
         substitution), forget about speculating.  */
       if (decl)
-       e = e->resolve_speculation (decl);
-      /* If types do not match, speculation was likely wrong. 
-         The direct edge was possibly redirected to the clone with a different
-        signature.  We did not update the call statement yet, so compare it 
-        with the reference that still points to the proper type.  */
-      else if (!gimple_check_call_matching_types (e->call_stmt,
-                                                 ref->referred->decl,
-                                                 true))
-       {
-         if (dump_file)
-           fprintf (dump_file, "Not expanding speculative call of %s -> %s\n"
-                    "Type mismatch.\n",
-                    e->caller->dump_name (),
-                    e->callee->dump_name ());
-         e = e->resolve_speculation ();
-         /* We are producing the final function body and will throw away the
-            callgraph edges really soon.  Reset the counts/frequencies to
-            keep verifier happy in the case of roundoff errors.  */
-         e->count = gimple_bb (e->call_stmt)->count;
-       }
-      /* Expand speculation into GIMPLE code.  */
+       e = make_direct (e->speculative_call_indirect_edge (),
+                        cgraph_node::get (decl));
       else
        {
+         /* Be sure we redirect all speculative targets before poking
+            abou tindirect edge.  */
+         gcc_checking_assert (e->callee);
+         cgraph_edge *indirect = e->speculative_call_indirect_edge ();
+         gcall *new_stmt;
+         ipa_ref *ref;
+
+         /* Expand speculation into GIMPLE code.  */
          if (dump_file)
            {
              fprintf (dump_file,
@@ -1317,28 +1438,45 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
              e->count.dump (dump_file);
              fprintf (dump_file, "\n");
            }
-         gcc_assert (e2->speculative);
          push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
 
-         profile_probability prob = e->count.probability_in (e->count
-                                                             + e2->count);
+         profile_count all = indirect->count;
+         for (cgraph_edge *e2 = e->first_speculative_call_target ();
+              e2;
+              e2 = e2->next_speculative_call_target ())
+           all = all + e2->count;
+         profile_probability prob = e->count.probability_in (all);
          if (!prob.initialized_p ())
            prob = profile_probability::even ();
+         ref = e->speculative_call_target_ref ();
          new_stmt = gimple_ic (e->call_stmt,
                                dyn_cast<cgraph_node *> (ref->referred),
                                prob);
          e->speculative = false;
-         e->caller->set_call_stmt_including_clones (e->call_stmt, new_stmt,
-                                                    false);
+         if (indirect->num_speculative_call_targets_p ())
+           {
+             /* The indirect edge has multiple speculative targets, don't
+                remove speculative until all related direct edges are
+                redirected.  */
+             indirect->indirect_info->num_speculative_call_targets--;
+             if (!indirect->indirect_info->num_speculative_call_targets)
+               indirect->speculative = false;
+           }
+         else
+           indirect->speculative = false;
+         /* Indirect edges are not both in the call site hash.
+            get it updated.  */
+         update_call_stmt_hash_for_removing_direct_edge (e, indirect);
+         cgraph_edge::set_call_stmt (e, new_stmt, false);
          e->count = gimple_bb (e->call_stmt)->count;
-         e2->speculative = false;
-         e2->count = gimple_bb (e2->call_stmt)->count;
+
+         /* Once we are done with expanding the sequence, update also indirect
+            call probability.  Until then the basic block accounts for the
+            sum of indirect edge and all non-expanded speculations.  */
+         if (!indirect->speculative)
+           indirect->count = gimple_bb (indirect->call_stmt)->count;
          ref->speculative = false;
          ref->stmt = NULL;
-         /* Indirect edges are not both in the call site hash.
-            get it updated.  */
-         if (e->caller->call_site_hash)
-           cgraph_update_edge_in_call_site_hash (e2);
          pop_cfun ();
          /* Continue redirecting E to proper target.  */
        }
@@ -1349,37 +1487,39 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
       || decl == e->callee->decl)
     return e->call_stmt;
 
+  if (decl && ipa_saved_clone_sources)
+    {
+      tree *p = ipa_saved_clone_sources->get (e->callee);
+      if (p && decl == *p)
+       {
+         gimple_call_set_fndecl (e->call_stmt, e->callee->decl);
+         return e->call_stmt;
+       }
+    }
   if (flag_checking && decl)
     {
-      cgraph_node *node = cgraph_node::get (decl);
-      gcc_assert (!node || !node->clone.param_adjustments);
+      if (cgraph_node *node = cgraph_node::get (decl))
+       {
+         clone_info *info = clone_info::get (node);
+         gcc_assert (!info || !info->param_adjustments);
+       }
     }
 
+  clone_info *callee_info = clone_info::get (e->callee);
   if (symtab->dump_file)
     {
       fprintf (symtab->dump_file, "updating call of %s -> %s: ",
               e->caller->dump_name (), e->callee->dump_name ());
       print_gimple_stmt (symtab->dump_file, e->call_stmt, 0, dump_flags);
-      if (e->callee->clone.param_adjustments)
-       e->callee->clone.param_adjustments->dump (symtab->dump_file);
-      unsigned performed_len
-       = vec_safe_length (e->caller->clone.performed_splits);
-      if (performed_len > 0)
-       fprintf (symtab->dump_file, "Performed splits records:\n");
-      for (unsigned i = 0; i < performed_len; i++)
-       {
-         ipa_param_performed_split *sm
-           = &(*e->caller->clone.performed_splits)[i];
-         print_node_brief (symtab->dump_file, "  dummy_decl: ", sm->dummy_decl,
-                           TDF_UID);
-         fprintf (symtab->dump_file, ", unit_offset: %u\n", sm->unit_offset);
-       }
+      if (callee_info && callee_info->param_adjustments)
+       callee_info->param_adjustments->dump (symtab->dump_file);
     }
 
-  if (ipa_param_adjustments *padjs = e->callee->clone.param_adjustments)
+  if (ipa_param_adjustments *padjs
+        = callee_info ? callee_info->param_adjustments : NULL)
     {
       /* We need to defer cleaning EH info on the new statement to
-         fixup-cfg.  We may not have dominator information at this point
+        fixup-cfg.  We may not have dominator information at this point
         and thus would end up with unreachable blocks and have no way
         to communicate that we need to run CFG cleanup then.  */
       int lp_nr = lookup_stmt_eh_lp (e->call_stmt);
@@ -1387,9 +1527,7 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
        remove_stmt_from_eh_lp (e->call_stmt);
 
       tree old_fntype = gimple_call_fntype (e->call_stmt);
-      new_stmt = padjs->modify_call (e->call_stmt,
-                                    e->caller->clone.performed_splits,
-                                    e->callee->decl, false);
+      new_stmt = padjs->modify_call (e, false);
       cgraph_node *origin = e->callee;
       while (origin->clone_of)
        origin = origin->clone_of;
@@ -1409,6 +1547,9 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
     }
   else
     {
+      if (flag_checking
+         && !fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
+       ipa_verify_edge_has_no_modifications (e);
       new_stmt = e->call_stmt;
       gimple_call_set_fndecl (new_stmt, e->callee->decl);
       update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt);
@@ -1437,7 +1578,7 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
          var = get_or_create_ssa_default_def
                  (DECL_STRUCT_FUNCTION (e->caller->decl), var);
          gimple *set_stmt = gimple_build_assign (lhs, var);
-          gsi = gsi_for_stmt (new_stmt);
+         gsi = gsi_for_stmt (new_stmt);
          gsi_insert_before_without_update (&gsi, set_stmt, GSI_SAME_STMT);
          update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), set_stmt);
        }
@@ -1496,8 +1637,8 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node *node,
          if (new_stmt && is_gimple_call (new_stmt) && e->callee
              && fndecl_built_in_p (e->callee->decl, BUILT_IN_UNREACHABLE))
            {
-              node->get_edge (old_stmt)->set_call_stmt
-                (as_a <gcall *> (new_stmt));
+             cgraph_edge::set_call_stmt (node->get_edge (old_stmt),
+                                         as_a <gcall *> (new_stmt));
              return;
            }
          /* See if the edge is already there and has the correct callee.  It
@@ -1511,7 +1652,7 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node *node,
                  if (callee->decl == new_call
                      || callee->former_clone_of == new_call)
                    {
-                     e->set_call_stmt (as_a <gcall *> (new_stmt));
+                     cgraph_edge::set_call_stmt (e, as_a <gcall *> (new_stmt));
                      return;
                    }
                  callee = callee->clone_of;
@@ -1523,7 +1664,7 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node *node,
             attached to edge is invalid.  */
          count = e->count;
          if (e->indirect_unknown_callee || e->inline_failed)
-           e->remove ();
+           cgraph_edge::remove (e);
          else
            e->callee->remove_symbol_and_inline_clones ();
        }
@@ -1543,7 +1684,8 @@ cgraph_update_edges_for_call_stmt_node (cgraph_node *node,
     }
   /* We only updated the call stmt; update pointer in cgraph edge..  */
   else if (old_stmt != new_stmt)
-    node->get_edge (old_stmt)->set_call_stmt (as_a <gcall *> (new_stmt));
+    cgraph_edge::set_call_stmt (node->get_edge (old_stmt),
+                               as_a <gcall *> (new_stmt));
 }
 
 /* Update or remove the corresponding cgraph edge if a GIMPLE_CALL
@@ -1562,7 +1704,8 @@ cgraph_update_edges_for_call_stmt (gimple *old_stmt, tree old_decl,
   if (orig->clones)
     for (node = orig->clones; node != orig;)
       {
-        cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl, new_stmt);
+       cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl,
+                                               new_stmt);
        if (node->clones)
          node = node->clones;
        else if (node->next_sibling_clone)
@@ -1585,6 +1728,8 @@ cgraph_node::remove_callees (void)
 {
   cgraph_edge *e, *f;
 
+  calls_comdat_local = false;
+
   /* It is sufficient to remove the edges from the lists of callers of
      the callees.  The callee list of the node can be zapped with one
      assignment.  */
@@ -1659,14 +1804,14 @@ release_function_body (tree decl)
          gcc_assert (!dom_info_available_p (fn, CDI_DOMINATORS));
          gcc_assert (!dom_info_available_p (fn, CDI_POST_DOMINATORS));
          delete_tree_cfg_annotations (fn);
-         clear_edges (fn);
+         free_cfg (fn);
          fn->cfg = NULL;
        }
       if (fn->value_histograms)
        free_histograms (fn);
       gimple_set_body (decl, NULL);
       /* Struct function hangs a lot of data that would leak if we didn't
-         removed all pointers to it.   */
+        removed all pointers to it.   */
       ggc_free (fn);
       DECL_STRUCT_FUNCTION (decl) = NULL;
     }
@@ -1701,6 +1846,17 @@ cgraph_node::release_body (bool keep_arguments)
       lto_free_function_in_decl_state_for_node (this);
       lto_file_data = NULL;
     }
+  if (flag_checking && clones)
+    {
+      /* It is invalid to release body before materializing clones except
+        for thunks that don't really need a body.  Verify also that we do
+        not leak pointers to the call statements.  */
+      for (cgraph_node *node = clones; node;
+          node = node->next_sibling_clone)
+       gcc_assert (node->thunk && !node->callees->call_stmt);
+    }
+  remove_callees ();
+  remove_all_references ();
 }
 
 /* Remove function from symbol table.  */
@@ -1708,12 +1864,19 @@ cgraph_node::release_body (bool keep_arguments)
 void
 cgraph_node::remove (void)
 {
+  bool clone_info_set = false;
+  clone_info *info, saved_info;
   if (symtab->ipa_clones_dump_file && symtab->cloned_nodes.contains (this))
     fprintf (symtab->ipa_clones_dump_file,
             "Callgraph removal;%s;%d;%s;%d;%d\n", asm_name (), order,
             DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl),
             DECL_SOURCE_COLUMN (decl));
 
+  if ((info = clone_info::get (this)) != NULL)
+    {
+      saved_info = *info;
+      clone_info_set = true;
+    }
   symtab->call_cgraph_removal_hooks (this);
   remove_callers ();
   remove_callees ();
@@ -1724,23 +1887,8 @@ cgraph_node::remove (void)
      */
   force_output = false;
   forced_by_abi = false;
-  cgraph_node *next;
-  for (cgraph_node *n = nested; n; n = next)
-  {
-    next = n->next_nested;
-    n->origin = NULL;
-    n->next_nested = NULL;
-  }
-  nested = NULL;
-  if (origin)
-    {
-      cgraph_node **node2 = &origin->nested;
 
-      while (*node2 != this)
-       node2 = &(*node2)->next_nested;
-      *node2 = next_nested;
-    }
-  unregister ();
+  unregister (clone_info_set ? &saved_info : NULL);
   if (prev_sibling_clone)
     prev_sibling_clone->next_sibling_clone = next_sibling_clone;
   else if (clone_of)
@@ -1752,7 +1900,7 @@ cgraph_node::remove (void)
       cgraph_node *n, *next;
 
       if (clone_of)
-        {
+       {
          for (n = clones; n->next_sibling_clone; n = n->next_sibling_clone)
            n->clone_of = clone_of;
          n->clone_of = clone_of;
@@ -1762,7 +1910,7 @@ cgraph_node::remove (void)
          clone_of->clones = clones;
        }
       else
-        {
+       {
          /* We are removing node with clones.  This makes clones inconsistent,
             but assume they will be removed subsequently and just keep clone
             tree intact.  This can happen in unreachable function removal since
@@ -1935,6 +2083,20 @@ cgraph_edge::dump_edge_flags (FILE *f)
     fprintf (f, "(can throw external) ");
 }
 
+/* Dump edge to stderr.  */
+
+void
+cgraph_edge::debug (void)
+{
+  fprintf (stderr, "%s -> %s ", caller->dump_asm_name (),
+          callee == NULL ? "(null)" : callee->dump_asm_name ());
+  dump_edge_flags (stderr);
+  fprintf (stderr, "\n\n");
+  caller->debug ();
+  if (callee != NULL)
+    callee->debug ();
+}
+
 /* Dump call graph node to file F.  */
 
 void
@@ -1957,6 +2119,9 @@ cgraph_node::dump (FILE *f)
   if (profile_id)
     fprintf (f, "  Profile id: %i\n",
             profile_id);
+  if (unit_id)
+    fprintf (f, "  Unit id: %i\n",
+            unit_id);
   cgraph_function_version_info *vi = function_version ();
   if (vi != NULL)
     {
@@ -1984,9 +2149,9 @@ cgraph_node::dump (FILE *f)
       count.dump (f);
     }
   if (tp_first_run > 0)
-    fprintf (f, " first_run:%i", tp_first_run);
-  if (origin)
-    fprintf (f, " nested in:%s", origin->asm_name ());
+    fprintf (f, " first_run:%" PRId64, (int64_t) tp_first_run);
+  if (cgraph_node *origin = nested_function_origin (this))
+    fprintf (f, " nested in:%s", origin->dump_asm_name ());
   if (gimple_has_body_p (decl))
     fprintf (f, " body");
   if (process)
@@ -2007,6 +2172,8 @@ cgraph_node::dump (FILE *f)
     fprintf (f, " icf_merged");
   if (merged_comdat)
     fprintf (f, " merged_comdat");
+  if (merged_extern_inline)
+    fprintf (f, " merged_extern_inline");
   if (split_part)
     fprintf (f, " split_part");
   if (indirect_call_target)
@@ -2027,52 +2194,35 @@ cgraph_node::dump (FILE *f)
     fprintf (f, " optimize_size");
   if (parallelized_function)
     fprintf (f, " parallelized_function");
+  if (DECL_IS_MALLOC (decl))
+    fprintf (f, " decl_is_malloc");
   if (DECL_IS_OPERATOR_NEW_P (decl))
-    fprintf (f, " operator_new");
+    fprintf (f, " %soperator_new",
+            DECL_IS_REPLACEABLE_OPERATOR (decl) ? "replaceable_" : "");
   if (DECL_IS_OPERATOR_DELETE_P (decl))
-    fprintf (f, " operator_delete");
-
+    fprintf (f, " %soperator_delete",
+            DECL_IS_REPLACEABLE_OPERATOR (decl) ? "replaceable_" : "");
 
   fprintf (f, "\n");
 
-  if (thunk.thunk_p)
+  if (thunk)
     {
       fprintf (f, "  Thunk");
-      if (thunk.alias)
-       fprintf (f, "  of %s (asm:%s)",
-                lang_hooks.decl_printable_name (thunk.alias, 2),
-                IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk.alias)));
-      fprintf (f, " fixed offset %i virtual value %i indirect_offset %i "
-                 "has virtual offset %i\n",
-              (int)thunk.fixed_offset,
-              (int)thunk.virtual_value,
-              (int)thunk.indirect_offset,
-              (int)thunk.virtual_offset_p);
+      thunk_info::get (this)->dump (f);
     }
   else if (former_thunk_p ())
-    fprintf (f, "  Former thunk fixed offset %i virtual value %i "
-            "indirect_offset %i has virtual offset %i\n",
-            (int)thunk.fixed_offset,
-            (int)thunk.virtual_value,
-            (int)thunk.indirect_offset,
-            (int)thunk.virtual_offset_p);
-  if (alias && thunk.alias
-      && DECL_P (thunk.alias))
-    {
-      fprintf (f, "  Alias of %s",
-              lang_hooks.decl_printable_name (thunk.alias, 2));
-      if (DECL_ASSEMBLER_NAME_SET_P (thunk.alias))
-       fprintf (f, " (asm:%s)",
-                IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk.alias)));
-      fprintf (f, "\n");
+    {
+      fprintf (f, "  Former thunk ");
+      thunk_info::get (this)->dump (f);
     }
+  else gcc_checking_assert (!thunk_info::get (this));
   
   fprintf (f, "  Called by: ");
 
   profile_count sum = profile_count::zero ();
   for (edge = callers; edge; edge = edge->next_caller)
     {
-      fprintf (f, "%s ", edge->caller->dump_name ());
+      fprintf (f, "%s ", edge->caller->dump_asm_name ());
       edge->dump_edge_flags (f);
       if (edge->count.initialized_p ())
        sum += edge->count.ipa ();
@@ -2081,12 +2231,12 @@ cgraph_node::dump (FILE *f)
   fprintf (f, "\n  Calls: ");
   for (edge = callees; edge; edge = edge->next_callee)
     {
-      fprintf (f, "%s ", edge->callee->dump_name ());
+      fprintf (f, "%s ", edge->callee->dump_asm_name ());
       edge->dump_edge_flags (f);
     }
   fprintf (f, "\n");
 
-  if (count.ipa ().initialized_p ())
+  if (!body_removed && count.ipa ().initialized_p ())
     {
       bool ok = true;
       bool min = false;
@@ -2095,7 +2245,7 @@ cgraph_node::dump (FILE *f)
       FOR_EACH_ALIAS (this, ref)
        if (dyn_cast <cgraph_node *> (ref->referring)->count.initialized_p ())
          sum += dyn_cast <cgraph_node *> (ref->referring)->count.ipa ();
-  
+
       if (inlined_to
          || (symtab->state < EXPANSION
              && ultimate_alias_target () == this && only_called_directly_p ()))
@@ -2120,25 +2270,26 @@ cgraph_node::dump (FILE *f)
     {
       if (edge->indirect_info->polymorphic)
        {
-          fprintf (f, "   Polymorphic indirect call of type ");
+         fprintf (f, "   Polymorphic indirect call of type ");
          print_generic_expr (f, edge->indirect_info->otr_type, TDF_SLIM);
          fprintf (f, " token:%i", (int) edge->indirect_info->otr_token);
        }
       else
-        fprintf (f, "   Indirect call");
+       fprintf (f, "   Indirect call");
       edge->dump_edge_flags (f);
       if (edge->indirect_info->param_index != -1)
        {
-         fprintf (f, " of param:%i", edge->indirect_info->param_index);
+         fprintf (f, "of param:%i ", edge->indirect_info->param_index);
          if (edge->indirect_info->agg_contents)
-          fprintf (f, " loaded from %s %s at offset %i",
+          fprintf (f, "loaded from %s %s at offset %i ",
                    edge->indirect_info->member_ptr ? "member ptr" : "aggregate",
                    edge->indirect_info->by_ref ? "passed by reference":"",
                    (int)edge->indirect_info->offset);
          if (edge->indirect_info->vptr_changed)
-           fprintf (f, " (vptr maybe changed)");
+           fprintf (f, "(vptr maybe changed) ");
        }
-      fprintf (f, "\n");
+      fprintf (f, "num speculative call targets: %i\n",
+              edge->indirect_info->num_speculative_call_targets);
       if (edge->indirect_info->polymorphic)
        edge->indirect_info->context.dump (f);
     }
@@ -2190,19 +2341,6 @@ cgraph_function_possibly_inlined_p (tree decl)
   return DECL_POSSIBLY_INLINED (decl);
 }
 
-/* cgraph_node is no longer nested function; update cgraph accordingly.  */
-void
-cgraph_node::unnest (void)
-{
-  cgraph_node **node2 = &origin->nested;
-  gcc_assert (origin);
-
-  while (*node2 != this)
-    node2 = &(*node2)->next_nested;
-  *node2 = next_nested;
-  origin = NULL;
-}
-
 /* Return function availability.  See cgraph.h for description of individual
    return values.  */
 enum availability
@@ -2215,7 +2353,7 @@ cgraph_node::get_availability (symtab_node *ref)
        ref = cref->inlined_to;
     }
   enum availability avail;
-  if (!analyzed)
+  if (!analyzed && !in_other_partition)
     avail = AVAIL_NOT_AVAILABLE;
   else if (local)
     avail = AVAIL_LOCAL;
@@ -2234,8 +2372,8 @@ cgraph_node::get_availability (symtab_node *ref)
 
      Also comdat groups are always resolved in groups.  */
   else if ((this == ref && !has_aliases_p ())
-           || (ref && get_comdat_group ()
-               && get_comdat_group () == ref->get_comdat_group ()))
+          || (ref && get_comdat_group ()
+              && get_comdat_group () == ref->get_comdat_group ()))
     avail = AVAIL_AVAILABLE;
   /* Inline functions are safe to be analyzed even if their symbol can
      be overwritten at runtime.  It is not meaningful to enforce any sane
@@ -2261,6 +2399,10 @@ static bool
 cgraph_node_cannot_be_local_p_1 (cgraph_node *node, void *)
 {
   return !(!node->force_output
+          && !node->ifunc_resolver
+          /* Limitation of gas requires us to output targets of symver aliases
+             as global symbols.  This is binutils PR 25295.  */
+          && !node->symver
           && ((DECL_COMDAT (node->decl)
                && !node->forced_by_abi
                && !node->used_from_object_file_p ()
@@ -2299,7 +2441,7 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
       || (avail = get_availability ()) > AVAIL_INTERPOSABLE)
     {
       if (callback (this, data))
-        return true;
+       return true;
     }
   FOR_EACH_ALIAS (this, ref)
     {
@@ -2314,11 +2456,11 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
   if (avail <= AVAIL_INTERPOSABLE)
     return false;
   for (e = callers; e; e = e->next_caller)
-    if (e->caller->thunk.thunk_p
+    if (e->caller->thunk
        && (include_overwritable
            || e->caller->get_availability () > AVAIL_INTERPOSABLE)
        && !(exclude_virtual_thunks
-            && e->caller->thunk.virtual_offset_p))
+            && thunk_info::get (e->caller)->virtual_offset_p))
       if (e->caller->call_for_symbol_thunks_and_aliases (callback, data,
                                                       include_overwritable,
                                                       exclude_virtual_thunks))
@@ -2370,7 +2512,7 @@ set_nothrow_flag_1 (cgraph_node *node, bool nothrow, bool non_call,
   if (nothrow && !TREE_NOTHROW (node->decl))
     {
       /* With non-call exceptions we can't say for sure if other function body
-        was not possibly optimized to stil throw.  */
+        was not possibly optimized to still throw.  */
       if (!non_call || node->binds_to_current_def_p ())
        {
          TREE_NOTHROW (node->decl) = true;
@@ -2392,7 +2534,7 @@ set_nothrow_flag_1 (cgraph_node *node, bool nothrow, bool non_call,
        set_nothrow_flag_1 (alias, nothrow, non_call, changed);
     }
   for (cgraph_edge *e = node->callers; e; e = e->next_caller)
-    if (e->caller->thunk.thunk_p
+    if (e->caller->thunk
        && (!nothrow || e->caller->get_availability () > AVAIL_INTERPOSABLE))
       set_nothrow_flag_1 (e->caller, nothrow, non_call, changed);
 }
@@ -2441,7 +2583,7 @@ set_malloc_flag_1 (cgraph_node *node, bool malloc_p, bool *changed)
     }
 
   for (cgraph_edge *e = node->callers; e; e = e->next_caller)
-    if (e->caller->thunk.thunk_p
+    if (e->caller->thunk
        && (!malloc_p || e->caller->get_availability () > AVAIL_INTERPOSABLE))
       set_malloc_flag_1 (e->caller, malloc_p, changed);
 }
@@ -2494,8 +2636,8 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
     {
       if (TREE_READONLY (node->decl))
        {
-          TREE_READONLY (node->decl) = 0;
-          DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+         TREE_READONLY (node->decl) = 0;
+         DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
          *changed = true;
        }
     }
@@ -2522,14 +2664,14 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
        {
          if (!looping && DECL_LOOPING_CONST_OR_PURE_P (node->decl))
            {
-              DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+             DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
              *changed = true;
            }
        }
       else if (node->binds_to_current_def_p ())
        {
          TREE_READONLY (node->decl) = true;
-          DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
+         DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
          DECL_PURE_P (node->decl) = false;
          *changed = true;
        }
@@ -2541,12 +2683,12 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
          if (!DECL_PURE_P (node->decl))
            {
              DECL_PURE_P (node->decl) = true;
-              DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
+             DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
              *changed = true;
            }
          else if (!looping && DECL_LOOPING_CONST_OR_PURE_P (node->decl))
            {
-              DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+             DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
              *changed = true;
            }
        }
@@ -2560,14 +2702,14 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
        set_const_flag_1 (alias, set_const, looping, changed);
     }
   for (cgraph_edge *e = node->callers; e; e = e->next_caller)
-    if (e->caller->thunk.thunk_p
+    if (e->caller->thunk
        && (!set_const || e->caller->get_availability () > AVAIL_INTERPOSABLE))
       {
        /* Virtual thunks access virtual offset in the vtable, so they can
           only be pure, never const.  */
-        if (set_const
-           && (e->caller->thunk.virtual_offset_p
-               || !node->binds_to_current_def_p (e->caller)))
+       if (set_const
+           && (thunk_info::get (e->caller)->virtual_offset_p
+               || !node->binds_to_current_def_p (e->caller)))
          *changed |= e->caller->set_pure_flag (true, looping);
        else
          set_const_flag_1 (e->caller, set_const, looping, changed);
@@ -2578,7 +2720,7 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
    If SET_CONST if false, clear the flag.
 
    When setting the flag be careful about possible interposition and
-   do not set the flag for functions that can be interposet and set pure
+   do not set the flag for functions that can be interposed and set pure
    flag for functions that can bind to other definition. 
 
    Return true if any change was done. */
@@ -2637,14 +2779,14 @@ set_pure_flag_1 (cgraph_node *node, void *data)
     {
       if (!DECL_PURE_P (node->decl) && !TREE_READONLY (node->decl))
        {
-          DECL_PURE_P (node->decl) = true;
-          DECL_LOOPING_CONST_OR_PURE_P (node->decl) = info->looping;
+         DECL_PURE_P (node->decl) = true;
+         DECL_LOOPING_CONST_OR_PURE_P (node->decl) = info->looping;
          info->changed = true;
        }
       else if (DECL_LOOPING_CONST_OR_PURE_P (node->decl)
               && !info->looping)
        {
-          DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+         DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
          info->changed = true;
        }
     }
@@ -2652,8 +2794,8 @@ set_pure_flag_1 (cgraph_node *node, void *data)
     {
       if (DECL_PURE_P (node->decl))
        {
-          DECL_PURE_P (node->decl) = false;
-          DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
+         DECL_PURE_P (node->decl) = false;
+         DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
          info->changed = true;
        }
     }
@@ -2730,14 +2872,18 @@ cgraph_edge::maybe_hot_p (void)
     return false;
   if (caller->frequency == NODE_FREQUENCY_HOT)
     return true;
-  /* If profile is now known yet, be conservative.
-     FIXME: this predicate is used by early inliner and can do better there.  */
-  if (symtab->state < IPA_SSA)
+  if (!count.initialized_p ())
     return true;
-  if (caller->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-      && sreal_frequency () * 2 < 3)
+  cgraph_node *where = caller->inlined_to ? caller->inlined_to : caller;
+  if (!where->count.initialized_p ())
     return false;
-  if (sreal_frequency () * PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION) <= 1)
+  if (caller->frequency == NODE_FREQUENCY_EXECUTED_ONCE)
+    {
+      if (count.apply_scale (2, 1) < where->count.apply_scale (3, 1))
+       return false;
+    }
+  else if (count.apply_scale (param_hot_bb_frequency_fraction , 1)
+          < where->count)
     return false;
   return true;
 }
@@ -2772,7 +2918,7 @@ cgraph_node::can_remove_if_no_direct_calls_p (bool will_inline)
   if (will_inline && address_taken)
     return false;
 
-  /* Otheriwse check if we can remove the symbol itself and then verify
+  /* Otherwise check if we can remove the symbol itself and then verify
      that only uses of the comdat groups are direct call to THIS
      or its aliases.   */
   if (!can_remove_if_no_direct_calls_and_refs_p ())
@@ -2803,7 +2949,7 @@ cgraph_node::can_remove_if_no_direct_calls_p (bool will_inline)
       /* If function is not being inlined, we care only about
         references outside of the comdat group.  */
       if (!will_inline)
-        for (int i = 0; next->iterate_referring (i, ref); i++)
+       for (int i = 0; next->iterate_referring (i, ref); i++)
          if (ref->referring->get_comdat_group () != get_comdat_group ())
            return false;
     }
@@ -2906,18 +3052,18 @@ collect_callers_of_node_1 (cgraph_node *node, void *data)
   if (avail > AVAIL_INTERPOSABLE)
     for (cs = node->callers; cs != NULL; cs = cs->next_caller)
       if (!cs->indirect_inlining_edge
-         && !cs->caller->thunk.thunk_p)
-        redirect_callers->safe_push (cs);
+         && !cs->caller->thunk)
+       redirect_callers->safe_push (cs);
   return false;
 }
 
 /* Collect all callers of cgraph_node and its aliases that are known to lead to
    cgraph_node (i.e. are not overwritable).  */
 
-vec<cgraph_edge *>
+auto_vec<cgraph_edge *>
 cgraph_node::collect_callers (void)
 {
-  vec<cgraph_edge *> redirect_callers = vNULL;
+  auto_vec<cgraph_edge *> redirect_callers;
   call_for_symbol_thunks_and_aliases (collect_callers_of_node_1,
                                    &redirect_callers, false);
   return redirect_callers;
@@ -2937,9 +3083,11 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
       || node2->former_clone_of == node->decl)
     return true;
 
-  if (!node->thunk.thunk_p && !node->former_thunk_p ())
+  if (!node->thunk && !node->former_thunk_p ())
     {
-      while (node2 && node->decl != node2->decl)
+      while (node2
+            && node->decl != node2->decl
+            && node->decl != node2->former_clone_of)
        node2 = node2->clone_of;
       return node2 != NULL;
     }
@@ -2947,21 +3095,24 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
   /* There are no virtual clones of thunks so check former_clone_of or if we
      might have skipped thunks because this adjustments are no longer
      necessary.  */
-  while (node->thunk.thunk_p || node->former_thunk_p ())
+  while (node->thunk || node->former_thunk_p ())
     {
-      if (!node->thunk.this_adjusting)
+      if (!thunk_info::get (node)->this_adjusting)
        return false;
       /* In case of instrumented expanded thunks, which can have multiple calls
         in them, we do not know how to continue and just have to be
-        optimistic.  */
-      if (node->callees->next_callee)
+        optimistic.  The same applies if all calls have already been inlined
+        into the thunk.  */
+      if (!node->callees || node->callees->next_callee)
        return true;
       node = node->callees->callee->ultimate_alias_target ();
 
-      if (!node2->clone.param_adjustments
-         || node2->clone.param_adjustments->first_param_intact_p ())
+      clone_info *info = clone_info::get (node2);
+      if (!info || !info->param_adjustments
+         || info->param_adjustments->first_param_intact_p ())
        return false;
-      if (node2->former_clone_of == node->decl)
+      if (node2->former_clone_of == node->decl
+         || node2->former_clone_of == node->former_clone_of)
        return true;
 
       cgraph_node *n2 = node2;
@@ -3057,6 +3208,147 @@ cgraph_edge::verify_corresponds_to_fndecl (tree decl)
 #  pragma GCC diagnostic ignored "-Wformat-diag"
 #endif
 
+/* Verify consistency of speculative call in NODE corresponding to STMT
+   and LTO_STMT_UID.  If INDIRECT is set, assume that it is the indirect
+   edge of call sequence. Return true if error is found.
+
+   This function is called to every component of indirect call (direct edges,
+   indirect edge and refs).  To save duplicated work, do full testing only
+   in that case.  */
+static bool
+verify_speculative_call (struct cgraph_node *node, gimple *stmt,
+                        unsigned int lto_stmt_uid,
+                        struct cgraph_edge *indirect)
+{
+  if (indirect == NULL)
+    {
+      for (indirect = node->indirect_calls; indirect;
+          indirect = indirect->next_callee)
+       if (indirect->call_stmt == stmt
+           && indirect->lto_stmt_uid == lto_stmt_uid)
+         break;
+      if (!indirect)
+       {
+         error ("missing indirect call in speculative call sequence");
+         return true;
+       }
+      if (!indirect->speculative)
+       {
+         error ("indirect call in speculative call sequence has no "
+                "speculative flag");
+         return true;
+       }
+      return false;
+    }
+
+  /* Maximal number of targets.  We probably will never want to have more than
+     this.  */
+  const unsigned int num = 256;
+  cgraph_edge *direct_calls[num];
+  ipa_ref *refs[num];
+
+  for (unsigned int i = 0; i < num; i++)
+    {
+      direct_calls[i] = NULL;
+      refs[i] = NULL;
+    }
+
+  cgraph_edge *first_call = NULL;
+  cgraph_edge *prev_call = NULL;
+
+  for (cgraph_edge *direct = node->callees; direct;
+       direct = direct->next_callee)
+    if (direct->call_stmt == stmt && direct->lto_stmt_uid == lto_stmt_uid)
+      {
+       if (!first_call)
+         first_call = direct;
+       if (prev_call && direct != prev_call->next_callee)
+         {
+           error ("speculative edges are not adjacent");
+           return true;
+         }
+       prev_call = direct;
+       if (!direct->speculative)
+         {
+           error ("direct call to %s in speculative call sequence has no "
+                  "speculative flag", direct->callee->dump_name ());
+           return true;
+         }
+       if (direct->speculative_id >= num)
+         {
+           error ("direct call to %s in speculative call sequence has "
+                  "speculative_id %i out of range",
+                  direct->callee->dump_name (), direct->speculative_id);
+           return true;
+         }
+       if (direct_calls[direct->speculative_id])
+         {
+           error ("duplicate direct call to %s in speculative call sequence "
+                  "with speculative_id %i",
+                  direct->callee->dump_name (), direct->speculative_id);
+           return true;
+         }
+       direct_calls[direct->speculative_id] = direct;
+      }
+
+  if (first_call->call_stmt
+      && first_call != node->get_edge (first_call->call_stmt))
+    {
+      error ("call stmt hash does not point to first direct edge of "
+            "speculative call sequence");
+      return true;
+    }
+
+  ipa_ref *ref;
+  for (int i = 0; node->iterate_reference (i, ref); i++)
+    if (ref->speculative
+       && ref->stmt == stmt && ref->lto_stmt_uid == lto_stmt_uid)
+      {
+       if (ref->speculative_id >= num)
+         {
+           error ("direct call to %s in speculative call sequence has "
+                  "speculative_id %i out of range",
+                  ref->referred->dump_name (), ref->speculative_id);
+           return true;
+         }
+       if (refs[ref->speculative_id])
+         {
+           error ("duplicate reference %s in speculative call sequence "
+                  "with speculative_id %i",
+                  ref->referred->dump_name (), ref->speculative_id);
+           return true;
+         }
+       refs[ref->speculative_id] = ref;
+      }
+
+  int num_targets = 0;
+  for (unsigned int i = 0 ; i < num ; i++)
+    {
+      if (refs[i] && !direct_calls[i])
+       {
+         error ("missing direct call for speculation %i", i);
+         return true;
+       }
+      if (!refs[i] && direct_calls[i])
+       {
+         error ("missing ref for speculation %i", i);
+         return true;
+       }
+      if (refs[i] != NULL)
+       num_targets++;
+    }
+
+  if (num_targets != indirect->num_speculative_call_targets_p ())
+    {
+      error ("number of speculative targets %i mismatched with "
+            "num_speculative_call_targets %i",
+            num_targets,
+            indirect->num_speculative_call_targets_p ());
+      return true;
+    }
+  return false;
+}
+
 /* Verify cgraph nodes of given cgraph node.  */
 DEBUG_FUNCTION void
 cgraph_node::verify_node (void)
@@ -3066,6 +3358,8 @@ cgraph_node::verify_node (void)
   basic_block this_block;
   gimple_stmt_iterator gsi;
   bool error_found = false;
+  int i;
+  ipa_ref *ref = NULL;
 
   if (seen_error ())
     return;
@@ -3090,6 +3384,18 @@ cgraph_node::verify_node (void)
       error ("inline clone in same comdat group list");
       error_found = true;
     }
+  if (inlined_to && !count.compatible_p (inlined_to->count))
+    {
+      error ("inline clone count is not compatible");
+      count.debug ();
+      inlined_to->count.debug ();
+      error_found = true;
+    }
+  if (tp_first_run < 0)
+    {
+      error ("tp_first_run must be non-negative");
+      error_found = true;
+    }
   if (!definition && !in_other_partition && local)
     {
       error ("local symbols must be defined");
@@ -3110,6 +3416,26 @@ cgraph_node::verify_node (void)
       error ("inline clone is forced to output");
       error_found = true;
     }
+  if (symtab->state != LTO_STREAMING)
+    {
+      if (calls_comdat_local && !same_comdat_group)
+       {
+         error ("calls_comdat_local is set outside of a comdat group");
+         error_found = true;
+       }
+      if (!inlined_to && calls_comdat_local != check_calls_comdat_local_p ())
+       {
+         error ("invalid calls_comdat_local flag");
+         error_found = true;
+       }
+    }
+  if (DECL_IS_MALLOC (decl)
+      && !POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
+    {
+      error ("malloc attribute should be used for a function that "
+            "returns a pointer");
+      error_found = true;
+    }
   for (e = indirect_calls; e; e = e->next_callee)
     {
       if (e->aux)
@@ -3118,6 +3444,13 @@ cgraph_node::verify_node (void)
                 identifier_to_locale (e->caller->name ()));
          error_found = true;
        }
+      if (!e->count.compatible_p (count))
+       {
+         error ("edge count is not compatible with function count");
+         e->count.debug ();
+         count.debug ();
+         error_found = true;
+       }
       if (!e->indirect_unknown_callee
          || !e->indirect_info)
        {
@@ -3127,6 +3460,11 @@ cgraph_node::verify_node (void)
          cgraph_debug_gimple_stmt (this_cfun, e->call_stmt);
          error_found = true;
        }
+      if (e->call_stmt && e->lto_stmt_uid)
+       {
+         error ("edge has both call_stmt and lto_stmt_uid set");
+         error_found = true;
+       }
     }
   bool check_comdat = comdat_local_p ();
   for (e = callers; e; e = e->next_caller)
@@ -3166,6 +3504,13 @@ cgraph_node::verify_node (void)
     {
       if (e->verify_count ())
        error_found = true;
+      if (!e->count.compatible_p (count))
+       {
+         error ("edge count is not compatible with function count");
+         e->count.debug ();
+         count.debug ();
+         error_found = true;
+       }
       if (gimple_has_body_p (e->caller->decl)
          && !e->caller->inlined_to
          && !e->speculative
@@ -3186,6 +3531,15 @@ cgraph_node::verify_node (void)
          fprintf (stderr, "\n");
          error_found = true;
        }
+      if (e->call_stmt && e->lto_stmt_uid)
+       {
+         error ("edge has both call_stmt and lto_stmt_uid set");
+         error_found = true;
+       }
+      if (e->speculative
+         && verify_speculative_call (e->caller, e->call_stmt, e->lto_stmt_uid,
+                                     NULL))
+       error_found = true;
     }
   for (e = indirect_calls; e; e = e->next_callee)
     {
@@ -3208,7 +3562,24 @@ cgraph_node::verify_node (void)
          fprintf (stderr, "\n");
          error_found = true;
        }
+      if (e->speculative
+         && verify_speculative_call (e->caller, e->call_stmt, e->lto_stmt_uid,
+                                     e))
+       error_found = true;
     }
+  for (i = 0; iterate_reference (i, ref); i++)
+    {
+      if (ref->stmt && ref->lto_stmt_uid)
+       {
+         error ("reference has both stmt and lto_stmt_uid set");
+         error_found = true;
+       }
+      if (ref->speculative
+         && verify_speculative_call (this, ref->stmt,
+                                     ref->lto_stmt_uid, NULL))
+       error_found = true;
+    }
+
   if (!callers && inlined_to)
     {
       error ("inlined_to pointer is set but no predecessors found");
@@ -3269,7 +3640,7 @@ cgraph_node::verify_node (void)
       if (callees)
        {
          error ("Alias has call edges");
-          error_found = true;
+         error_found = true;
        }
       for (i = 0; iterate_reference (i, ref); i++)
        if (ref->use != IPA_REF_ALIAS)
@@ -3291,23 +3662,23 @@ cgraph_node::verify_node (void)
        }
     }
 
-  if (analyzed && thunk.thunk_p)
+  if (analyzed && thunk)
     {
       if (!callees)
        {
          error ("No edge out of thunk node");
-          error_found = true;
+         error_found = true;
        }
       else if (callees->next_callee)
        {
          error ("More than one edge out of thunk node");
-          error_found = true;
+         error_found = true;
        }
       if (gimple_has_body_p (decl) && !inlined_to)
-        {
+       {
          error ("Thunk is not supposed to have body");
-          error_found = true;
-        }
+         error_found = true;
+       }
     }
   else if (analyzed && gimple_has_body_p (decl)
           && !TREE_ASM_WRITTEN (decl)
@@ -3317,8 +3688,6 @@ cgraph_node::verify_node (void)
       if (this_cfun->cfg)
        {
          hash_set<gimple *> stmts;
-         int i;
-         ipa_ref *ref = NULL;
 
          /* Reach the trees by walking over the CFG, and note the
             enclosing basic-blocks in the call edges.  */
@@ -3389,7 +3758,7 @@ cgraph_node::verify_node (void)
 
       for (e = callees; e; e = e->next_callee)
        {
-         if (!e->aux)
+         if (!e->aux && !e->speculative)
            {
              error ("edge %s->%s has no corresponding call_stmt",
                     identifier_to_locale (e->caller->name ()),
@@ -3412,27 +3781,32 @@ cgraph_node::verify_node (void)
        }
     }
 
-  if (nested != NULL)
+  if (nested_function_info *info = nested_function_info::get (this))
     {
-      for (cgraph_node *n = nested; n != NULL; n = n->next_nested)
+      if (info->nested != NULL)
        {
-         if (n->origin == NULL)
+         for (cgraph_node *n = info->nested; n != NULL;
+              n = next_nested_function (n))
            {
-             error ("missing origin for a node in a nested list");
-             error_found = true;
-           }
-         else if (n->origin != this)
-           {
-             error ("origin points to a different parent");
-             error_found = true;
-             break;
+             nested_function_info *ninfo = nested_function_info::get (n);
+             if (ninfo->origin == NULL)
+               {
+                 error ("missing origin for a node in a nested list");
+                 error_found = true;
+               }
+             else if (ninfo->origin != this)
+               {
+                 error ("origin points to a different parent");
+                 error_found = true;
+                 break;
+               }
            }
        }
-    }
-  if (next_nested != NULL && origin == NULL)
-    {
-      error ("missing origin for a node in a nested list");
-      error_found = true;
+      if (info->next_nested != NULL && info->origin == NULL)
+       {
+         error ("missing origin for a node in a nested list");
+         error_found = true;
+       }
     }
 
   if (error_found)
@@ -3472,18 +3846,15 @@ cgraph_node::function_symbol (enum availability *availability,
 {
   cgraph_node *node = ultimate_alias_target (availability, ref);
 
-  while (node->thunk.thunk_p)
+  while (node->thunk)
     {
+      enum availability a;
+
       ref = node;
       node = node->callees->callee;
-      if (availability)
-       {
-         enum availability a;
-         a = node->get_availability (ref);
-         if (a < *availability)
-           *availability = a;
-       }
-      node = node->ultimate_alias_target (availability, ref);
+      node = node->ultimate_alias_target (availability ? &a : NULL, ref);
+      if (availability && a < *availability)
+       *availability = a;
     }
   return node;
 }
@@ -3502,33 +3873,41 @@ cgraph_node::function_or_virtual_thunk_symbol
 {
   cgraph_node *node = ultimate_alias_target (availability, ref);
 
-  while (node->thunk.thunk_p && !node->thunk.virtual_offset_p)
+  while (node->thunk && !thunk_info::get (node)->virtual_offset_p)
     {
+      enum availability a;
+
       ref = node;
       node = node->callees->callee;
-      if (availability)
-       {
-         enum availability a;
-         a = node->get_availability (ref);
-         if (a < *availability)
-           *availability = a;
-       }
-      node = node->ultimate_alias_target (availability, ref);
+      node = node->ultimate_alias_target (availability ? &a : NULL, ref);
+      if (availability && a < *availability)
+       *availability = a;
     }
   return node;
 }
 
 /* When doing LTO, read cgraph_node's body from disk if it is not already
-   present.  */
+   present.  Also perform any necessary clone materializations.  */
 
 bool
-cgraph_node::get_untransformed_body (void)
+cgraph_node::get_untransformed_body ()
 {
   lto_file_decl_data *file_data;
   const char *data, *name;
   size_t len;
   tree decl = this->decl;
 
+  /* See if there is clone to be materialized.
+     (inline clones does not need materialization, but we can be seeing
+      an inline clone of real clone).  */
+  cgraph_node *p = this;
+  for (cgraph_node *c = clone_of; c; c = c->clone_of)
+    {
+      if (c->decl != decl)
+       p->materialize_clone ();
+      p = c;
+    }
+
   /* Check if body is already there.  Either we have gimple body or
      the function is thunk and in that case we set DECL_ARGUMENTS.  */
   if (DECL_ARGUMENTS (decl) || gimple_has_body_p (decl))
@@ -3546,12 +3925,17 @@ cgraph_node::get_untransformed_body (void)
   struct lto_in_decl_state *decl_state
         = lto_get_function_in_decl_state (file_data, decl);
 
+  cgraph_node *origin = this;
+  while (origin->clone_of)
+    origin = origin->clone_of;
+
+  int stream_order = origin->order - file_data->order_base;
   data = lto_get_section_data (file_data, LTO_section_function_body,
-                              name, &len, decl_state->compressed);
+                              name, stream_order, &len,
+                              decl_state->compressed);
   if (!data)
-    fatal_error (input_location, "%s: section %s is missing",
-                file_data->file_name,
-                name);
+    fatal_error (input_location, "%s: section %s.%d is missing",
+                file_data->file_name, name, stream_order);
 
   gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
 
@@ -3597,6 +3981,8 @@ cgraph_node::get_body (void)
       set_dump_file (NULL);
 
       push_cfun (DECL_STRUCT_FUNCTION (decl));
+
+      update_ssa (TODO_update_ssa_only_virtuals);
       execute_all_ipa_transforms (true);
       cgraph_edge::rebuild_edges ();
       free_dominance_info (CDI_DOMINATORS);
@@ -3629,108 +4015,15 @@ cgraph_node::get_fun () const
   return fun;
 }
 
-/* Verify if the type of the argument matches that of the function
-   declaration.  If we cannot verify this or there is a mismatch,
-   return false.  */
-
-static bool
-gimple_check_call_args (gimple *stmt, tree fndecl, bool args_count_match)
-{
-  tree parms, p;
-  unsigned int i, nargs;
-
-  /* Calls to internal functions always match their signature.  */
-  if (gimple_call_internal_p (stmt))
-    return true;
-
-  nargs = gimple_call_num_args (stmt);
-
-  /* Get argument types for verification.  */
-  if (fndecl)
-    parms = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-  else
-    parms = TYPE_ARG_TYPES (gimple_call_fntype (stmt));
-
-  /* Verify if the type of the argument matches that of the function
-     declaration.  If we cannot verify this or there is a mismatch,
-     return false.  */
-  if (fndecl && DECL_ARGUMENTS (fndecl))
-    {
-      for (i = 0, p = DECL_ARGUMENTS (fndecl);
-          i < nargs;
-          i++, p = DECL_CHAIN (p))
-       {
-         tree arg;
-         /* We cannot distinguish a varargs function from the case
-            of excess parameters, still deferring the inlining decision
-            to the callee is possible.  */
-         if (!p)
-           break;
-         arg = gimple_call_arg (stmt, i);
-         if (p == error_mark_node
-             || DECL_ARG_TYPE (p) == error_mark_node
-             || arg == error_mark_node
-             || (!types_compatible_p (DECL_ARG_TYPE (p), TREE_TYPE (arg))
-                 && !fold_convertible_p (DECL_ARG_TYPE (p), arg)))
-            return false;
-       }
-      if (args_count_match && p)
-       return false;
-    }
-  else if (parms)
-    {
-      for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
-       {
-         tree arg;
-         /* If this is a varargs function defer inlining decision
-            to callee.  */
-         if (!p)
-           break;
-         arg = gimple_call_arg (stmt, i);
-         if (TREE_VALUE (p) == error_mark_node
-             || arg == error_mark_node
-             || TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
-             || (!types_compatible_p (TREE_VALUE (p), TREE_TYPE (arg))
-                 && !fold_convertible_p (TREE_VALUE (p), arg)))
-            return false;
-       }
-    }
-  else
-    {
-      if (nargs != 0)
-        return false;
-    }
-  return true;
-}
-
-/* Verify if the type of the argument and lhs of CALL_STMT matches
-   that of the function declaration CALLEE. If ARGS_COUNT_MATCH is
-   true, the arg count needs to be the same.
-   If we cannot verify this or there is a mismatch, return false.  */
-
-bool
-gimple_check_call_matching_types (gimple *call_stmt, tree callee,
-                                 bool args_count_match)
-{
-  tree lhs;
-
-  if ((DECL_RESULT (callee)
-       && !DECL_BY_REFERENCE (DECL_RESULT (callee))
-       && (lhs = gimple_call_lhs (call_stmt)) != NULL_TREE
-       && !useless_type_conversion_p (TREE_TYPE (DECL_RESULT (callee)),
-                                      TREE_TYPE (lhs))
-       && !fold_convertible_p (TREE_TYPE (DECL_RESULT (callee)), lhs))
-      || !gimple_check_call_args (call_stmt, callee, args_count_match))
-    return false;
-  return true;
-}
-
 /* Reset all state within cgraph.c so that we can rerun the compiler
    within the same process.  For use by toplev::finalize.  */
 
 void
 cgraph_c_finalize (void)
 {
+  nested_function_info::release ();
+  thunk_info::release ();
+  clone_info::release ();
   symtab = NULL;
 
   x_cgraph_nodes_queue = NULL;
@@ -3739,7 +4032,7 @@ cgraph_c_finalize (void)
   version_info_node = NULL;
 }
 
-/* A wroker for call_for_symbol_and_aliases.  */
+/* A worker for call_for_symbol_and_aliases.  */
 
 bool
 cgraph_node::call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
@@ -3766,7 +4059,7 @@ bool
 cgraph_node::has_thunk_p (cgraph_node *node, void *)
 {
   for (cgraph_edge *e = node->callers; e; e = e->next_caller)
-    if (e->caller->thunk.thunk_p)
+    if (e->caller->thunk)
       return true;
   return false;
 }
@@ -3794,13 +4087,14 @@ cgraph_edge::possibly_call_in_translation_unit_p (void)
   if (flag_incremental_link == INCREMENTAL_LINK_LTO)
     return true;
 
-  /* We may be smarter here and avoid stremaing in indirect calls we can't
-     track, but that would require arranging stremaing the indirect call
+  /* We may be smarter here and avoid streaming in indirect calls we can't
+     track, but that would require arranging streaming the indirect call
      summary first.  */
   if (!callee)
     return true;
 
-  /* If calle is local to the original translation unit, it will be defined.  */
+  /* If callee is local to the original translation unit, it will be
+     defined.  */
   if (!TREE_PUBLIC (callee->decl) && !DECL_EXTERNAL (callee->decl))
     return true;
 
@@ -3813,7 +4107,43 @@ cgraph_edge::possibly_call_in_translation_unit_p (void)
   if (node->previous_sharing_asm_name)
     node = symtab_node::get_for_asmname (DECL_ASSEMBLER_NAME (callee->decl));
   gcc_assert (TREE_PUBLIC (node->decl));
-  return node->get_availability () >= AVAIL_AVAILABLE;
+  return node->get_availability () >= AVAIL_INTERPOSABLE;
+}
+
+/* Return num_speculative_targets of this edge.  */
+
+int
+cgraph_edge::num_speculative_call_targets_p (void)
+{
+  return indirect_info ? indirect_info->num_speculative_call_targets : 0;
+}
+
+/* Check if function calls comdat local.  This is used to recompute
+   calls_comdat_local flag after function transformations.  */
+bool
+cgraph_node::check_calls_comdat_local_p ()
+{
+  for (cgraph_edge *e = callees; e; e = e->next_callee)
+    if (e->inline_failed
+       ? e->callee->comdat_local_p ()
+       : e->callee->check_calls_comdat_local_p ())
+      return true;
+  return false;
+}
+
+/* Return true if this node represents a former, i.e. an expanded, thunk.  */
+
+bool
+cgraph_node::former_thunk_p (void)
+{
+  if (thunk)
+    return false;
+  thunk_info *i = thunk_info::get (this);
+  if (!i)
+    return false;
+  gcc_checking_assert (i->fixed_offset || i->virtual_offset_p
+                      || i->indirect_offset);
+  return true;
 }
 
 /* A stashed copy of "symtab" for use by selftest::symbol_table_test.
@@ -3835,7 +4165,7 @@ symbol_table_test::symbol_table_test ()
 {
   gcc_assert (saved_symtab == NULL);
   saved_symtab = symtab;
-  symtab = new (ggc_alloc <symbol_table> ()) symbol_table ();
+  symtab = new (ggc_alloc<symbol_table> ()) symbol_table ();
 }
 
 /* Destructor.  Restore the old value of symtab.  */