LTO/WHOPR summary streaming fixes

Jan Hubicka hubicka@ucw.cz
Wed Oct 21 17:55:00 GMT 2009


Hi,
I got somewhat lucky in testing previous patch since dumping of jump functions
was pretty much disabled by mismatch in headers of sections and they still got
recomputed due to bug in passmanager change.

This patch finally does the trick, but there are few extra changes in addition
to comment fixes requested by Diego.

  1) I now use produce_asm to get the section output with header.  This makes me
     to re-use function header that gets care of offsets and such.

     Same trick is already done by initializer pool.  Later I would like to
     cleanup the API so we have simple way of creating the output block with
     their own output block header containing the offsets needed and
     functions/decls/summaries can then use the block and embedd whatever
     headers they need into their main block.  But for now I just use that code
     since the patch has too much of snowballing effect.
  2) Added code into lto-stream-in.c to make whopr execute inliner transform method.
     Previously this was completely missed so we got clean run without checking
     only.
  3) There are several bugfixes into streaming in/out the data.
  4) LTO was saving work by not analyzing call to functions external to the unit.
     With LTO we need to analyze everything in hope that at linktime these
     won't be external.
  5) The cgraph during streaming differs from cgraph read back in a way that
     all calls appears in reversed order.  This confuse way I store call site info
     (that is just sequence in callgraph order) and also will make optimizations
     to diverge.  Fixed by streaming all callgraph edges in backward order.

     It might be prettier to output them in normal order and reverse list later,
     but I doubt it makes difference given that the files we produce are complette
     mess at the moment anyway.  I plan to do pass on cgraph streaming and avoid
     streaming unnecesary stuff etc. I can get this prettier then.

Regtested x86_64-linux, I am bootstrapping now.  OK?

	* ipa-cp.c (ipcp_write_summary, ipcp_read_summary): New functions.
	(pass_ipa_cp): Register them.
	(ipcp_init_stage): Analyze all functions for whopr/lto.
	(ipcp_propagate_stage): Skip external calls.
	* ipa-reference.c (write_node_summary_p): Fix thinko about availability.
	* cgraphunit.c (ipa_passes): When in lto, ne er produce new summaries;
	when in ltrans, skip executing of ipa passes since everything should've
	been done.
	* ipa-inline.c (cgraph_decide_inlining): Remove FIXMEs.
	(inline_generate_summary): Likewise.
	(inline_read_summary): New function.
	(inline_write_summary): New function.
	(pass_ipa_inline): Register new hooks.
	* ipa-prop.c: Inlcude lto-streamer.h
	(ipa_write_jump_function, ipa_read_jump_function, ipa_write_node_info,
	ipa_read_node_info): New static functions.
	(ipa_prop_write_jump_functions, ipa_prop_read_jump_functions): Update.
	* ipa-prop.h (ipa_prop_write_jump_functions,
	ipa_prop_read_jump_functions): Declare.
	* passes.c (ipa_write_summaries_1): When in wpa, do not write summaries.
	(ipa_read_summaries): When in ltrans, so not read summaries.
	* lto-streamer.c (lto_get_section_name): Add LTO_section_jump_functions.
	* lto-streamer.h (LTO_section_jump_functions): New section.
	(produce_asm): Declare.
	* lto-cgraph.c (output_cgraph): Output edges in reverse order.
	* lto-streamer-out.c (produce_asm): Export.
	* lto-streamer-in.c: Include tree-pass.h
	(lto_read_body): Push ipa_inline in ltrans stage.
