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]

[PATCH] LTO Streaming of parameter call notes


Hi,

the following patch enables indirect inlining with LTO.  It streams
parameter call notes in an out and then proceeds as usual.  It must be
applied on top of (yet not approved) patch at
http://gcc.gnu.org/ml/gcc-patches/2009-11/msg00501.html.

It also allows indirect inlining even in wpa mode because the problem
we were facing should be fixed by the patch linked above too.
Finally, the patch removes some unnecessary vector length test and
growth.

Bootstrapped and tested on x86_64-linux. OK for trunk?

Thanks,

Martin


2009-11-11  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (struct ipa_param_call_note): New field lto_stmt_uid.
	(lto_ipa_fixup_call_notes): Declare.
	* ipa-prop.c (ipa_note_param_call): Store gimple uid.
	(update_call_notes_after_inlining): Copy call stmt uid to the new
	edge.
	(ipa_write_param_call_note): New function.
	(ipa_read_param_call_note): New function
	(ipa_write_node_info): Write also param call notes.  Removed a bogus
	comment, reformatted to fit 80 columns.
	(ipa_read_node_info): Read also param call notes. Removed a bogus
	comment.  Remove ipa_edge_args_vector growth.
	(lto_ipa_fixup_call_notes): New function.
	* ipa-cp.c (pass_ipa_cp): Add stmt_fixup hook.
	* ipa-inline.c (cgraph_mark_inline_edge): Perform indirect
	inlining regardless of flag_wpa.
	(cgraph_decide_inlining_of_small_functions): Likewise.
	(cgraph_decide_inlining): Likewise.
	(inline_read_summary): Likewise.


Index: icln/gcc/ipa-prop.h
===================================================================
--- icln.orig/gcc/ipa-prop.h
+++ icln/gcc/ipa-prop.h
@@ -143,6 +143,8 @@ struct ipa_param_call_note
   struct ipa_param_call_note *next;
   /* Statement that contains the call to the parameter above.  */
   gimple stmt;
+  /* When in LTO, we the above stmt will be NULL and we need an uid. */
+  unsigned int lto_stmt_uid;
   /* Index of the parameter that is called.  */
   int formal_id;
   /* Expected number of executions: calculated in profile.c.  */
