This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Cgraph optimization summary streaming


Hi,
this patch adds streaming of cgraph optimizations summaries.  This contains
part of cgraph that needs to be streamed from WPA to ltrans unit since it
contains decision of optimizers.  This is different from pass specific
optimization summaries in a way that it contains bits sotred dirrectly in the callgraph.
At the moment it is clonning info for virtual clones, but in future I will
move there some other stuff, such as inline_failed info that does not need to
be part of cgraph ssection (that I want to be the same for lto and wpa->ltrans
streaming.

there is a problem that tree_map structure used to control replacement in
clonning contains pointers to function local nodes. At the moment they are
always parm_decls so I aded simple special purpose code for that.
I kept the old_tree pointer since we use it for some non-param transforms
in C++ and open-mp as well as I have some more future plans with it.
I am not sure if we will want to develop generic way to store references
to function body, or just stay with few special cases we need.  I guess
the second option is quite viable.

With few additional changes this patch allows ipa-cp to work at WPA level.

Bootstrapped/regtested x86_64, OK?
	* cgraph.h (struct ipa_replace_map): Add parm_num parameter.
	* lto-cgraph.c (output_cgraph_opt_summary, input_cgraph_opt_summary):
	New functions.
	(output_cgraph): Call output_cgraph_opt_summary.
	(input_cgrpah): Call input_cgraph_opt_summary.
	(output_cgraph_opt_summary_p, output_node_opt_summary,
	input_node_opt_summary, input_cgraph_opt_section): New functions.
	* lto-section-in.c (lto_section_name): Add cgraphopt.
	* tree-inline.c (tree_function_versioning): Handle parm_num.
	* lto-streamer.c (lto_get_section_name): Handle cgraphopt.
	* lto-streamer.h (lto_section_type): Add LTO_section_cgraph_opt_sum.
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 159467)
+++ cgraph.h	(working copy)
@@ -157,6 +157,8 @@ struct GTY(()) ipa_replace_map
   tree old_tree;
   /* The new (replacing) tree.  */
   tree new_tree;
+  /* Parameter number to replace, when old_tree is NULL.  */
+  int parm_num;
   /* True when a substitution should be done, false otherwise.  */
   bool replace_p;
   /* True when we replace a reference to old_tree.  */
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 159467)
+++ lto-cgraph.c	(working copy)
@@ -47,6 +47,9 @@ along with GCC; see the file COPYING3.  
 #include "gcov-io.h"
 
 static void output_varpool (cgraph_node_set, varpool_node_set);
+static void output_cgraph_opt_summary (void);
+static void input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes);
+
 
 /* Cgraph streaming is organized as set of record whose type
    is indicated by a tag.  */
@@ -840,6 +843,9 @@ output_cgraph (cgraph_node_set set, varp
   lto_varpool_encoder_t varpool_encoder;
   struct cgraph_asm_node *can;
 
+  if (flag_wpa)
+    output_cgraph_opt_summary ();
+
   ob = lto_create_simple_output_block (LTO_section_cgraph);
 
   output_profile_summary (ob);
@@ -1403,6 +1409,8 @@ input_cgraph (void)
       input_refs (ib, nodes, varpool);
       lto_destroy_simple_input_block (file_data, LTO_section_refs,
 				      ib, data, len);
+      if (flag_ltrans)
+	input_cgraph_opt_summary (nodes);
       VEC_free (cgraph_node_ptr, heap, nodes);
       VEC_free (varpool_node_ptr, heap, varpool);
     }
@@ -1420,3 +1428,197 @@ input_cgraph (void)
 	node->aux = NULL;
     }
 }
