]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/ipa-split.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / ipa-split.c
index 0c25fcae59fa801e5ffdff5ba22725316610757d..c68577d04a9940380c813dfb1821bc4b62bc4c1f 100644 (file)
@@ -1,5 +1,5 @@
 /* Function splitting pass
-   Copyright (C) 2010-2016 Free Software Foundation, Inc.
+   Copyright (C) 2010-2021 Free Software Foundation, Inc.
    Contributed by Jan Hubicka  <jh@suse.cz>
 
 This file is part of GCC.
@@ -100,28 +100,30 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-into-ssa.h"
 #include "tree-dfa.h"
 #include "tree-inline.h"
-#include "params.h"
 #include "gimple-pretty-print.h"
-#include "ipa-inline.h"
+#include "ipa-fnsummary.h"
 #include "cfgloop.h"
-#include "tree-chkp.h"
+#include "attribs.h"
 
 /* Per basic block info.  */
 
-struct split_bb_info
+class split_bb_info
 {
+public:
   unsigned int size;
-  unsigned int time;
+  sreal time;
 };
 
 static vec<split_bb_info> bb_info_vec;
 
 /* Description of split point.  */
 
-struct split_point
+class split_point
 {
+public:
   /* Size of the partitions.  */
-  unsigned int header_time, header_size, split_time, split_size;
+  sreal header_time, split_time;
+  unsigned int header_size, split_size;
 
   /* SSA names that need to be passed into spit function.  */
   bitmap ssa_names_to_pass;
@@ -129,6 +131,10 @@ struct split_point
   /* Basic block where we split (that will become entry point of new function.  */
   basic_block entry_bb;
 
+  /* Count for entering the split part.
+     This is not count of the entry_bb because it may be in loop.  */
+  profile_count count;
+
   /* Basic blocks we are splitting away.  */
   bitmap split_bbs;
 
@@ -139,14 +145,13 @@ struct split_point
 
 /* Best split point found.  */
 
-struct split_point best_split_point;
+class split_point best_split_point;
 
 /* Set of basic blocks that are not allowed to dominate a split point.  */
 
 static bitmap forbidden_dominators;
 
 static tree find_retval (basic_block return_bb);
-static tree find_retbnd (basic_block return_bb);
 
 /* Callback for walk_stmt_load_store_addr_ops.  If T is non-SSA automatic
    variable, check it if it is present in bitmap passed via DATA.  */
@@ -160,10 +165,10 @@ test_nonssa_use (gimple *, tree t, tree, void *data)
     return false;
 
   if (TREE_CODE (t) == PARM_DECL
-      || (TREE_CODE (t) == VAR_DECL
+      || (VAR_P (t)
          && auto_var_in_fn_p (t, current_function_decl))
       || TREE_CODE (t) == RESULT_DECL
-        /* Normal labels are part of CFG and will be handled gratefuly.
+        /* Normal labels are part of CFG and will be handled gratefully.
            Forced labels however can be used directly by statements and
            need to stay in one partition along with their uses.  */
       || (TREE_CODE (t) == LABEL_DECL
@@ -187,14 +192,15 @@ test_nonssa_use (gimple *, tree t, tree, void *data)
 /* Dump split point CURRENT.  */
 
 static void
-dump_split_point (FILE * file, struct split_point *current)
+dump_split_point (FILE * file, class split_point *current)
 {
   fprintf (file,
           "Split point at BB %i\n"
-          "  header time: %i header size: %i\n"
-          "  split time: %i split size: %i\n  bbs: ",
-          current->entry_bb->index, current->header_time,
-          current->header_size, current->split_time, current->split_size);
+          "  header time: %f header size: %i\n"
+          "  split time: %f split size: %i\n  bbs: ",
+          current->entry_bb->index, current->header_time.to_double (),
+          current->header_size, current->split_time.to_double (),
+          current->split_size);
   dump_bitmap (file, current->split_bbs);
   fprintf (file, "  SSA names to pass: ");
   dump_bitmap (file, current->ssa_names_to_pass);
@@ -205,7 +211,7 @@ dump_split_point (FILE * file, struct split_point *current)
    Parameters are the same as for consider_split.  */
 
 static bool
-verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars,
+verify_non_ssa_vars (class split_point *current, bitmap non_ssa_vars,
                     basic_block return_bb)
 {
   bitmap seen = BITMAP_ALLOC (NULL);
@@ -399,7 +405,7 @@ dominated_by_forbidden (basic_block bb)
 /* For give split point CURRENT and return block RETURN_BB return 1
    if ssa name VAL is set by split part and 0 otherwise.  */
 static bool
-split_part_set_ssa_name_p (tree val, struct split_point *current,
+split_part_set_ssa_name_p (tree val, class split_point *current,
                           basic_block return_bb)
 {
   if (TREE_CODE (val) != SSA_NAME)
@@ -416,7 +422,7 @@ split_part_set_ssa_name_p (tree val, struct split_point *current,
    See if we can split function here.  */
 
 static void
-consider_split (struct split_point *current, bitmap non_ssa_vars,
+consider_split (class split_point *current, bitmap non_ssa_vars,
                basic_block return_bb)
 {
   tree parm;
@@ -426,41 +432,46 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
   edge_iterator ei;
   gphi_iterator bsi;
   unsigned int i;
-  int incoming_freq = 0;
   tree retval;
-  tree retbnd;
   bool back_edge = false;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_split_point (dump_file, current);
 
+  current->count = profile_count::zero ();
   FOR_EACH_EDGE (e, ei, current->entry_bb->preds)
     {
       if (e->flags & EDGE_DFS_BACK)
        back_edge = true;
       if (!bitmap_bit_p (current->split_bbs, e->src->index))
-        incoming_freq += EDGE_FREQUENCY (e);
+       current->count += e->count ();
     }
 
-  /* Do not split when we would end up calling function anyway.  */
-  if (incoming_freq
-      >= (ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency
-         * PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY) / 100))
+  /* Do not split when we would end up calling function anyway.
+     Compares are three state, use !(...<...) to also give up when outcome
+     is unknown.  */
+  if (!(current->count
+       < (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.apply_scale
+          (param_partial_inlining_entry_probability, 100))))
     {
-      /* When profile is guessed, we can not expect it to give us
-        realistic estimate on likelyness of function taking the
+      /* When profile is guessed, we cannot expect it to give us
+        realistic estimate on likeliness of function taking the
         complex path.  As a special case, when tail of the function is
         a loop, enable splitting since inlining code skipping the loop
         is likely noticeable win.  */
       if (back_edge
          && profile_status_for_fn (cfun) != PROFILE_READ
-         && incoming_freq < ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency)
+         && current->count
+                < ENTRY_BLOCK_PTR_FOR_FN (cfun)->count)
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
-           fprintf (dump_file,
-                    "  Split before loop, accepting despite low frequencies %i %i.\n",
-                    incoming_freq,
-                    ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency);
+           {
+             fprintf (dump_file,
+                      "  Split before loop, accepting despite low counts");
+             current->count.dump (dump_file);
+             fprintf (dump_file, " ");
+             ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.dump (dump_file);
+           }
        }
       else
        {
@@ -535,8 +546,9 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
            }
        }
     }
-  if (!VOID_TYPE_P (TREE_TYPE (current_function_decl)))
-    call_overhead += estimate_move_cost (TREE_TYPE (current_function_decl),
+  if (!VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
+    call_overhead += estimate_move_cost (TREE_TYPE (TREE_TYPE
+                                                (current_function_decl)),
                                         false);
 
   if (current->split_size <= call_overhead)
@@ -546,10 +558,13 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
                 "  Refused: split size is smaller than call overhead\n");
       return;
     }
+  /* FIXME: The logic here is not very precise, because inliner does use
+     inline predicates to reduce function body size.  We add 10 to anticipate
+     that.  Next stage1 we should try to be more meaningful here.  */
   if (current->header_size + call_overhead
       >= (unsigned int)(DECL_DECLARED_INLINE_P (current_function_decl)
-                       ? MAX_INLINE_INSNS_SINGLE
-                       : MAX_INLINE_INSNS_AUTO))
+                       ? param_max_inline_insns_single
+                       : param_max_inline_insns_auto) + 10)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
@@ -562,7 +577,7 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
      Limit this duplication.  This is consistent with limit in tree-sra.c  
      FIXME: with LTO we ought to be able to do better!  */
   if (DECL_ONE_ONLY (current_function_decl)
-      && current->split_size >= (unsigned int) MAX_INLINE_INSNS_AUTO)
+      && current->split_size >= (unsigned int) param_max_inline_insns_auto + 10)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
@@ -574,7 +589,7 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
      FIXME: with LTO we ought to be able to do better!  */
   if (DECL_ONE_ONLY (current_function_decl)
       && current->split_size
-        <= (unsigned int) PARAM_VALUE (PARAM_EARLY_INLINING_INSNS) / 2)
+        <= (unsigned int) param_early_inlining_insns / 2)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
@@ -656,36 +671,13 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
       = split_part_set_ssa_name_p (retval, current, return_bb);
   else if (TREE_CODE (retval) == PARM_DECL)
     current->split_part_set_retval = false;
-  else if (TREE_CODE (retval) == VAR_DECL
+  else if (VAR_P (retval)
           || TREE_CODE (retval) == RESULT_DECL)
     current->split_part_set_retval
       = bitmap_bit_p (non_ssa_vars, DECL_UID (retval));
   else
     current->split_part_set_retval = true;
 
-  /* See if retbnd used by return bb is computed by header or split part.  */
-  retbnd = find_retbnd (return_bb);
-  if (retbnd)
-    {
-      bool split_part_set_retbnd
-       = split_part_set_ssa_name_p (retbnd, current, return_bb);
-
-      /* If we have both return value and bounds then keep their definitions
-        in a single function.  We use SSA names to link returned bounds and
-        value and therefore do not handle cases when result is passed by
-        reference (which should not be our case anyway since bounds are
-        returned for pointers only).  */
-      if ((DECL_BY_REFERENCE (DECL_RESULT (current_function_decl))
-          && current->split_part_set_retval)
-         || split_part_set_retbnd != current->split_part_set_retval)
-       {
-         if (dump_file && (dump_flags & TDF_DETAILS))
-           fprintf (dump_file,
-                    "  Refused: split point splits return value and bounds\n");
-         return;
-       }
-    }
-
   /* split_function fixes up at most one PHI non-virtual PHI node in return_bb,
      for the return value.  If there are other PHIs, give up.  */
   if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun))
@@ -710,12 +702,13 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "  Accepted!\n");
 