Index: ipa-cp.c
===================================================================
*** ipa-cp.c	(revision 152974)
--- ipa-cp.c	(working copy)
*************** ipcp_init_stage (void)
*** 614,620 ****
        /* building jump functions  */
        for (cs = node->callees; cs; cs = cs->next_callee)
  	{
! 	  if (!cs->callee->analyzed)
  	    continue;
  	  ipa_count_arguments (cs);
  	  if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
--- 614,622 ----
        /* building jump functions  */
        for (cs = node->callees; cs; cs = cs->next_callee)
  	{
! 	  /* We do not need to bother analyzing calls to unknown
! 	     functions unless they may become known during lto/whopr.  */
! 	  if (!cs->callee->analyzed && !flag_lto && !flag_whopr)
  	    continue;
  	  ipa_count_arguments (cs);
  	  if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
*************** ipcp_propagate_stage (void)
*** 696,702 ****
  	  struct ipa_node_params *callee_info = IPA_NODE_REF (cs->callee);
  	  struct ipa_edge_args *args = IPA_EDGE_REF (cs);
  
! 	  if (ipa_is_called_with_var_arguments (callee_info))
  	    continue;
  
  	  count = ipa_get_cs_argument_count (args);
--- 698,705 ----
  	  struct ipa_node_params *callee_info = IPA_NODE_REF (cs->callee);
  	  struct ipa_edge_args *args = IPA_EDGE_REF (cs);
  
! 	  if (ipa_is_called_with_var_arguments (callee_info)
! 	      || !cs->callee->analyzed)
  	    continue;
  
  	  count = ipa_get_cs_argument_count (args);
*************** ipcp_generate_summary (void)
*** 1276,1281 ****
--- 1279,1298 ----
    ipcp_init_stage ();
  }
  
+ /* Write ipcp summary for nodes in SET.  */
+ static void
+ ipcp_write_summary (cgraph_node_set set)
+ {
+   ipa_prop_write_jump_functions (set);
+ }
+ 
+ /* Read ipcp summary.  */
+ static void
+ ipcp_read_summary (void)
+ {
+   ipa_prop_read_jump_functions ();
+ }
+ 
  /* Gate for IPCP optimization.  */
  static bool
  cgraph_gate_cp (void)
*************** struct ipa_opt_pass_d pass_ipa_cp =
*** 1308,1315 ****
    TODO_remove_functions /* todo_flags_finish */
   },
   ipcp_generate_summary,			/* generate_summary */
!  NULL,					/* write_summary */
!  NULL,					/* read_summary */
   NULL,					/* function_read_summary */
   0,					/* TODOs */
   NULL,					/* function_transform */
--- 1325,1332 ----
    TODO_remove_functions /* todo_flags_finish */
   },
   ipcp_generate_summary,			/* generate_summary */
!  ipcp_write_summary,			/* write_summary */
!  ipcp_read_summary,			/* read_summary */
   NULL,					/* function_read_summary */
   0,					/* TODOs */
   NULL,					/* function_transform */
Index: ipa-reference.c
===================================================================
*** ipa-reference.c	(revision 152974)
--- ipa-reference.c	(working copy)
*************** write_node_summary_p (struct cgraph_node
*** 1014,1020 ****
  {
    return (node->analyzed 
  	  && node->global.inlined_to == NULL
! 	  && cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE
  	  && get_reference_vars_info (node) != NULL);
  }
  
--- 1014,1020 ----
  {
    return (node->analyzed 
  	  && node->global.inlined_to == NULL
! 	  && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE
  	  && get_reference_vars_info (node) != NULL);
  }
  
Index: cgraphunit.c
===================================================================
*** cgraphunit.c	(revision 152974)
--- cgraphunit.c	(working copy)
*************** ipa_passes (void)
*** 1375,1389 ****
        set_cfun (NULL);
        current_function_decl = NULL;
        cgraph_process_new_functions ();
-     }
  
!   execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
    execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
  
    if (!in_lto_p)
      ipa_write_summaries ();
  
!   execute_ipa_pass_list (all_regular_ipa_passes);
  
    bitmap_obstack_release (NULL);
  }
--- 1375,1390 ----
        set_cfun (NULL);
        current_function_decl = NULL;
        cgraph_process_new_functions ();
  
!       execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_regular_ipa_passes);
!     }
    execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
  
    if (!in_lto_p)
      ipa_write_summaries ();
  