+
+/* True when we need optimization summary for NODE.  */
+
+static int
+output_cgraph_opt_summary_p (struct cgraph_node *node)
+{
+  if (!node->clone_of)
+    return false;
+  return (node->clone.tree_map
+          || node->clone.args_to_skip
+          || node->clone.combined_args_to_skip);
+}
+
+/* Output optimization summary for NODE to OB.  */
+
+static void
+output_node_opt_summary (struct output_block *ob,
+			 struct cgraph_node *node)
+{
+  unsigned int index;
+  bitmap_iterator bi;
+  struct ipa_replace_map *map;
+  struct bitpack_d *bp;
+  int i;
+
+  lto_output_uleb128_stream (ob->main_stream,
+			     bitmap_count_bits (node->clone.args_to_skip));
+  EXECUTE_IF_SET_IN_BITMAP (node->clone.args_to_skip, 0, index, bi)
+    lto_output_uleb128_stream (ob->main_stream, index);
+  lto_output_uleb128_stream (ob->main_stream,
+			     bitmap_count_bits (node->clone.combined_args_to_skip));
+  EXECUTE_IF_SET_IN_BITMAP (node->clone.combined_args_to_skip, 0, index, bi)
+    lto_output_uleb128_stream (ob->main_stream, index);
+  lto_output_uleb128_stream (ob->main_stream,
+		             VEC_length (ipa_replace_map_p, node->clone.tree_map));
+  for (i = 0; VEC_iterate (ipa_replace_map_p, node->clone.tree_map, i, map); i++)
+    {
+      int parm_num;
+      tree parm;
+
+      for (parm_num = 0, parm = DECL_ARGUMENTS (node->decl); parm;
+	   parm = TREE_CHAIN (parm), parm_num ++)
+	if (map->old_tree == parm)
+	  break;
+      /* At the moment we assume all old trees to be PARM_DECLs, because we have no
+         mechanism to store function local declarations into summaries.  */
+      gcc_assert (parm);
+      lto_output_uleb128_stream (ob->main_stream, parm_num);
+      lto_output_tree (ob, map->new_tree, true);
+      bp = bitpack_create ();
+      bp_pack_value (bp, map->replace_p, 1);
+      bp_pack_value (bp, map->ref_p, 1);
+      lto_output_bitpack (ob->main_stream, bp);
+      bitpack_delete (bp);
+    }
+}
+
+/* Output optimization summaries stored in callgraph.
+   At the moment it is the clone info structure.  */
+
+static void
+output_cgraph_opt_summary (void)
+{
+  struct cgraph_node *node;
+  int i, n_nodes;
+  lto_cgraph_encoder_t encoder;
+  struct output_block *ob = create_output_block (LTO_section_cgraph_opt_sum);
+  unsigned count = 0;
+
+  ob->cgraph_node = NULL;
+  encoder = ob->decl_state->cgraph_node_encoder;
+  n_nodes = lto_cgraph_encoder_size (encoder);
+  for (i = 0; i < n_nodes; i++)
+    if (output_cgraph_opt_summary_p (lto_cgraph_encoder_deref (encoder, i)))
+      count++;
+  lto_output_uleb128_stream (ob->main_stream, count);
+  for (i = 0; i < n_nodes; i++)
+    {
+      node = lto_cgraph_encoder_deref (encoder, i);
+      if (output_cgraph_opt_summary_p (node))
+	{
+	  lto_output_uleb128_stream (ob->main_stream, i);
+	  output_node_opt_summary (ob, node);
+	}
+    }
+  produce_asm (ob, NULL);
+  destroy_output_block (ob);
+}
+
+/* Input optimiation summary of NODE.  */
+
+static void
+input_node_opt_summary (struct cgraph_node *node,
+			struct lto_input_block *ib_main,
+			struct data_in *data_in)
+{
+  int i;
+  int count;
+  int bit;
+  struct bitpack_d *bp;
+
+  count = lto_input_uleb128 (ib_main);
+  if (count)
+    node->clone.args_to_skip = BITMAP_GGC_ALLOC ();
+  for (i = 0; i < count; i++)
+    {
+      bit = lto_input_uleb128 (ib_main);
+      bitmap_set_bit (node->clone.args_to_skip, bit);
+    }
+  count = lto_input_uleb128 (ib_main);
+  if (count)
+    node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC ();
+  for (i = 0; i < count; i++)
+    {
+      bit = lto_input_uleb128 (ib_main);
+      bitmap_set_bit (node->clone.combined_args_to_skip, bit);
+    }
+  count = lto_input_uleb128 (ib_main);
+  for (i = 0; i < count; i++)
+    {
+      int parm_num;
+      tree parm;
+      struct ipa_replace_map *map = GGC_NEW (struct ipa_replace_map);
+
+      VEC_safe_push (ipa_replace_map_p, gc, node->clone.tree_map, map);
+      for (parm_num = 0, parm = DECL_ARGUMENTS (node->decl); parm_num;
+	   parm = TREE_CHAIN (parm))
+	parm_num --;
+      map->parm_num = lto_input_uleb128 (ib_main);
+      map->old_tree = NULL;
+      map->new_tree = lto_input_tree (ib_main, data_in);
+      bp = lto_input_bitpack (ib_main);
+      map->replace_p = bp_unpack_value (bp, 1);
+      map->ref_p = bp_unpack_value (bp, 1);
+      bitpack_delete (bp);
+    }
+}
+
+/* Read section in file FILE_DATA of length LEN with data DATA.  */
+
+static void
+input_cgraph_opt_section (struct lto_file_decl_data *file_data,
+			  const char *data, size_t len, VEC (cgraph_node_ptr,
+							     heap) * nodes)
+{
+  const struct lto_function_header *header =
+    (const struct lto_function_header *) data;
+  const int32_t cfg_offset = sizeof (struct lto_function_header);
+  const int32_t main_offset = cfg_offset + header->cfg_size;
+  const int32_t string_offset = main_offset + header->main_size;
+  struct data_in *data_in;
+  struct lto_input_block ib_main;
+  unsigned int i;
+  unsigned int count;
+
+  LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0,
+			header->main_size);
+
+  data_in =
+    lto_data_in_create (file_data, (const char *) data + string_offset,
+			header->string_size, NULL);
+  count = lto_input_uleb128 (&ib_main);
+
+  for (i = 0; i < count; i++)
+    {
+      int ref = lto_input_uleb128 (&ib_main);
+      input_node_opt_summary (VEC_index (cgraph_node_ptr, nodes, ref),
+			      &ib_main, data_in);
+    }
+  lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
+			 len);
+  lto_data_in_delete (data_in);
+}
+
+/* Input optimization summary of cgraph.  */
+
+static void
+input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes)
+{
+  struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
+  struct lto_file_decl_data *file_data;
+  unsigned int j = 0;
+
+  while ((file_data = file_data_vec[j++]))
+    {
+      size_t len;
+      const char *data =
+	lto_get_section_data (file_data, LTO_section_cgraph_opt_sum, NULL,
+			      &len);
+
+      if (data)
+	input_cgraph_opt_section (file_data, data, len, nodes);
+    }
+}
Index: lto-section-in.c
===================================================================
--- lto-section-in.c	(revision 159467)
+++ lto-section-in.c	(working copy)
@@ -58,7 +58,8 @@ const char *lto_section_name[LTO_N_SECTI
   "ipa_pure_const",
   "ipa_reference",
   "symtab",
-  "opts"
+  "opts",
+  "cgraphopt"
 };
 
 unsigned char
Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 159467)
+++ tree-inline.c	(working copy)
@@ -4945,6 +4945,15 @@ tree_function_versioning (tree old_decl,
 	if (replace_info->replace_p)
 	  {
 	    tree op = replace_info->new_tree;
+	    if (!replace_info->old_tree)
+	      {
+		int i = replace_info->parm_num;
+		tree parm;
+		for (parm = DECL_ARGUMENTS (old_decl); i; parm = TREE_CHAIN (parm))
+		  i --;
+		replace_info->old_tree = parm;
+	      }
+		
 
 	    STRIP_NOPS (op);
 
Index: lto-streamer.c
===================================================================
--- lto-streamer.c	(revision 159467)
+++ lto-streamer.c	(working copy)
@@ -178,6 +178,9 @@ lto_get_section_name (int section_type, 
     case LTO_section_opts:
       return concat (LTO_SECTION_NAME_PREFIX, ".opts", NULL);
 
+    case LTO_section_cgraph_opt_sum:
+      return concat (LTO_SECTION_NAME_PREFIX, ".cgraphopt", NULL);
+
     default:
       internal_error ("bytecode stream: unexpected LTO section %s", name);
     }
Index: lto-streamer.h
===================================================================
--- lto-streamer.h	(revision 159467)
+++ lto-streamer.h	(working copy)
@@ -264,6 +264,7 @@ enum lto_section_type
   LTO_section_ipa_reference,
   LTO_section_symtab,
   LTO_section_opts,
+  LTO_section_cgraph_opt_sum,
   LTO_N_SECTION_TYPES		/* Must be last.  */
 };
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]