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:
Jan Hubicka 2009-10-22 12:02:29 +02:00 committed by Jan Hubicka
parent 34677bae65
commit fb3f88cc0d
17 changed files with 529 additions and 60 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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);
}

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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));
}
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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);
}