!   if (!flag_ltrans)
!     execute_ipa_pass_list (all_regular_ipa_passes);
  
    bitmap_obstack_release (NULL);
  }
Index: lto-cgraph.c
===================================================================
*** lto-cgraph.c	(revision 152974)
--- lto-cgraph.c	(working copy)
*************** output_cgraph (cgraph_node_set set)
*** 372,379 ****
    for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
      {
        node = csi_node (csi);
!       for (edge = node->callees; edge; edge = edge->next_callee)
! 	lto_output_edge (ob, edge, encoder);
      }
  
    lto_output_uleb128_stream (ob->main_stream, 0);
--- 372,387 ----
    for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
      {
        node = csi_node (csi);
!       if (node->callees)
!         {
! 	  /* Output edges in backward direction, so the reconstructed callgraph
! 	     match and it is easy to associate call sites in the IPA pass summaries.  */
! 	  edge = node->callees;
! 	  while (edge->next_callee)
! 	    edge = edge->next_callee;
! 	  for (; edge; edge = edge->prev_callee)
! 	    lto_output_edge (ob, edge, encoder);
! 	}
      }
  
    lto_output_uleb128_stream (ob->main_stream, 0);
Index: lto-streamer-out.c
===================================================================
*** lto-streamer-out.c	(revision 152974)
--- lto-streamer-out.c	(working copy)
*************** output_bb (struct output_block *ob, basi
*** 1762,1768 ****
  /* Create the header in the file using OB.  If the section type is for
     a function, set FN to the decl for that function.  */
  
! static void
  produce_asm (struct output_block *ob, tree fn)
  {
    enum lto_section_type section_type = ob->section_type;
--- 1762,1768 ----
  /* Create the header in the file using OB.  If the section type is for
     a function, set FN to the decl for that function.  */
  
! void
  produce_asm (struct output_block *ob, tree fn)
  {
    enum lto_section_type section_type = ob->section_type;
Index: ipa-inline.c
===================================================================
*** ipa-inline.c	(revision 152974)
--- ipa-inline.c	(working copy)
*************** cgraph_decide_inlining (void)
*** 1113,1125 ****
    bool redo_always_inline = true;
    int initial_size = 0;
  
!   /* FIXME lto.  We need to rethink how to coordinate different passes. */
!   if (flag_ltrans)
!     return 0;
! 
!   /* FIXME lto.  We need to re-think about how the passes get invoked. */
!   if (!flag_wpa)
!     cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
  
    max_count = 0;
    max_benefit = 0;
--- 1113,1119 ----
    bool redo_always_inline = true;
    int initial_size = 0;
  
!   cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
  
    max_count = 0;
    max_benefit = 0;
*************** inline_generate_summary (void)
*** 1928,1937 ****
  {
    struct cgraph_node *node;
  
-   /* FIXME lto.  We should not run any IPA-summary pass in LTRANS mode.  */
-   if (flag_ltrans)
-     return;
- 
    function_insertion_hook_holder =
        cgraph_add_function_insertion_hook (&add_new_function, NULL);
  
--- 1922,1927 ----
*************** inline_transform (struct cgraph_node *no
*** 1976,1981 ****
--- 1966,1999 ----
    return todo | execute_fixup_cfg ();
  }
  
+ /* Read inline summary.  Jump functions are shared among ipa-cp
+    and inliner, so when ipa-cp is active, we don't need to write them
+    twice.  */
+ 
+ static void 
+ inline_read_summary (void)
+ {
+   if (flag_indirect_inlining)
+     {
+       ipa_register_cgraph_hooks ();
+       if (!flag_ipa_cp)
+         ipa_prop_read_jump_functions ();
+     }
+   function_insertion_hook_holder =
+       cgraph_add_function_insertion_hook (&add_new_function, NULL);
+ }
+ 
+ /* Write inline summary for node in SET.
+    Jump functions are shared among ipa-cp and inliner, so when ipa-cp is
+    active, we don't need to write them twice.  */
+ 
+ static void 
+ inline_write_summary (cgraph_node_set set)
+ {
+   if (flag_indirect_inlining && !flag_ipa_cp)
+     ipa_prop_write_jump_functions (set);
+ }
+ 
  struct ipa_opt_pass_d pass_ipa_inline =
  {
   {
*************** struct ipa_opt_pass_d pass_ipa_inline =
*** 1995,2002 ****
    | TODO_remove_functions		/* todo_flags_finish */
   },
   inline_generate_summary,		/* generate_summary */
!  NULL,					/* write_summary */
!  NULL,					/* read_summary */
   NULL,					/* function_read_summary */
   0,					/* TODOs */
   inline_transform,			/* function_transform */
--- 2013,2020 ----
    | TODO_remove_functions		/* todo_flags_finish */
   },
   inline_generate_summary,		/* generate_summary */
!  inline_write_summary,			/* write_summary */
!  inline_read_summary,			/* read_summary */
   NULL,					/* function_read_summary */
   0,					/* TODOs */
   inline_transform,			/* function_transform */
Index: lto-streamer-in.c
===================================================================
*** lto-streamer-in.c	(revision 152974)
--- lto-streamer-in.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 47,52 ****
--- 47,53 ----
  #include "output.h"
  #include "ipa-utils.h"
  #include "lto-streamer.h"
+ #include "tree-pass.h"
  
  /* Data structure used to hash file names in the source_location field.  */
  struct string_slot
*************** lto_read_body (struct lto_file_decl_data
*** 1455,1460 ****
--- 1456,1470 ----
        /* Restore decl state */
        file_data->current_decl_state = file_data->global_decl_state;
  
+       /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization
+          summaries computed and needs to apply changes.  At the moment WHOPR only
+          supports inlining, so we can push it here by hand.  In future we need to stream
+          this field into ltrans compilation.  This will also need to move the field
+ 	 from struct function into cgraph node where it belongs.  */
+       if (flag_ltrans)
+ 	 VEC_safe_push (ipa_opt_pass, heap,
+ 			cfun->ipa_transforms_to_apply,
+ 			(ipa_opt_pass)&pass_ipa_inline);
        pop_cfun ();
      }
    else 
Index: ipa-prop.c
===================================================================
*** ipa-prop.c	(revision 152974)
--- ipa-prop.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 33,38 ****
--- 33,39 ----
  #include "timevar.h"
  #include "flags.h"
  #include "diagnostic.h"
+ #include "lto-streamer.h"
  
  /* Vector where the parameter infos are actually stored. */
  VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
*************** ipa_dump_param_adjustments (FILE *file, 
*** 1875,1877 ****
--- 1876,2134 ----
    VEC_free (tree, heap, parms);
  }
  
+ /* Stream out jump function JUMP_FUNC to OB.  */
+ 
+ static void
+ ipa_write_jump_function (struct output_block *ob,
+ 			 struct ipa_jump_func *jump_func)
+ {
+   lto_output_uleb128_stream (ob->main_stream,
+ 			     jump_func->type);
+ 
+   switch (jump_func->type)
+     {
+     case IPA_JF_UNKNOWN:
+       break;
+     case IPA_JF_CONST:
+       lto_output_tree (ob, jump_func->value.constant, true);
+       break;
+     case IPA_JF_PASS_THROUGH:
+       lto_output_tree (ob, jump_func->value.pass_through.operand, true);
+       lto_output_uleb128_stream (ob->main_stream,
+ 				 jump_func->value.pass_through.formal_id);
+       lto_output_uleb128_stream (ob->main_stream,
+ 				 jump_func->value.pass_through.operation);
+       break;
+     case IPA_JF_ANCESTOR:
+       lto_output_uleb128_stream (ob->main_stream,
+ 				 jump_func->value.ancestor.offset);
+       lto_output_tree (ob, jump_func->value.ancestor.type, true);
+       lto_output_uleb128_stream (ob->main_stream,
+ 				 jump_func->value.ancestor.formal_id);
+       break;
+     case IPA_JF_CONST_MEMBER_PTR:
+       lto_output_tree (ob, jump_func->value.member_cst.pfn, true);
+       lto_output_tree (ob, jump_func->value.member_cst.delta, false);
+       break;
+     }
+ }
+ 
+ /* Read in jump function JUMP_FUNC from IB.  */
+ 
+ static void
+ ipa_read_jump_function (struct lto_input_block *ib,
+ 			struct ipa_jump_func *jump_func,
+ 			struct data_in *data_in)
+ {
+   jump_func->type = (enum jump_func_type) lto_input_uleb128 (ib);
+ 
+   switch (jump_func->type)
+     {
+     case IPA_JF_UNKNOWN:
+       break;
+     case IPA_JF_CONST:
+       jump_func->value.constant = lto_input_tree (ib, data_in);
+       break;
+     case IPA_JF_PASS_THROUGH:
+       jump_func->value.pass_through.operand = lto_input_tree (ib, data_in);
+       jump_func->value.pass_through.formal_id = lto_input_uleb128 (ib);
+       jump_func->value.pass_through.operation = (enum tree_code) lto_input_uleb128 (ib);
+       break;
+     case IPA_JF_ANCESTOR:
+       jump_func->value.ancestor.offset = lto_input_uleb128 (ib);
+       jump_func->value.ancestor.type = lto_input_tree (ib, data_in);
+       jump_func->value.ancestor.formal_id = lto_input_uleb128 (ib);
+       break;
+     case IPA_JF_CONST_MEMBER_PTR:
+       jump_func->value.member_cst.pfn = lto_input_tree (ib, data_in);
+       jump_func->value.member_cst.delta = lto_input_tree (ib, data_in);
+       break;
+     }
+ }
+ 
+ /* Stream out NODE info to OB.  */
+ 
+ static void
+ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
+ {
+   int node_ref;
+   lto_cgraph_encoder_t encoder;
+   struct ipa_node_params *info = IPA_NODE_REF (node);
+   int j;
+   struct cgraph_edge *e;
+   struct bitpack_d *bp;
+ 
+   encoder = ob->decl_state->cgraph_node_encoder;
+   node_ref = lto_cgraph_encoder_encode (encoder, node);
+   lto_output_uleb128_stream (ob->main_stream, node_ref);
+ 
+   /* Note that flags will need to be read in the opposite
+      order as we are pushing the bitflags into FLAGS.  */
+   bp = bitpack_create ();
+   bp_pack_value (bp, info->called_with_var_arguments, 1);
+   gcc_assert (info->modification_analysis_done || ipa_get_param_count (info) == 0);
+   gcc_assert (info->uses_analysis_done || ipa_get_param_count (info) == 0);
+   gcc_assert (!info->node_enqueued);
+   gcc_assert (!info->ipcp_orig_node);
+   for (j = 0; j < ipa_get_param_count (info); j++)
+     {
+       bp_pack_value (bp, info->params[j].modified, 1);
+       bp_pack_value (bp, info->params[j].called, 1);
+     }
+   lto_output_bitpack (ob->main_stream, bp);
+   bitpack_delete (bp);
+   for (e = node->callees; e; e = e->next_callee)
+     {
+       struct ipa_edge_args *args = IPA_EDGE_REF (e);
+ 
+       lto_output_uleb128_stream (ob->main_stream, ipa_get_cs_argument_count (args));
+       for (j = 0; j < ipa_get_cs_argument_count (args); j++)
+ 	ipa_write_jump_function (ob, ipa_get_ith_jump_func (args, j));
+     }
+ }
+ 
+ /* Srtream in NODE info from IB.  */
+ 
+ static void
+ ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node,
+ 		    struct data_in *data_in)
+ {
+   struct ipa_node_params *info = IPA_NODE_REF (node);
+   int k;
+   struct cgraph_edge *e;
+   struct bitpack_d *bp;
+ 
+   ipa_initialize_node_params (node);
+ 
+   /* Note that the flags must be read in the opposite
+      order in which they were written (the bitflags were
+      pushed into FLAGS).  */
+   bp = lto_input_bitpack (ib);
+   info->called_with_var_arguments = bp_unpack_value (bp, 1);
+   if (ipa_get_param_count (info) != 0)
+     {
+       info->modification_analysis_done = true;
+       info->uses_analysis_done = true;
+     }
+   info->node_enqueued = false;
+   for (k = 0; k < ipa_get_param_count (info); k++)
+     {
+       info->params[k].modified = bp_unpack_value (bp, 1);
+       info->params[k].called = bp_unpack_value (bp, 1);
+     }
+   bitpack_delete (bp);
+   for (e = node->callees; e; e = e->next_callee)
+     {
+       struct ipa_edge_args *args = IPA_EDGE_REF (e);
+       int count = lto_input_uleb128 (ib);
+ 
+       if (VEC_length (ipa_edge_args_t, ipa_edge_args_vector)
+ 	  <= (unsigned) cgraph_edge_max_uid)
+ 	VEC_safe_grow_cleared (ipa_edge_args_t, heap,
+ 			       ipa_edge_args_vector, cgraph_edge_max_uid + 1);
+       ipa_set_cs_argument_count (args, count);
+       if (!count)
+ 	continue;
+ 
+       args->jump_functions = XCNEWVEC (struct ipa_jump_func,
+ 				       ipa_get_cs_argument_count (args));
+       for (k = 0; k < ipa_get_cs_argument_count (args); k++)
+ 	ipa_read_jump_function (ib, ipa_get_ith_jump_func (args, k), data_in);
+     }
+ }
+ 
+ /* Write jump functions for nodes in SET.  */
+ 
+ void
+ ipa_prop_write_jump_functions (cgraph_node_set set)
+ {
+   struct cgraph_node *node;
+   struct output_block *ob = create_output_block (LTO_section_jump_functions);
+   unsigned int count = 0;
+   cgraph_node_set_iterator csi;
+ 
+   ob->cgraph_node = NULL;
+ 
+   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+     {
+       node = csi_node (csi);
+       if (node->analyzed && IPA_NODE_REF (node) != NULL)
+ 	count++;
+     }
+ 
+   lto_output_uleb128_stream (ob->main_stream, count);
+ 
+   /* Process all of the functions.  */
+   for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
+     {
+       node = csi_node (csi);
+       if (node->analyzed && IPA_NODE_REF (node) != NULL)
+         ipa_write_node_info (ob, node);
+     }
+   lto_output_1_stream (ob->main_stream, 0);
+   produce_asm (ob, NULL);
+   destroy_output_block (ob);
+ }
+ 
+ /* Read section in file FILE_DATA of length LEN with data DATA.  */
+ 
+ static void
+ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data,
+ 		       size_t len)
+ {
+   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++)
+     {
+       unsigned int index;
+       struct cgraph_node *node;
+       lto_cgraph_encoder_t encoder;
+ 
+       index = lto_input_uleb128 (&ib_main);
+       encoder = file_data->cgraph_node_encoder;
+       node = lto_cgraph_encoder_deref (encoder, index);
+       ipa_read_node_info (&ib_main, node, data_in);
+     }
+   lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data,
+ 			 len);
+   lto_data_in_delete (data_in);
+ }
+ 
+ /* Read ipcp jump functions.  */
+ 
+ void
+ ipa_prop_read_jump_functions (void)
+ {
+   struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data ();
+   struct lto_file_decl_data *file_data;
+   unsigned int j = 0;
+ 
+   ipa_check_create_node_params ();
+   ipa_check_create_edge_args ();
+   ipa_register_cgraph_hooks ();
+ 
+   while ((file_data = file_data_vec[j++]))
+     {
+       size_t len;
+       const char *data = lto_get_section_data (file_data, LTO_section_jump_functions, NULL, &len);
+ 
+       if (data)
+         ipa_prop_read_section (file_data, data, len);
+     }
+ }
Index: ipa-prop.h
===================================================================
*** ipa-prop.h	(revision 152974)
--- ipa-prop.h	(working copy)
*************** ipa_parm_adjustment_vec ipa_combine_adju
*** 508,513 ****
--- 508,516 ----
  						 ipa_parm_adjustment_vec);
  void ipa_dump_param_adjustments (FILE *, ipa_parm_adjustment_vec, tree);
  
