LTO/WHOPR summary streaming fixes
Richard Guenther
rguenther@suse.de
Tue Oct 20 15:05:00 GMT 2009
On Tue, 20 Oct 2009, Jan Hubicka wrote:
> Hi,
> this patch fixes summary generation issues with LTO and WHOPR. The main changes are:
>
> 1) We used to re-compute all summaries at LTO read in. This is not correct, we should
> use what we wrote into disk.
> 2) We used to write summaries into ltrans files and re-execute all IPA passes. This is
> wrong since all decisions should've been mae at WPA
> 3) Jump functions are not streamed out.
> Note that I did not include patch to stream in/out indirect call notes. This is not
> needed for testsuite so I want to handle this independently.
> 4) ipa-reference was saving summaries only for overwrittable functions.
>
> Note that whopr is still somewhat broken. We now apply the inline plan
> changes, but other passes are not run and we now lose some optimization by
> not re-doing all IPA passes at ltrans stage. I have incremental patches for this,
> I am just trying to avoid snowballing effect.
>
> I've bootstrapped/regtested earlier vesion of this patch on x86_64-linux and I
> am re-testing current version. I think I can approve myself all changes except
> for the streaming part. OK?
It looks good to me. Let me build a piece of SPEC2006 with the patch,
I'll report on IRC before I leave today.
Thanks,
Richard.
> Honza
>
> * ipa-cp.c (ipcp_write_summary, ipcp_read_summary): New functions.
> (pass_ipa_cp): Register them.
> * 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.
> Index: ipa-cp.c
> ===================================================================
> *** ipa-cp.c (revision 152974)
> --- ipa-cp.c (working copy)
> *************** ipcp_generate_summary (void)
> *** 1276,1281 ****
> --- 1276,1295 ----
> ipcp_init_stage ();
> }
>
> + /* Write ipcp summary. */
> + 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 */
> --- 1322,1329 ----
> 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: 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. 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: 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,2102 ----
> VEC_free (tree, heap, parms);
> }
>
> + /* Stream out jump function JUMP_FUNC. */
> +
> + static void
> + ipa_write_jump_function (struct output_block *ob,
> + struct ipa_jump_func *jump_func)
> + {
> + struct bitpack_d *bp;
> +
> + bp = bitpack_create ();
> + bp_pack_value (bp, jump_func->type, 3);
> + lto_output_bitpack (ob->main_stream, bp);
> + bitpack_delete (bp);
> +
> + switch (jump_func->type)
> + {
> + case IPA_JF_UNKNOWN:
> + break;
> + case IPA_JF_CONST:
> + lto_output_tree (ob, jump_func->value.constant, false);
> + break;
> + case IPA_JF_PASS_THROUGH:
> + lto_output_tree (ob, jump_func->value.pass_through.operand, false);
> + 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, false);
> + 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, false);
> + lto_output_tree (ob, jump_func->value.member_cst.delta, false);
> + break;
> + }
> + }
> +
> + /* Read in jump function JUMP_FUNC. */
> +
> + static void
> + ipa_read_jump_function (struct lto_input_block *ib,
> + struct ipa_jump_func *jump_func)
> + {
> + struct bitpack_d *bp;
> +
> + bp = lto_input_bitpack (ib);
> + jump_func->type = (enum jump_func_type) bp_unpack_value (bp, 3);
> + bitpack_delete (bp);
> +
> + switch (jump_func->type)
> + {
> + case IPA_JF_UNKNOWN:
> + break;
> + case IPA_JF_CONST:
> + jump_func->value.constant = lto_input_tree (ib, false);
> + break;
> + case IPA_JF_PASS_THROUGH:
> + jump_func->value.pass_through.operand = lto_input_tree (ib, false);
> + 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, false);
> + 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, false);
> + jump_func->value.member_cst.delta = lto_input_tree (ib, false);
> + break;
> + }
> + bitpack_delete (bp);
> + }
> +
> + /* Stream out node info. */
> +
> + static void
> + ipa_write_node_info (struct output_block *ob, struct cgraph_node *node)
> + {
> + struct bitpack_d *bp;
> + int node_ref;
> + lto_cgraph_encoder_t encoder;
> + struct ipa_node_params *info = IPA_NODE_REF (node);
> + int j;
> + struct cgraph_edge *e;
> +
> + 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);
> + gcc_assert (info->uses_analysis_done);
> + 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);
> + 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. */
> +
> + static void
> + ipa_read_node_info (struct lto_input_block *ib, struct cgraph_node *node)
> + {
> + struct ipa_node_params *info = IPA_NODE_REF (node);
> + struct bitpack_d *bp;
> + int k;
> + struct cgraph_edge *e;
> +
> + 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);
> + 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);
> + for (k = 0; k < ipa_get_cs_argument_count (args); k++)
> + ipa_read_jump_function (ib, ipa_get_ith_jump_func (args, k));
> + }
> + }
> +
> + /* Write jump functions. */
> +
> + 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;
> +
> + 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);
> + }
> + destroy_output_block (ob);
> + }
> +
> + /* 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++]))
> + {
> + const char *data;
> + size_t len;
> + struct lto_input_block *ib
> + = lto_create_simple_input_block (file_data,
> + LTO_section_ipa_pure_const,
> + &data, &len);
> + if (ib)
> + {
> + unsigned int i;
> + unsigned int count = lto_input_uleb128 (ib);
> +
> + for (i = 0; i < count; i++)
> + {
> + unsigned int index;
> + struct cgraph_node *node;
> + lto_cgraph_encoder_t encoder;
> +
> + index = lto_input_uleb128 (ib);
> + encoder = file_data->cgraph_node_encoder;
> + node = lto_cgraph_encoder_deref (encoder, index);
> + ipa_read_node_info (ib, node);
> + }
> +
> + lto_destroy_simple_input_block (file_data,
> + LTO_section_ipa_pure_const,
> + ib, 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,
>
>
--
Richard Guenther <rguenther@suse.de>
Novell / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 - GF: Markus Rex
More information about the Gcc-patches
mailing list