-  /* At the moment chose split point with lowest frequency and that leaves
+  /* At the moment chose split point with lowest count and that leaves
      out smallest size of header.
      In future we might re-consider this heuristics.  */
   if (!best_split_point.split_bbs
-      || best_split_point.entry_bb->frequency > current->entry_bb->frequency
-      || (best_split_point.entry_bb->frequency == current->entry_bb->frequency
+      || best_split_point.count
+        > current->count
+      || (best_split_point.count == current->count 
          && best_split_point.split_size < current->split_size))
        
     {
@@ -739,7 +732,7 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
    of the form:
    <retval> = tmp_var;
    return <retval>
-   but return_bb can not be more complex than this (except for
+   but return_bb cannot be more complex than this (except for
    -fsanitize=thread we allow TSAN_FUNC_EXIT () internal call in there).
    If nothing is found, return the exit block.
 
@@ -814,18 +807,6 @@ find_retval (basic_block return_bb)
   return NULL;
 }
 
-/* Given return basic block RETURN_BB, see where return bounds are really
-   stored.  */
-static tree
-find_retbnd (basic_block return_bb)
-{
-  gimple_stmt_iterator bsi;
-  for (bsi = gsi_last_bb (return_bb); !gsi_end_p (bsi); gsi_prev (&bsi))
-    if (gimple_code (gsi_stmt (bsi)) == GIMPLE_RETURN)
-      return gimple_return_retbnd (gsi_stmt (bsi));
-  return NULL;
-}
-
 /* Callback for walk_stmt_load_store_addr_ops.  If T is non-SSA automatic
    variable, mark it as used in bitmap passed via DATA.
    Return true when access to T prevents splitting the function.  */
@@ -848,11 +829,9 @@ mark_nonssa_use (gimple *, tree t, tree, void *data)
       return true;
     }
 
-  if ((TREE_CODE (t) == VAR_DECL
-       && auto_var_in_fn_p (t, current_function_decl))
+  if ((VAR_P (t) && auto_var_in_fn_p (t, current_function_decl))
       || TREE_CODE (t) == RESULT_DECL
-      || (TREE_CODE (t) == LABEL_DECL
-         && FORCED_LABEL (t)))
+      || (TREE_CODE (t) == LABEL_DECL && FORCED_LABEL (t)))
     bitmap_set_bit ((bitmap)data, DECL_UID (t));
 
   /* For DECL_BY_REFERENCE, the return value is actually a pointer.  We want
@@ -902,7 +881,7 @@ visit_bb (basic_block bb, basic_block return_bb,
       if (gimple_clobber_p (stmt))
        continue;
 
-      /* FIXME: We can split regions containing EH.  We can not however
+      /* FIXME: We can split regions containing EH.  We cannot however
         split RESX, EH_DISPATCH and EH_POINTER referring to same region
         into different partitions.  This would require tracking of
         EH regions and checking in consider_split_point if they 
@@ -923,8 +902,7 @@ visit_bb (basic_block bb, basic_block return_bb,
       /* Check builtins that prevent splitting.  */
       if (gimple_code (stmt) == GIMPLE_CALL
          && (decl = gimple_call_fndecl (stmt)) != NULL_TREE
-         && DECL_BUILT_IN (decl)
-         && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+         && fndecl_built_in_p (decl, BUILT_IN_NORMAL))
        switch (DECL_FUNCTION_CODE (decl))
          {
          /* FIXME: once we will allow passing non-parm values to split part,
@@ -1003,8 +981,9 @@ visit_bb (basic_block bb, basic_block return_bb,
 
 /* Stack entry for recursive DFS walk in find_split_point.  */
 
-struct stack_entry
+class stack_entry
 {
+public:
   /* Basic block we are examining.  */
   basic_block bb;
 
@@ -1025,9 +1004,10 @@ struct stack_entry
   int earliest;
 
   /* Overall time and size of all BBs reached from this BB in DFS walk.  */
-  int overall_time, overall_size;
+  sreal overall_time;
+  int overall_size;
 
-  /* When false we can not split on this BB.  */
+  /* When false we cannot split on this BB.  */
   bool can_split;
 };
 
@@ -1050,12 +1030,12 @@ struct stack_entry
    the component used by consider_split.  */
 
 static void
-find_split_points (basic_block return_bb, int overall_time, int overall_size)
+find_split_points (basic_block return_bb, sreal overall_time, int overall_size)
 {
   stack_entry first;
   vec<stack_entry> stack = vNULL;
   basic_block bb;
-  struct split_point current;
+  class split_point current;
 
   current.header_time = overall_time;
   current.header_size = overall_size;
@@ -1095,7 +1075,7 @@ find_split_points (basic_block return_bb, int overall_time, int overall_size)
          if (pos <= entry->earliest && !entry->can_split
              && dump_file && (dump_flags & TDF_DETAILS))
            fprintf (dump_file,
-                    "found articulation at bb %i but can not split\n",
+                    "found articulation at bb %i but cannot split\n",
                     entry->bb->index);
          if (pos <= entry->earliest && entry->can_split)
             {
@@ -1201,7 +1181,7 @@ find_split_points (basic_block return_bb, int overall_time, int overall_size)
 /* Split function at SPLIT_POINT.  */
 
 static void
-split_function (basic_block return_bb, struct split_point *split_point,
+split_function (basic_block return_bb, class split_point *split_point,
                bool add_tsan_func_exit)
 {
   vec<tree> args_to_pass = vNULL;
@@ -1213,8 +1193,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
   gcall *call, *tsan_func_exit_call = NULL;
   edge e;
   edge_iterator ei;
-  tree retval = NULL, real_retval = NULL, retbnd = NULL;
-  bool with_bounds = chkp_function_instrumented_p (current_function_decl);
+  tree retval = NULL, real_retval = NULL;
   gimple *last_stmt = NULL;
   unsigned int i;
   tree arg, ddef;
@@ -1225,7 +1204,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
       dump_split_point (dump_file, split_point);
     }
 
-  if (cur_node->local.can_change_signature)
+  if (cur_node->can_change_signature)
     args_to_skip = BITMAP_ALLOC (NULL);
   else
     args_to_skip = NULL;
@@ -1280,32 +1259,26 @@ split_function (basic_block return_bb, struct split_point *split_point,
       basic_block new_return_bb = create_basic_block (NULL, 0, return_bb);
       gimple_stmt_iterator gsi = gsi_start_bb (new_return_bb);
       gsi_insert_after (&gsi, gimple_build_return (NULL), GSI_NEW_STMT);
+      new_return_bb->count = profile_count::zero ();
       while (redirected)
        {
          redirected = false;
          FOR_EACH_EDGE (e, ei, return_bb->preds)
            if (bitmap_bit_p (split_point->split_bbs, e->src->index))
              {
-               new_return_bb->count += e->count;
-               new_return_bb->frequency += EDGE_FREQUENCY (e);
+               new_return_bb->count += e->count ();
                redirect_edge_and_branch (e, new_return_bb);
                redirected = true;
                break;
              }
        }
-      e = make_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
-      e->probability = REG_BR_PROB_BASE;
-      e->count = new_return_bb->count;
+      e = make_single_succ_edge (new_return_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
       add_bb_to_loop (new_return_bb, current_loops->tree_root);
       bitmap_set_bit (split_point->split_bbs, new_return_bb->index);
-      retbnd = find_retbnd (return_bb);
     }
   /* When we pass around the value, use existing return block.  */
   else
-    {
-      bitmap_set_bit (split_point->split_bbs, return_bb->index);
-      retbnd = find_retbnd (return_bb);
-    }
+    bitmap_set_bit (split_point->split_bbs, return_bb->index);
 
   /* If RETURN_BB has virtual operand PHIs, they must be removed and the
      virtual operand marked for renaming as we change the CFG in a way that
@@ -1353,26 +1326,58 @@ split_function (basic_block return_bb, struct split_point *split_point,
          }
     }
 
+  ipa_param_adjustments *adjustments;
+  bool skip_return = (!split_part_return_p
+                     || !split_point->split_part_set_retval);
+  /* TODO: Perhaps get rid of args_to_skip entirely, after we make sure the
+     debug info generation and discrepancy avoiding works well too.  */
+  if ((args_to_skip && !bitmap_empty_p (args_to_skip))
+      || skip_return)
+    {
+      vec<ipa_adjusted_param, va_gc> *new_params = NULL;
+      unsigned j;
+      for (parm = DECL_ARGUMENTS (current_function_decl), j = 0;
+          parm; parm = DECL_CHAIN (parm), j++)
+       if (!args_to_skip || !bitmap_bit_p (args_to_skip, j))
+         {
+           ipa_adjusted_param adj;
+           memset (&adj, 0, sizeof (adj));
+           adj.op = IPA_PARAM_OP_COPY;
+           adj.base_index = j;
+           adj.prev_clone_index = j;
+           vec_safe_push (new_params, adj);
+         }
+      adjustments = new ipa_param_adjustments (new_params, j, skip_return);
+    }
+  else
+    adjustments = NULL;
+
   /* Now create the actual clone.  */
   cgraph_edge::rebuild_edges ();
   node = cur_node->create_version_clone_with_body
-    (vNULL, NULL, args_to_skip,
-     !split_part_return_p || !split_point->split_part_set_retval,
+    (vNULL, NULL, adjustments,
      split_point->split_bbs, split_point->entry_bb, "part");
-
+  delete adjustments;
   node->split_part = true;
 
+  if (cur_node->same_comdat_group)
+    {
+      /* TODO: call is versionable if we make sure that all
+        callers are inside of a comdat group.  */
+      cur_node->calls_comdat_local = true;
+      node->add_to_same_comdat_group (cur_node);
+    }
+
+
   /* Let's take a time profile for splitted function.  */
-  node->tp_first_run = cur_node->tp_first_run + 1;
+  if (cur_node->tp_first_run)
+    node->tp_first_run = cur_node->tp_first_run + 1;
 
   /* For usual cloning it is enough to clear builtin only when signature
-     changes.  For partial inlining we however can not expect the part
+     changes.  For partial inlining we however cannot expect the part
      of builtin implementation to have same semantic as the whole.  */
-  if (DECL_BUILT_IN (node->decl))
-    {
-      DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
-      DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
-    }
+  if (fndecl_built_in_p (node->decl))
+    set_decl_built_in_function (node->decl, NOT_BUILT_IN, 0);
 
   /* If return_bb contains any clobbers that refer to SSA_NAMEs
      set in the split part, remove them.  Also reset debug stmts that
@@ -1412,11 +1417,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
        }
     }
 
-  /* If the original function is instrumented then it's
-     part is also instrumented.  */
-  if (with_bounds)
-    chkp_function_mark_instrumented (node->decl);
-
   /* If the original function is declared inline, there is no point in issuing
      a warning for the non-inlinable part.  */
   DECL_NO_INLINE_WARNING_P (node->decl) = 1;
@@ -1438,6 +1438,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
       }
     else
       break;
+  call_bb->count = split_point->count;
   e = split_block (split_point->entry_bb, last_stmt);
   remove_edge (e);
 
@@ -1451,7 +1452,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
        args_to_pass[i] = arg;
       }
   call = gimple_build_call_vec (node->decl, args_to_pass);
-  gimple_call_set_with_bounds (call, with_bounds);
   gimple_set_block (call, DECL_INITIAL (current_function_decl));
   args_to_pass.release ();
 
@@ -1465,7 +1465,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
     {
       vec<tree, va_gc> **debug_args = NULL;
       unsigned i = 0, len = 0;
-      if (MAY_HAVE_DEBUG_STMTS)
+      if (MAY_HAVE_DEBUG_BIND_STMTS)
        {
          debug_args = decl_debug_args_lookup (node->decl);
          if (debug_args)
@@ -1478,11 +1478,12 @@ split_function (basic_block return_bb, struct split_point *split_point,
            tree ddecl;
            gimple *def_temp;
 
-           /* This needs to be done even without MAY_HAVE_DEBUG_STMTS,
-              otherwise if it didn't exist before, we'd end up with
-              different SSA_NAME_VERSIONs between -g and -g0.  */
+           /* This needs to be done even without
+              MAY_HAVE_DEBUG_BIND_STMTS, otherwise if it didn't exist
+              before, we'd end up with different SSA_NAME_VERSIONs
+              between -g and -g0.  */
            arg = get_or_create_ssa_default_def (cfun, parm);
-           if (!MAY_HAVE_DEBUG_STMTS || debug_args == NULL)
+           if (!MAY_HAVE_DEBUG_BIND_STMTS || debug_args == NULL)
              continue;
 
            while (i < len && (**debug_args)[i] != DECL_ORIGIN (parm))
@@ -1494,6 +1495,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
              = gimple_build_debug_bind (ddecl, unshare_expr (arg), call);
            gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
          }
+      BITMAP_FREE (args_to_skip);
     }
 
   /* We avoid address being taken on any variable used by split part,
@@ -1519,11 +1521,9 @@ split_function (basic_block return_bb, struct split_point *split_point,
     }
   else
     {
-      e = make_edge (call_bb, return_bb,
-                    return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
-                    ? 0 : EDGE_FALLTHRU);
-      e->count = call_bb->count;
-      e->probability = REG_BR_PROB_BASE;
+      e = make_single_succ_edge (call_bb, return_bb,
+                                return_bb == EXIT_BLOCK_PTR_FOR_FN (cfun)
+                                ? 0 : EDGE_FALLTHRU);
 
       /* If there is return basic block, see what value we need to store
          return value into and put call just before it.  */
@@ -1596,21 +1596,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
                            }
                        }
                    }
-
-                 /* Replace retbnd with new one.  */
-                 if (retbnd)
-                   {
-                     gimple_stmt_iterator bsi;
-                     for (bsi = gsi_last_bb (return_bb); !gsi_end_p (bsi);
-                          gsi_prev (&bsi))
-                       if (gimple_code (gsi_stmt (bsi)) == GIMPLE_RETURN)
-                         {
-                           retbnd = copy_ssa_name (retbnd, call);
-                           gimple_return_set_retbnd (gsi_stmt (bsi), retbnd);
-                           update_stmt (gsi_stmt (bsi));
-                           break;
-                         }
-                   }
                }
              if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
                {
@@ -1631,9 +1616,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
                      gsi_insert_after (&gsi, cpy, GSI_NEW_STMT);
                      retval = tem;
                    }
-                 /* Build bndret call to obtain returned bounds.  */
-                 if (retbnd)
-                   chkp_insert_retbnd_call (retbnd, retval, &gsi);
                  gimple_call_set_lhs (call, retval);
                  update_stmt (call);
                }
@@ -1654,10 +1636,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
            {
              retval = DECL_RESULT (current_function_decl);
 
-             if (chkp_function_instrumented_p (current_function_decl)
-                 && BOUNDED_P (retval))
-               retbnd = create_tmp_reg (pointer_bounds_type_node);
-
              /* We use temporary register to hold value when aggregate_value_p
                 is false.  Similarly for DECL_BY_REFERENCE we must avoid extra
                 copy.  */
@@ -1695,9 +1673,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
                  gsi_insert_after (&gsi, g, GSI_NEW_STMT);
                }
            }
