mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-27 06:55:30 +08:00
ipa-cp.c (ipcp_write_summary, [...]): New functions.
* 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. (ipcp_iterate_stage): Call ipa_update_after_lto_read if needed. * 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_edge_args_vector): Update declaration. (ipa_count_arguments, ipa_compute_jump_functions, ipa_free_edge_args_substructures): Move ipa_edge_args_vector into ggc. (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. (duplicate_array): Use xmalloc. (duplicate_ggc_array): New. (ipa_edge_duplication_hook): Use it. (ipa_update_after_lto_read): New function. * ipa-prop.h (ipa_prop_write_jump_functions, ipa_prop_read_jump_functions): Declare. (ipa_pass_through_data, ipa_ancestor_jf_data, ipa_member_ptr_cst, jump_func_value, ipa_member_ptr_cst, ipa_edge_args): Add GTY markers. (ipa_edge_args_vector): Move into GGC. (ipa_check_create_edge_args): Update. (ipa_update_after_lto_read): New. * 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 (input_function): Free dominance info when done. (lto_read_body): Push ipa_inline in ltrans stage. * gengtype.c (open_base_files): Add ipa-prop.h into includes. * Makefile.in (GTFILES): Add ipa-prop.h * lto.c (lto_fixup_jump_functions): New function. (lto_fixup_decls): Use it. From-SVN: r153449
This commit is contained in:
parent
34677bae65
commit
fb3f88cc0d
@ -1,3 +1,50 @@
|
||||
2009-10-22 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* 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.
|
||||
(ipcp_iterate_stage): Call ipa_update_after_lto_read if needed.
|
||||
* 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_edge_args_vector): Update declaration.
|
||||
(ipa_count_arguments, ipa_compute_jump_functions,
|
||||
ipa_free_edge_args_substructures): Move ipa_edge_args_vector into ggc.
|
||||
(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.
|
||||
(duplicate_array): Use xmalloc.
|
||||
(duplicate_ggc_array): New.
|
||||
(ipa_edge_duplication_hook): Use it.
|
||||
(ipa_update_after_lto_read): New function.
|
||||
* ipa-prop.h (ipa_prop_write_jump_functions,
|
||||
ipa_prop_read_jump_functions): Declare.
|
||||
(ipa_pass_through_data, ipa_ancestor_jf_data, ipa_member_ptr_cst,
|
||||
jump_func_value, ipa_member_ptr_cst, ipa_edge_args): Add GTY markers.
|
||||
(ipa_edge_args_vector): Move into GGC.
|
||||
(ipa_check_create_edge_args): Update.
|
||||
(ipa_update_after_lto_read): New.
|
||||
* 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
|
||||
(input_function): Free dominance info when done.
|
||||
(lto_read_body): Push ipa_inline in ltrans stage.
|
||||
* gengtype.c (open_base_files): Add ipa-prop.h into includes.
|
||||
* Makefile.in (GTFILES): Add ipa-prop.h
|
||||
|
||||
2009-10-22 Matthias Klose <doko@ubuntu.com>
|
||||
|
||||
* doc/install.texi: Document --enable-browser-plugin.
|
||||
|
@ -3585,6 +3585,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
|
||||
$(srcdir)/tree-ssa-structalias.c \
|
||||
$(srcdir)/lto-symtab.c \
|
||||
$(srcdir)/tree-ssa-alias.h \
|
||||
$(srcdir)/ipa-prop.h \
|
||||
@all_gtfiles@
|
||||
|
||||
# Compute the list of GT header files from the corresponding C sources,
|
||||
|
@ -1375,15 +1375,16 @@ ipa_passes (void)
|
||||
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_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);
|
||||
if (!flag_ltrans)
|
||||
execute_ipa_pass_list (all_regular_ipa_passes);
|
||||
|
||||
bitmap_obstack_release (NULL);
|
||||
}
|
||||
|
@ -1571,7 +1571,7 @@ open_base_files (void)
|
||||
"optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
|
||||
"tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
|
||||
"cfglayout.h", "except.h", "output.h", "gimple.h", "cfgloop.h",
|
||||
"target.h", NULL
|
||||
"target.h", "ipa-prop.h", NULL
|
||||
};
|
||||
const char *const *ifp;
|
||||
outf_p gtype_desc_c;
|
||||
|
30
gcc/ipa-cp.c
30
gcc/ipa-cp.c
@ -614,7 +614,9 @@ ipcp_init_stage (void)
|
||||
/* building jump functions */
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
if (!cs->callee->analyzed)
|
||||
/* 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))
|
||||
@ -696,7 +698,9 @@ ipcp_propagate_stage (void)
|
||||
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))
|
||||
if (ipa_is_called_with_var_arguments (callee_info)
|
||||
|| !cs->callee->analyzed
|
||||
|| ipa_is_called_with_var_arguments (callee_info))
|
||||
continue;
|
||||
|
||||
count = ipa_get_cs_argument_count (args);
|
||||
@ -727,6 +731,10 @@ ipcp_iterate_stage (void)
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "\nIPA iterate stage:\n\n");
|
||||
|
||||
if (in_lto_p)
|
||||
ipa_update_after_lto_read ();
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
ipcp_initialize_node_lattices (node);
|
||||
@ -1276,6 +1284,20 @@ ipcp_generate_summary (void)
|
||||
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)
|
||||
@ -1308,8 +1330,8 @@ struct ipa_opt_pass_d pass_ipa_cp =
|
||||
TODO_remove_functions /* todo_flags_finish */
|
||||
},
|
||||
ipcp_generate_summary, /* generate_summary */
|
||||
NULL, /* write_summary */
|
||||
NULL, /* read_summary */
|
||||
ipcp_write_summary, /* write_summary */
|
||||
ipcp_read_summary, /* read_summary */
|
||||
NULL, /* function_read_summary */
|
||||
0, /* TODOs */
|
||||
NULL, /* function_transform */
|
||||
|
@ -1113,13 +1113,9 @@ cgraph_decide_inlining (void)
|
||||
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);
|
||||
cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
|
||||
if (in_lto_p && flag_indirect_inlining)
|
||||
ipa_update_after_lto_read ();
|
||||
|
||||
max_count = 0;
|
||||
max_benefit = 0;
|
||||
@ -1928,10 +1924,6 @@ inline_generate_summary (void)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -1976,6 +1968,34 @@ inline_transform (struct cgraph_node *node)
|
||||
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 =
|
||||
{
|
||||
{
|
||||
@ -1995,8 +2015,8 @@ struct ipa_opt_pass_d pass_ipa_inline =
|
||||
| TODO_remove_functions /* todo_flags_finish */
|
||||
},
|
||||
inline_generate_summary, /* generate_summary */
|
||||
NULL, /* write_summary */
|
||||
NULL, /* read_summary */
|
||||
inline_write_summary, /* write_summary */
|
||||
inline_read_summary, /* read_summary */
|
||||
NULL, /* function_read_summary */
|
||||
0, /* TODOs */
|
||||
inline_transform, /* function_transform */
|
||||
|
314
gcc/ipa-prop.c
314
gcc/ipa-prop.c
@ -33,11 +33,12 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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;
|
||||
/* Vector where the parameter infos are actually stored. */
|
||||
VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector;
|
||||
VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector;
|
||||
|
||||
/* Holders of ipa cgraph hooks: */
|
||||
static struct cgraph_edge_hook_list *edge_removal_hook_holder;
|
||||
@ -248,7 +249,7 @@ ipa_count_arguments (struct cgraph_edge *cs)
|
||||
arg_num = gimple_call_num_args (stmt);
|
||||
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,
|
||||
VEC_safe_grow_cleared (ipa_edge_args_t, gc,
|
||||
ipa_edge_args_vector, cgraph_edge_max_uid + 1);
|
||||
ipa_set_cs_argument_count (IPA_EDGE_REF (cs), arg_num);
|
||||
}
|
||||
@ -661,8 +662,8 @@ ipa_compute_jump_functions (struct cgraph_edge *cs)
|
||||
|
||||
if (ipa_get_cs_argument_count (arguments) == 0 || arguments->jump_functions)
|
||||
return;
|
||||
arguments->jump_functions = XCNEWVEC (struct ipa_jump_func,
|
||||
ipa_get_cs_argument_count (arguments));
|
||||
arguments->jump_functions = GGC_CNEWVEC (struct ipa_jump_func,
|
||||
ipa_get_cs_argument_count (arguments));
|
||||
|
||||
call = cs->call_stmt;
|
||||
gcc_assert (is_gimple_call (call));
|
||||
@ -1173,7 +1174,7 @@ void
|
||||
ipa_free_edge_args_substructures (struct ipa_edge_args *args)
|
||||
{
|
||||
if (args->jump_functions)
|
||||
free (args->jump_functions);
|
||||
ggc_free (args->jump_functions);
|
||||
|
||||
memset (args, 0, sizeof (*args));
|
||||
}
|
||||
@ -1191,7 +1192,7 @@ ipa_free_all_edge_args (void)
|
||||
i++)
|
||||
ipa_free_edge_args_substructures (args);
|
||||
|
||||
VEC_free (ipa_edge_args_t, heap, ipa_edge_args_vector);
|
||||
VEC_free (ipa_edge_args_t, gc, ipa_edge_args_vector);
|
||||
ipa_edge_args_vector = NULL;
|
||||
}
|
||||
|
||||
@ -1262,7 +1263,22 @@ duplicate_array (void *src, size_t n)
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
p = xcalloc (1, n);
|
||||
p = xmalloc (n);
|
||||
memcpy (p, src, n);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Like duplicate_array byt in GGC memory. */
|
||||
|
||||
static void *
|
||||
duplicate_ggc_array (void *src, size_t n)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (!src)
|
||||
return NULL;
|
||||
|
||||
p = ggc_alloc (n);
|
||||
memcpy (p, src, n);
|
||||
return p;
|
||||
}
|
||||
@ -1284,8 +1300,8 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst,
|
||||
arg_count = ipa_get_cs_argument_count (old_args);
|
||||
ipa_set_cs_argument_count (new_args, arg_count);
|
||||
new_args->jump_functions = (struct ipa_jump_func *)
|
||||
duplicate_array (old_args->jump_functions,
|
||||
sizeof (struct ipa_jump_func) * arg_count);
|
||||
duplicate_ggc_array (old_args->jump_functions,
|
||||
sizeof (struct ipa_jump_func) * arg_count);
|
||||
}
|
||||
|
||||
/* Hook that is called by cgraph.c when a node is duplicated. */
|
||||
@ -1875,3 +1891,283 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments,
|
||||
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, gc,
|
||||
ipa_edge_args_vector, cgraph_edge_max_uid + 1);
|
||||
ipa_set_cs_argument_count (args, count);
|
||||
if (!count)
|
||||
continue;
|
||||
|
||||
args->jump_functions = GGC_CNEWVEC (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);
|
||||
}
|
||||
}
|
||||
|
||||
/* After merging units, we can get mismatch in argument counts.
|
||||
Also decl merging might've rendered parameter lists obsolette.
|
||||
Also compute called_with_variable_arg info. */
|
||||
|
||||
void
|
||||
ipa_update_after_lto_read (void)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
if (!node->analyzed)
|
||||
continue;
|
||||
ipa_populate_param_decls (node, IPA_NODE_REF (node));
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
|
||||
!= ipa_get_param_count (IPA_NODE_REF (cs->callee)))
|
||||
ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ enum ipa_lattice_type
|
||||
|
||||
/* Structure holding data required to describe a pass-through jump function. */
|
||||
|
||||
struct ipa_pass_through_data
|
||||
struct GTY(()) ipa_pass_through_data
|
||||
{
|
||||
/* If an operation is to be performed on the original parameter, this is the
|
||||
second (constant) operand. */
|
||||
@ -89,7 +89,7 @@ struct ipa_pass_through_data
|
||||
/* Structure holding data required to describe and ancestor pass throu
|
||||
funkci. */
|
||||
|
||||
struct ipa_ancestor_jf_data
|
||||
struct GTY(()) ipa_ancestor_jf_data
|
||||
{
|
||||
/* Offset of the field representing the ancestor. */
|
||||
HOST_WIDE_INT offset;
|
||||
@ -101,30 +101,28 @@ struct ipa_ancestor_jf_data
|
||||
|
||||
/* Structure holding a C++ member pointer constant. Holds a pointer to the
|
||||
method and delta offset. */
|
||||
struct ipa_member_ptr_cst
|
||||
struct GTY(()) ipa_member_ptr_cst
|
||||
{
|
||||
tree pfn;
|
||||
tree delta;
|
||||
};
|
||||
|
||||
/* Represents a value of a jump function. pass_through is used only in jump
|
||||
function context. constant represents the actual constant in constant jump
|
||||
functions and member_cst holds constant c++ member functions. */
|
||||
union jump_func_value
|
||||
{
|
||||
tree constant;
|
||||
struct ipa_pass_through_data pass_through;
|
||||
struct ipa_ancestor_jf_data ancestor;
|
||||
struct ipa_member_ptr_cst member_cst;
|
||||
};
|
||||
|
||||
/* A jump function for a callsite represents the values passed as actual
|
||||
arguments of the callsite. See enum jump_func_type for the various
|
||||
types of jump functions supported. */
|
||||
struct ipa_jump_func
|
||||
struct GTY (()) ipa_jump_func
|
||||
{
|
||||
enum jump_func_type type;
|
||||
union jump_func_value value;
|
||||
/* Represents a value of a jump function. pass_through is used only in jump
|
||||
function context. constant represents the actual constant in constant jump
|
||||
functions and member_cst holds constant c++ member functions. */
|
||||
union jump_func_value
|
||||
{
|
||||
tree GTY ((tag ("IPA_JF_CONST"))) constant;
|
||||
struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) pass_through;
|
||||
struct ipa_ancestor_jf_data GTY ((tag ("IPA_JF_ANCESTOR"))) ancestor;
|
||||
struct ipa_member_ptr_cst GTY ((tag ("IPA_JF_CONST_MEMBER_PTR"))) member_cst;
|
||||
} GTY ((desc ("%1.type"))) value;
|
||||
};
|
||||
|
||||
/* All formal parameters in the program have a cval computed by
|
||||
@ -280,15 +278,15 @@ ipa_is_called_with_var_arguments (struct ipa_node_params *info)
|
||||
/* ipa_edge_args stores information related to a callsite and particularly
|
||||
its arguments. It is pointed to by a field in the
|
||||
callsite's corresponding cgraph_edge. */
|
||||
struct ipa_edge_args
|
||||
typedef struct GTY(()) ipa_edge_args
|
||||
{
|
||||
/* Number of actual arguments in this callsite. When set to 0,
|
||||
this callsite's parameters would not be analyzed by the different
|
||||
stages of IPA CP. */
|
||||
int argument_count;
|
||||
/* Array of the callsite's jump function of each parameter. */
|
||||
struct ipa_jump_func *jump_functions;
|
||||
};
|
||||
struct ipa_jump_func GTY ((length ("%h.argument_count"))) *jump_functions;
|
||||
} ipa_edge_args_t;
|
||||
|
||||
/* ipa_edge_args access functions. Please use these to access fields that
|
||||
are or will be shared among various passes. */
|
||||
@ -321,18 +319,17 @@ ipa_get_ith_jump_func (struct ipa_edge_args *args, int i)
|
||||
|
||||
/* Vectors need to have typedefs of structures. */
|
||||
typedef struct ipa_node_params ipa_node_params_t;
|
||||
typedef struct ipa_edge_args ipa_edge_args_t;
|
||||
|
||||
/* Types of vectors holding the infos. */
|
||||
DEF_VEC_O (ipa_node_params_t);
|
||||
DEF_VEC_ALLOC_O (ipa_node_params_t, heap);
|
||||
DEF_VEC_O (ipa_edge_args_t);
|
||||
DEF_VEC_ALLOC_O (ipa_edge_args_t, heap);
|
||||
DEF_VEC_ALLOC_O (ipa_edge_args_t, gc);
|
||||
|
||||
/* Vector where the parameter infos are actually stored. */
|
||||
extern VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
|
||||
/* Vector where the parameter infos are actually stored. */
|
||||
extern VEC (ipa_edge_args_t, heap) *ipa_edge_args_vector;
|
||||
extern GTY(()) VEC (ipa_edge_args_t, gc) *ipa_edge_args_vector;
|
||||
|
||||
/* Return the associated parameter/argument info corresponding to the given
|
||||
node/edge. */
|
||||
@ -378,12 +375,12 @@ static inline void
|
||||
ipa_check_create_edge_args (void)
|
||||
{
|
||||
if (!ipa_edge_args_vector)
|
||||
ipa_edge_args_vector = VEC_alloc (ipa_edge_args_t, heap,
|
||||
ipa_edge_args_vector = VEC_alloc (ipa_edge_args_t, gc,
|
||||
cgraph_edge_max_uid);
|
||||
|
||||
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,
|
||||
VEC_safe_grow_cleared (ipa_edge_args_t, gc, ipa_edge_args_vector,
|
||||
cgraph_edge_max_uid + 1);
|
||||
}
|
||||
|
||||
@ -508,6 +505,10 @@ ipa_parm_adjustment_vec ipa_combine_adjustments (ipa_parm_adjustment_vec,
|
||||
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);
|
||||
void ipa_update_after_lto_read (void);
|
||||
|
||||
/* From tree-sra.c: */
|
||||
bool build_ref_for_offset (tree *, tree, HOST_WIDE_INT, tree, bool);
|
||||
|
||||
|
@ -1014,7 +1014,7 @@ write_node_summary_p (struct cgraph_node *node)
|
||||
{
|
||||
return (node->analyzed
|
||||
&& node->global.inlined_to == NULL
|
||||
&& cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE
|
||||
&& cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE
|
||||
&& get_reference_vars_info (node) != NULL);
|
||||
}
|
||||
|
||||
|
@ -372,8 +372,16 @@ output_cgraph (cgraph_node_set set)
|
||||
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);
|
||||
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);
|
||||
|
@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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
|
||||
@ -1341,6 +1342,8 @@ input_function (tree fn_decl, struct data_in *data_in,
|
||||
fixup_call_stmt_edges (cgraph_node (fn_decl), stmts);
|
||||
|
||||
update_ssa (TODO_update_ssa_only_virtuals);
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
free_dominance_info (CDI_POST_DOMINATORS);
|
||||
free (stmts);
|
||||
}
|
||||
|
||||
@ -1455,6 +1458,15 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
|
||||
/* 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 && !cgraph_node (fn_decl)->global.inlined_to)
|
||||
VEC_safe_push (ipa_opt_pass, heap,
|
||||
cfun->ipa_transforms_to_apply,
|
||||
(ipa_opt_pass)&pass_ipa_inline);
|
||||
pop_cfun ();
|
||||
}
|
||||
else
|
||||
|
@ -1762,7 +1762,7 @@ output_bb (struct output_block *ob, basic_block bb, struct function *fn)
|
||||
/* 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
|
||||
void
|
||||
produce_asm (struct output_block *ob, tree fn)
|
||||
{
|
||||
enum lto_section_type section_type = ob->section_type;
|
||||
|
@ -157,6 +157,9 @@ lto_get_section_name (int section_type, const char *name)
|
||||
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);
|
||||
|
||||
|
@ -256,6 +256,7 @@ enum lto_section_type
|
||||
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,
|
||||
@ -827,6 +828,7 @@ extern struct output_block *create_output_block (enum lto_section_type);
|
||||
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 */
|
||||
|
@ -1,3 +1,8 @@
|
||||
2009-10-22 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto.c (lto_fixup_jump_functions): New function.
|
||||
(lto_fixup_decls): Use it.
|
||||
|
||||
2009-10-16 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR lto/41715
|
||||
|
@ -1652,6 +1652,53 @@ free_decl (const void *p, void *data ATTRIBUTE_UNUSED)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fixup pointers in jump functions.
|
||||
TODO: We need some generic solution that will allow tree pointers in
|
||||
function summaries. */
|
||||
static void
|
||||
lto_fixup_jump_functions (lto_fixup_data_t * data)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
struct cgraph_edge *cs;
|
||||
|
||||
for (node = cgraph_nodes; node; node = node->next)
|
||||
{
|
||||
if (!node->analyzed)
|
||||
continue;
|
||||
for (cs = node->callees; cs; cs = cs->next_callee)
|
||||
{
|
||||
int i;
|
||||
struct ipa_edge_args *args = IPA_EDGE_REF (cs);
|
||||
for (i = 0; i < ipa_get_cs_argument_count (args); i++)
|
||||
{
|
||||
struct ipa_jump_func *jf = ipa_get_ith_jump_func (args, i);
|
||||
switch (jf->type)
|
||||
{
|
||||
case IPA_JF_UNKNOWN:
|
||||
break;
|
||||
case IPA_JF_CONST:
|
||||
walk_tree (&jf->value.constant, lto_fixup_tree, data, NULL);
|
||||
break;
|
||||
case IPA_JF_PASS_THROUGH:
|
||||
walk_tree (&jf->value.pass_through.operand, lto_fixup_tree,
|
||||
data, NULL);
|
||||
break;
|
||||
case IPA_JF_ANCESTOR:
|
||||
walk_tree (&jf->value.ancestor.type, lto_fixup_tree, data,
|
||||
NULL);
|
||||
break;
|
||||
case IPA_JF_CONST_MEMBER_PTR:
|
||||
walk_tree (&jf->value.member_cst.pfn, lto_fixup_tree, data,
|
||||
NULL);
|
||||
walk_tree (&jf->value.member_cst.delta, lto_fixup_tree,
|
||||
data, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the decls from all FILES. Replaces each decl with the corresponding
|
||||
prevailing one. */
|
||||
|
||||
@ -1682,6 +1729,8 @@ lto_fixup_decls (struct lto_file_decl_data **files)
|
||||
if (decl != saved_decl)
|
||||
VEC_replace (tree, lto_global_var_decls, i, decl);
|
||||
}
|
||||
if (ipa_edge_args_vector)
|
||||
lto_fixup_jump_functions (&data);
|
||||
|
||||
pointer_set_traverse (free_list, free_decl, NULL);
|
||||
pointer_set_destroy (free_list);
|
||||
|
@ -1618,7 +1618,8 @@ ipa_write_summaries_1 (cgraph_node_set set)
|
||||
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);
|
||||
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);
|
||||
@ -1712,7 +1713,8 @@ ipa_read_summaries_1 (struct opt_pass *pass)
|
||||
void
|
||||
ipa_read_summaries (void)
|
||||
{
|
||||
ipa_read_summaries_1 (all_regular_ipa_passes);
|
||||
if (!flag_ltrans)
|
||||
ipa_read_summaries_1 (all_regular_ipa_passes);
|
||||
ipa_read_summaries_1 (all_lto_gen_passes);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user