diff gcc/ipa-split.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
line wrap: on
line diff
--- a/gcc/ipa-split.c	Thu Oct 25 07:37:49 2018 +0900
+++ b/gcc/ipa-split.c	Thu Feb 13 11:34:05 2020 +0900
@@ -1,5 +1,5 @@
 /* Function splitting pass
-   Copyright (C) 2010-2018 Free Software Foundation, Inc.
+   Copyright (C) 2010-2020 Free Software Foundation, Inc.
    Contributed by Jan Hubicka  <jh@suse.cz>
 
 This file is part of GCC.
@@ -100,15 +100,16 @@
 #include "tree-into-ssa.h"
 #include "tree-dfa.h"
 #include "tree-inline.h"
-#include "params.h"
 #include "gimple-pretty-print.h"
 #include "ipa-fnsummary.h"
 #include "cfgloop.h"
+#include "attribs.h"
 
 /* Per basic block info.  */
 
-struct split_bb_info
+class split_bb_info
 {
+public:
   unsigned int size;
   sreal time;
 };
@@ -117,8 +118,9 @@
 
 /* Description of split point.  */
 
-struct split_point
+class split_point
 {
+public:
   /* Size of the partitions.  */
   sreal header_time, split_time;
   unsigned int header_size, split_size;
@@ -143,7 +145,7 @@
 
 /* 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.  */
 
@@ -166,7 +168,7 @@
       || (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
@@ -190,7 +192,7 @@
 /* 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"
@@ -209,7 +211,7 @@
    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);
@@ -403,7 +405,7 @@
 /* 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)
@@ -420,7 +422,7 @@
    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;
@@ -450,10 +452,10 @@
      is unknown.  */
   if (!(current->count
        < (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.apply_scale
-	   (PARAM_VALUE (PARAM_PARTIAL_INLINING_ENTRY_PROBABILITY), 100))))
+	   (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.  */
@@ -560,8 +562,8 @@
      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) + 10)
+			? param_max_inline_insns_single
+			: param_max_inline_insns_auto) + 10)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
 	fprintf (dump_file,
@@ -574,7 +576,7 @@
      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 + 10)
+      && current->split_size >= (unsigned int) param_max_inline_insns_auto + 10)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
 	fprintf (dump_file,
@@ -586,7 +588,7 @@
      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,
@@ -729,7 +731,7 @@
    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.
 
@@ -878,7 +880,7 @@
       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 
@@ -978,8 +980,9 @@
 
 /* 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;
 
@@ -1003,7 +1006,7 @@
   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;
 };
 
@@ -1031,7 +1034,7 @@
   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;
@@ -1071,7 +1074,7 @@
 	  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)
 	     {
@@ -1177,7 +1180,7 @@
 /* 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;
@@ -1200,7 +1203,7 @@
       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;
@@ -1322,13 +1325,38 @@
 	  }
     }
 
+  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)
@@ -1341,16 +1369,14 @@
 
 
   /* 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 (fndecl_built_in_p (node->decl))
-    {
-      DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
-      DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
-    }
+    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
@@ -1468,6 +1494,7 @@
 	      = 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,
@@ -1730,7 +1757,7 @@
      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))
@@ -1751,6 +1778,20 @@
       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)