-         /* Build bndret call to obtain returned bounds.  */
-         if (retbnd)
-           chkp_insert_retbnd_call (retbnd, retval, &gsi);
          if (tsan_func_exit_call)
            gsi_insert_after (&gsi, tsan_func_exit_call, GSI_NEW_STMT);
          ret = gimple_build_return (retval);
@@ -1706,7 +1681,7 @@ split_function (basic_block return_bb, struct split_point *split_point,
     }
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
-  compute_inline_parameters (node, true);
+  compute_fn_summary (node, true);
 }
 
 /* Execute function splitting pass.  */
@@ -1716,7 +1691,8 @@ execute_split_functions (void)
 {
   gimple_stmt_iterator bsi;
   basic_block bb;
-  int overall_time = 0, overall_size = 0;
+  sreal overall_time = 0;
+  int overall_size = 0;
   int todo = 0;
   struct cgraph_node *node = cgraph_node::get (current_function_decl);
 
@@ -1733,10 +1709,17 @@ execute_split_functions (void)
        fprintf (dump_file, "Not splitting: main function.\n");
       return 0;
     }
+  if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
+    {
+      if (dump_file)
+       fprintf (dump_file, "Not splitting: function is unlikely executed.\n");
+      return 0;
+    }
   /* This can be relaxed; function might become inlinable after splitting
      away the uninlinable part.  */