@@ -508,6 +510,7 @@ void ipa_dump_param_adjustments (FILE *,
 void ipa_prop_write_jump_functions (cgraph_node_set set);
 void ipa_prop_read_jump_functions (void);
 void ipa_update_after_lto_read (void);
+void lto_ipa_fixup_call_notes (struct cgraph_node *, gimple *);
 
 /* From tree-sra.c:  */
 bool build_ref_for_offset (tree *, tree, HOST_WIDE_INT, tree, bool);
Index: icln/gcc/ipa-prop.c
===================================================================
--- icln.orig/gcc/ipa-prop.c
+++ icln/gcc/ipa-prop.c
@@ -751,6 +751,7 @@ ipa_note_param_call (struct ipa_node_par
   note = XCNEW (struct ipa_param_call_note);
   note->formal_id = formal_id;
   note->stmt = stmt;
+  note->lto_stmt_uid = gimple_uid (stmt);
   note->count = bb->count;
   note->frequency = compute_call_stmt_bb_frequency (current_function_decl, bb);
 
@@ -1100,6 +1101,7 @@ update_call_notes_after_inlining (struct
 	  new_indirect_edge = cgraph_create_edge (node, callee, nt->stmt,
 						  nt->count, nt->frequency,
 						  nt->loop_nest);
+	  new_indirect_edge->lto_stmt_uid = nt->lto_stmt_uid;
 	  new_indirect_edge->indirect_call = 1;
 	  ipa_check_create_edge_args ();
 	  if (new_edges)
@@ -1961,6 +1963,46 @@ ipa_read_jump_function (struct lto_input
     }
 }
 
+/* Stream out a parameter call note.  */
+
+static void
+ipa_write_param_call_note (struct output_block *ob,
+			   struct ipa_param_call_note *note)
+{
+  struct bitpack_d *bp = bitpack_create ();
+
+  gcc_assert (!note->processed);
+  bp_pack_value (bp, note->lto_stmt_uid, HOST_BITS_PER_INT);
+  bp_pack_value (bp, note->formal_id, HOST_BITS_PER_INT);
+  bp_pack_value (bp, note->frequency, HOST_BITS_PER_INT);
+  bp_pack_value (bp, note->loop_nest, HOST_BITS_PER_INT);
+  lto_output_bitpack (ob->main_stream, bp);
+  bitpack_delete (bp);
+  lto_output_sleb128_stream (ob->main_stream, note->count);
+}
+
+/* Read in a parameter call note.  */
+
+static void
+ipa_read_param_call_note (struct lto_input_block *ib,
+			  struct ipa_node_params *info)
+
+{
+  struct ipa_param_call_note *note = XCNEW (struct ipa_param_call_note);
+  struct bitpack_d *bp = lto_input_bitpack (ib);
+
+  note->lto_stmt_uid = (unsigned int) bp_unpack_value (bp, HOST_BITS_PER_INT);
+  note->formal_id = (int) bp_unpack_value (bp, HOST_BITS_PER_INT);
+  note->frequency = (int) bp_unpack_value (bp, HOST_BITS_PER_INT);
+  note->loop_nest = (int) bp_unpack_value (bp, HOST_BITS_PER_INT);
+  bitpack_delete (bp);
+  note->count = (gcov_type) lto_input_sleb128 (ib);
+
+  note->next = info->param_calls;
+  info->param_calls = note;
+}
+
+
 /* Stream out NODE info to OB.  */
 
 static void
@@ -1972,16 +2014,17 @@ ipa_write_node_info (struct output_block
   int j;
   struct cgraph_edge *e;
   struct bitpack_d *bp;
+  int note_count;
+  struct ipa_param_call_note *note;
 
   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->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);
@@ -1996,10 +2039,17 @@ ipa_write_node_info (struct output_block
     {
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
 
-      lto_output_uleb128_stream (ob->main_stream, ipa_get_cs_argument_count (args));
+      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));
     }
+
+  for (note = info->param_calls; note; note = note->next)
+    note_count++;
+  lto_output_uleb128_stream (ob->main_stream, note_count);
+  for (note = info->param_calls; note; note = note->next)
+    ipa_write_param_call_note (ob, note);
 }
 
 /* Srtream in NODE info from IB.  */
@@ -2012,12 +2062,10 @@ ipa_read_node_info (struct lto_input_blo
   int k;
   struct cgraph_edge *e;
   struct bitpack_d *bp;
+  int i, note_count;
 
   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)
@@ -2037,10 +2085,6 @@ ipa_read_node_info (struct lto_input_blo
       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, gc,
-			       ipa_edge_args_vector, cgraph_edge_max_uid + 1);
       ipa_set_cs_argument_count (args, count);
       if (!count)
 	continue;
@@ -2050,6 +2094,10 @@ ipa_read_node_info (struct lto_input_blo
       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);
     }
+
+  note_count = lto_input_uleb128 (ib);
+  for (i = 0; i < note_count; i++)
+    ipa_read_param_call_note (ib, info);
 }
 
 /* Write jump functions for nodes in SET.  */
@@ -2174,3 +2222,29 @@ ipa_update_after_lto_read (void)
 	}
     }
 }
+
+/* Walk param call notes of NODE and set their call statements given the uid
+   stored in each note and STMTS which is an array of statements indexed by the
+   uid.  */
+
+void
+lto_ipa_fixup_call_notes (struct cgraph_node *node, gimple *stmts)
+{
+  struct ipa_node_params *info;
+  struct ipa_param_call_note *note;
+
+  ipa_check_create_node_params ();
+  info = IPA_NODE_REF (node);
+  note = info->param_calls;
+  /* If there are no notes or they have already been fixed up (the same fixup
+     is called for both inlining and ipa-cp), there's nothing to do. */
+  if (!note || note->stmt)
+    return;
+
+  do
+    {
+      note->stmt = stmts[note->lto_stmt_uid];
+      note = note->next;
+    }
+  while (note);
+}
Index: icln/gcc/ipa-cp.c
===================================================================
--- icln.orig/gcc/ipa-cp.c
+++ icln/gcc/ipa-cp.c
@@ -1327,7 +1327,7 @@ struct ipa_opt_pass_d pass_ipa_cp =
  ipcp_write_summary,			/* write_summary */
  ipcp_read_summary,			/* read_summary */
  NULL,					/* function_read_summary */