+ void ipa_prop_write_jump_functions (cgraph_node_set set);
+ void ipa_prop_read_jump_functions (void);
+ 
  /* From tree-sra.c:  */
  bool build_ref_for_offset (tree *, tree, HOST_WIDE_INT, tree, bool);
  
Index: passes.c
===================================================================
*** passes.c	(revision 152974)
--- passes.c	(working copy)
*************** ipa_write_summaries_1 (cgraph_node_set s
*** 1618,1624 ****
    struct lto_out_decl_state *state = lto_new_out_decl_state ();
    lto_push_out_decl_state (state);
  
!   ipa_write_summaries_2 (all_regular_ipa_passes, set, state);
    ipa_write_summaries_2 (all_lto_gen_passes, set, state);
  
    gcc_assert (lto_get_out_decl_state () == state);
--- 1618,1625 ----
    struct lto_out_decl_state *state = lto_new_out_decl_state ();
    lto_push_out_decl_state (state);
  
!   if (!flag_wpa)
!     ipa_write_summaries_2 (all_regular_ipa_passes, set, state);
    ipa_write_summaries_2 (all_lto_gen_passes, set, state);
  
    gcc_assert (lto_get_out_decl_state () == state);
*************** ipa_read_summaries_1 (struct opt_pass *p
*** 1712,1718 ****
  void
  ipa_read_summaries (void)
  {
!   ipa_read_summaries_1 (all_regular_ipa_passes);
    ipa_read_summaries_1 (all_lto_gen_passes);
  }
  
--- 1713,1720 ----
  void
  ipa_read_summaries (void)
  {
!   if (!flag_ltrans)
!     ipa_read_summaries_1 (all_regular_ipa_passes);
    ipa_read_summaries_1 (all_lto_gen_passes);
  }
  
Index: lto-streamer.c
===================================================================
*** lto-streamer.c	(revision 152974)
--- lto-streamer.c	(working copy)
*************** lto_get_section_name (int section_type, 
*** 157,162 ****
--- 157,165 ----
      case LTO_section_cgraph:
        return concat (LTO_SECTION_NAME_PREFIX, ".cgraph", NULL);
  
+     case LTO_section_jump_functions:
+       return concat (LTO_SECTION_NAME_PREFIX, ".jmpfuncs", NULL);
+ 
      case LTO_section_ipa_pure_const:
        return concat (LTO_SECTION_NAME_PREFIX, ".pureconst", NULL);
  
Index: lto-streamer.h
===================================================================
*** lto-streamer.h	(revision 152974)
--- lto-streamer.h	(working copy)
*************** enum lto_section_type
*** 256,261 ****
--- 256,262 ----
    LTO_section_function_body,
    LTO_section_static_initializer,
    LTO_section_cgraph,
+   LTO_section_jump_functions,
    LTO_section_ipa_pure_const,
    LTO_section_ipa_reference,
    LTO_section_symtab,
*************** extern struct output_block *create_outpu
*** 827,832 ****
--- 828,834 ----
  extern void destroy_output_block (struct output_block *);
  extern void lto_output_tree (struct output_block *, tree, bool);
  extern void lto_output_bitpack (struct lto_output_stream *, struct bitpack_d *);
+ extern void produce_asm (struct output_block *ob, tree fn);
  
  
  /* In lto-cgraph.c  */



More information about the Gcc-patches mailing list