-  if (inline_edge_summary_vec.exists ()
-      && !inline_summaries->get (node)->inlinable)
+  if (ipa_fn_summaries
+      && ipa_fn_summaries->get (node)
+      && !ipa_fn_summaries->get (node)->inlinable)
     {
       if (dump_file)
        fprintf (dump_file, "Not splitting: not inlinable.\n");
@@ -1775,7 +1758,7 @@ execute_split_functions (void)
      then inlining would still benefit.  */
   if ((!node->callers
        /* Local functions called once will be completely inlined most of time.  */
-       || (!node->callers->next_caller && node->local.local))
+       || (!node->callers->next_caller && node->local))
       && !node->address_taken
       && !node->has_aliases_p ()
       && (!flag_lto || !node->externally_visible))
@@ -1796,6 +1779,20 @@ execute_split_functions (void)
       return 0;
     }
 
+  if (lookup_attribute ("noinline", DECL_ATTRIBUTES (current_function_decl)))
+    {
+      if (dump_file)
+       fprintf (dump_file, "Not splitting: function is noinline.\n");
+      return 0;
+    }
+  if (lookup_attribute ("section", DECL_ATTRIBUTES (current_function_decl)))
+    {
+      if (dump_file)
+       fprintf (dump_file, "Not splitting: function is in user defined "
+                "section.\n");
+      return 0;
+    }
+
   /* We enforce splitting after loop headers when profile info is not
      available.  */
   if (profile_status_for_fn (cfun) != PROFILE_READ)