- NULL,					/* stmt_fixup */
+ lto_ipa_fixup_call_notes, 		/* stmt_fixup */
  0,					/* TODOs */
  NULL,					/* function_transform */
  NULL,					/* variable_transform */
Index: icln/gcc/ipa-inline.c
===================================================================
--- icln.orig/gcc/ipa-inline.c
+++ icln/gcc/ipa-inline.c
@@ -310,7 +310,7 @@ cgraph_mark_inline_edge (struct cgraph_e
     overall_size -= orig_size;
   ncalls_inlined++;
 
-  if (flag_indirect_inlining && !flag_wpa)
+  if (flag_indirect_inlining)
     return ipa_propagate_indirect_call_infos (curr, new_edges);
   else
     return false;
@@ -876,7 +876,7 @@ cgraph_decide_inlining_of_small_function
   int min_size, max_size;
   VEC (cgraph_edge_p, heap) *new_indirect_edges = NULL;
 
-  if (flag_indirect_inlining && !flag_wpa)
+  if (flag_indirect_inlining)
     new_indirect_edges = VEC_alloc (cgraph_edge_p, heap, 8);
 
   if (dump_file)
@@ -1023,10 +1023,10 @@ cgraph_decide_inlining_of_small_function
 	  if (where->global.inlined_to)
 	    where = where->global.inlined_to;
 	  if (!cgraph_decide_recursive_inlining (where,
-						 flag_indirect_inlining && !flag_wpa
+						 flag_indirect_inlining
 						 ? &new_indirect_edges : NULL))
 	    continue;
-	  if (flag_indirect_inlining && !flag_wpa)
+	  if (flag_indirect_inlining)
 	    add_new_edges_to_heap (heap, new_indirect_edges);
           update_callee_keys (heap, where, updated_nodes);
 	}
@@ -1045,7 +1045,7 @@ cgraph_decide_inlining_of_small_function
 	    }
 	  callee = edge->callee;
 	  cgraph_mark_inline_edge (edge, true, &new_indirect_edges);
-	  if (flag_indirect_inlining && !flag_wpa)
+	  if (flag_indirect_inlining)
 	    add_new_edges_to_heap (heap, new_indirect_edges);
 
 	  update_callee_keys (heap, callee, updated_nodes);
@@ -1114,7 +1114,7 @@ cgraph_decide_inlining (void)
   int initial_size = 0;
 
   cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
-  if (in_lto_p && flag_indirect_inlining && !flag_wpa)
+  if (in_lto_p && flag_indirect_inlining)
     ipa_update_after_lto_read ();
 
   max_count = 0;
@@ -1270,7 +1270,7 @@ cgraph_decide_inlining (void)
     }
 
   /* Free ipa-prop structures if they are no longer needed.  */
-  if (flag_indirect_inlining && !flag_wpa)
+  if (flag_indirect_inlining)
     free_all_ipa_structures_after_iinln ();
 
   if (dump_file)
@@ -1977,7 +1977,7 @@ inline_transform (struct cgraph_node *no
 static void 
 inline_read_summary (void)
 {
-  if (flag_indirect_inlining && !flag_wpa)
+  if (flag_indirect_inlining)
     {
       ipa_register_cgraph_hooks ();
       if (!flag_ipa_cp)
@@ -2020,7 +2020,7 @@ struct ipa_opt_pass_d pass_ipa_inline =
  inline_write_summary,			/* write_summary */
  inline_read_summary,			/* read_summary */
  NULL,					/* function_read_summary */
- NULL,					/* stmt_fixup */
+ lto_ipa_fixup_call_notes,		/* stmt_fixup */
  0,					/* TODOs */
  inline_transform,			/* function_transform */
  NULL,					/* variable_transform */


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