@@ -1806,35 +1803,38 @@ execute_split_functions (void)
   calculate_dominance_info (CDI_DOMINATORS);
 
   /* Compute local info about basic blocks and determine function size/time.  */
-  bb_info_vec.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1);
-  memset (&best_split_point, 0, sizeof (best_split_point));
+  bb_info_vec.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1, true);
+  best_split_point.split_bbs = NULL;
   basic_block return_bb = find_return_bb ();
   int tsan_exit_found = -1;
   FOR_EACH_BB_FN (bb, cfun)
     {
-      int time = 0;
+      sreal time = 0;
       int size = 0;
-      int freq = compute_call_stmt_bb_frequency (current_function_decl, bb);
+      sreal freq = bb->count.to_sreal_scale
+                        (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count);
 
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file, "Basic block %i\n", bb->index);
 
       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
        {
-         int this_time, this_size;
+         sreal this_time;
+         int this_size;
          gimple *stmt = gsi_stmt (bsi);
 
          this_size = estimate_num_insns (stmt, &eni_size_weights);
-         this_time = estimate_num_insns (stmt, &eni_time_weights) * freq;
+         this_time = (sreal)estimate_num_insns (stmt, &eni_time_weights)
+                        * freq;
          size += this_size;
          time += this_time;
          check_forbidden_calls (stmt);
 
          if (dump_file && (dump_flags & TDF_DETAILS))
            {
-             fprintf (dump_file, "  freq:%6i size:%3i time:%3i ",
-                      freq, this_size, this_time);
-             print_gimple_stmt (dump_file, stmt, 0, 0);
+             fprintf (dump_file, "  freq:%4.2f size:%3i time:%4.2f ",
+                      freq.to_double (), this_size, this_time.to_double ());
+             print_gimple_stmt (dump_file, stmt, 0);
            }
 
          if ((flag_sanitize & SANITIZE_THREAD)