lto-cgraph.c (compute_ltrans_boundary): Add abstract origins into boundaries.
* lto-cgraph.c (compute_ltrans_boundary): Add abstract origins into boundaries. * lto-streamer-out.c (tree_is_indexable): Results decls and parm decls are not indexable. (DFS_write_tree_body): Do not follow args and results. (hash_tree): Likewise. (output_functions): Rearrange so struct function is needed only when real body is output; be able to also ouptut abstract functions; output DECL_ARGUMENTS and DECL_RESULT. (lto_output): When not in WPA, ale store abstract functions. (write_symbol): Do not care about RESULT_DECL. (output_symbol_p): Handle correctly sbtract decls. * lto-streamer-in.c (input_function): Rearrange so struct function can be NULL at entry; allow streaming of functions w/o body; store DECL_ARGUMENTS and DECL_RESULT. * ipa.c (symtab_remove_unreachable_nodes): Silence confused sanity check during LTO. * tree-streamer-out.c (write_ts_decl_non_common_tree_pointers): Skip RESULT_DECl and DECL_ARGUMENTS. * tree-streamer-in.c (lto_input_ts_decl_non_common_tree_pointers): Likewise. * lto.c (lto_materialize_function): Do not push struct function. * lto-partition.c (get_symbol_class): Handle abstracts correctly. (may_need_named_section_p): Even abstract origins may need named section. From-SVN: r201468
This commit is contained in:
parent
07838b1363
commit
815effe155
@ -1,3 +1,27 @@
|
||||
2013-08-02 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto-cgraph.c (compute_ltrans_boundary): Add abstract origins into
|
||||
boundaries.
|
||||
* lto-streamer-out.c (tree_is_indexable): Results decls and
|
||||
parm decls are not indexable.
|
||||
(DFS_write_tree_body): Do not follow args and results.
|
||||
(hash_tree): Likewise.
|
||||
(output_functions): Rearrange so struct function is needed
|
||||
only when real body is output; be able to also ouptut abstract
|
||||
functions; output DECL_ARGUMENTS and DECL_RESULT.
|
||||
(lto_output): When not in WPA, ale store abstract functions.
|
||||
(write_symbol): Do not care about RESULT_DECL.
|
||||
(output_symbol_p): Handle correctly sbtract decls.
|
||||
* lto-streamer-in.c (input_function): Rearrange so struct
|
||||
function can be NULL at entry; allow streaming of
|
||||
functions w/o body; store DECL_ARGUMENTS and DECL_RESULT.
|
||||
* ipa.c (symtab_remove_unreachable_nodes): Silence confused
|
||||
sanity check during LTO.
|
||||
* tree-streamer-out.c (write_ts_decl_non_common_tree_pointers): Skip
|
||||
RESULT_DECl and DECL_ARGUMENTS.
|
||||
* tree-streamer-in.c (lto_input_ts_decl_non_common_tree_pointers):
|
||||
Likewise.
|
||||
|
||||
2013-08-03 Gabriel Dos Reis <gdr@integrable-solutions.net>
|
||||
|
||||
* pretty-print.h (pp_underscore): New.
|
||||
|
@ -371,7 +371,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
|
||||
if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl))
|
||||
cgraph_release_function_body (node);
|
||||
else if (!node->clone_of)
|
||||
gcc_assert (DECL_RESULT (node->symbol.decl));
|
||||
gcc_assert (in_lto_p || DECL_RESULT (node->symbol.decl));
|
||||
if (node->symbol.definition)
|
||||
{
|
||||
if (file)
|
||||
@ -382,7 +382,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
|
||||
}
|
||||
else
|
||||
gcc_assert (node->clone_of || !cgraph_function_with_gimple_body_p (node)
|
||||
|| DECL_RESULT (node->symbol.decl));
|
||||
|| in_lto_p || DECL_RESULT (node->symbol.decl));
|
||||
}
|
||||
|
||||
/* Inline clones might be kept around so their materializing allows further
|
||||
|
@ -749,6 +749,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
|
||||
add_node_to (encoder, node, true);
|
||||
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node);
|
||||
add_references (encoder, &node->symbol.ref_list);
|
||||
/* For proper debug info, we need to ship the origins, too. */
|
||||
if (DECL_ABSTRACT_ORIGIN (node->symbol.decl))
|
||||
{
|
||||
struct cgraph_node *origin_node
|
||||
= cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
|
||||
add_node_to (encoder, origin_node, true);
|
||||
}
|
||||
}
|
||||
for (lsei = lsei_start_variable_in_partition (in_encoder);
|
||||
!lsei_end_p (lsei); lsei_next_variable_in_partition (&lsei))
|
||||
@ -758,6 +765,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder)
|
||||
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode);
|
||||
lto_set_symtab_encoder_encode_initializer (encoder, vnode);
|
||||
add_references (encoder, &vnode->symbol.ref_list);
|
||||
/* For proper debug info, we need to ship the origins, too. */
|
||||
if (DECL_ABSTRACT_ORIGIN (vnode->symbol.decl))
|
||||
{
|
||||
struct varpool_node *origin_node
|
||||
= varpool_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
|
||||
lto_set_symtab_encoder_in_partition (encoder, (symtab_node)origin_node);
|
||||
}
|
||||
}
|
||||
/* Pickle in also the initializer of all referenced readonly variables
|
||||
to help folding. Constant pool variables are not shared, so we must
|
||||
|
@ -851,7 +851,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
|
||||
|
||||
static void
|
||||
input_function (tree fn_decl, struct data_in *data_in,
|
||||
struct lto_input_block *ib)
|
||||
struct lto_input_block *ib, struct lto_input_block *ib_cfg)
|
||||
{
|
||||
struct function *fn;
|
||||
enum LTO_tags tag;
|
||||
@ -859,13 +859,30 @@ input_function (tree fn_decl, struct data_in *data_in,
|
||||
basic_block bb;
|
||||
struct cgraph_node *node;
|
||||
|
||||
fn = DECL_STRUCT_FUNCTION (fn_decl);
|
||||
tag = streamer_read_record_start (ib);
|
||||
|
||||
gimple_register_cfg_hooks ();
|
||||
lto_tag_check (tag, LTO_function);
|
||||
|
||||
/* Read decls for parameters and args. */
|
||||
DECL_RESULT (fn_decl) = stream_read_tree (ib, data_in);
|
||||
DECL_ARGUMENTS (fn_decl) = streamer_read_chain (ib, data_in);
|
||||
|
||||
/* Read the tree of lexical scopes for the function. */
|
||||
DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
|
||||
|
||||
if (!streamer_read_uhwi (ib))
|
||||
return;
|
||||
|
||||
push_struct_function (fn_decl);
|
||||
fn = DECL_STRUCT_FUNCTION (fn_decl);
|
||||
init_tree_ssa (fn);
|
||||
/* We input IL in SSA form. */
|
||||
cfun->gimple_df->in_ssa_p = true;
|
||||
|
||||
gimple_register_cfg_hooks ();
|
||||
|
||||
node = cgraph_get_create_node (fn_decl);
|
||||
input_struct_function_base (fn, data_in, ib);
|
||||
input_cfg (ib_cfg, fn, node->count_materialization_scale);
|
||||
|
||||
/* Read all the SSA names. */
|
||||
input_ssa_names (ib, data_in, fn);
|
||||
@ -873,11 +890,8 @@ input_function (tree fn_decl, struct data_in *data_in,
|
||||
/* Read the exception handling regions in the function. */
|
||||
input_eh_regions (ib, data_in, fn);
|
||||
|
||||
/* Read the tree of lexical scopes for the function. */
|
||||
DECL_INITIAL (fn_decl) = stream_read_tree (ib, data_in);
|
||||
gcc_assert (DECL_INITIAL (fn_decl));
|
||||
DECL_SAVED_TREE (fn_decl) = NULL_TREE;
|
||||
node = cgraph_get_create_node (fn_decl);
|
||||
|
||||
/* Read all the basic blocks. */
|
||||
tag = streamer_read_record_start (ib);
|
||||
@ -987,28 +1001,21 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
|
||||
|
||||
if (section_type == LTO_section_function_body)
|
||||
{
|
||||
struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
|
||||
struct lto_in_decl_state *decl_state;
|
||||
struct cgraph_node *node = cgraph_get_node (fn_decl);
|
||||
unsigned from;
|
||||
|
||||
gcc_checking_assert (node);
|
||||
push_cfun (fn);
|
||||
init_tree_ssa (fn);
|
||||
|
||||
/* We input IL in SSA form. */
|
||||
cfun->gimple_df->in_ssa_p = true;
|
||||
|
||||
/* Use the function's decl state. */
|
||||
decl_state = lto_get_function_in_decl_state (file_data, fn_decl);
|
||||
gcc_assert (decl_state);
|
||||
file_data->current_decl_state = decl_state;
|
||||
|
||||
input_cfg (&ib_cfg, fn, node->count_materialization_scale);
|
||||
|
||||
/* Set up the struct function. */
|
||||
from = data_in->reader_cache->nodes.length ();
|
||||
input_function (fn_decl, data_in, &ib_main);
|
||||
input_function (fn_decl, data_in, &ib_main, &ib_cfg);
|
||||
/* And fixup types we streamed locally. */
|
||||
{
|
||||
struct streamer_tree_cache_d *cache = data_in->reader_cache;
|
||||
|
@ -124,8 +124,8 @@ output_type_ref (struct output_block *ob, tree node)
|
||||
static bool
|
||||
tree_is_indexable (tree t)
|
||||
{
|
||||
if (TREE_CODE (t) == PARM_DECL)
|
||||
return true;
|
||||
if (TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
|
||||
return false;
|
||||
else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t)
|
||||
&& !TREE_STATIC (t))
|
||||
return false;
|
||||
@ -506,13 +506,7 @@ DFS_write_tree_body (struct output_block *ob,
|
||||
|
||||
if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
|
||||
{
|
||||
if (TREE_CODE (expr) == FUNCTION_DECL)
|
||||
{
|
||||
for (tree t = DECL_ARGUMENTS (expr); t; t = TREE_CHAIN (t))
|
||||
DFS_follow_tree_edge (t);
|
||||
DFS_follow_tree_edge (DECL_RESULT (expr));
|
||||
}
|
||||
else if (TREE_CODE (expr) == TYPE_DECL)
|
||||
if (TREE_CODE (expr) == TYPE_DECL)
|
||||
DFS_follow_tree_edge (DECL_ORIGINAL_TYPE (expr));
|
||||
DFS_follow_tree_edge (DECL_VINDEX (expr));
|
||||
}
|
||||
@ -936,13 +930,7 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t)
|
||||
|
||||
if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
|
||||
{
|
||||
if (code == FUNCTION_DECL)
|
||||
{
|
||||
for (tree a = DECL_ARGUMENTS (t); a; a = DECL_CHAIN (a))
|
||||
visit (a);
|
||||
visit (DECL_RESULT (t));
|
||||
}
|
||||
else if (code == TYPE_DECL)
|
||||
if (code == TYPE_DECL)
|
||||
visit (DECL_ORIGINAL_TYPE (t));
|
||||
visit (DECL_VINDEX (t));
|
||||
}
|
||||
@ -1772,50 +1760,63 @@ output_function (struct cgraph_node *node)
|
||||
|
||||
streamer_write_record_start (ob, LTO_function);
|
||||
|
||||
output_struct_function_base (ob, fn);
|
||||
|
||||
/* Output all the SSA names used in the function. */
|
||||
output_ssa_names (ob, fn);
|
||||
|
||||
/* Output any exception handling regions. */
|
||||
output_eh_regions (ob, fn);
|
||||
/* Output decls for parameters and args. */
|
||||
stream_write_tree (ob, DECL_RESULT (function), true);
|
||||
streamer_write_chain (ob, DECL_ARGUMENTS (function), true);
|
||||
|
||||
/* Output DECL_INITIAL for the function, which contains the tree of
|
||||
lexical scopes. */
|
||||
stream_write_tree (ob, DECL_INITIAL (function), true);
|
||||
|
||||
/* We will renumber the statements. The code that does this uses
|
||||
the same ordering that we use for serializing them so we can use
|
||||
the same code on the other end and not have to write out the
|
||||
statement numbers. We do not assign UIDs to PHIs here because
|
||||
virtual PHIs get re-computed on-the-fly which would make numbers
|
||||
inconsistent. */
|
||||
set_gimple_stmt_max_uid (cfun, 0);
|
||||
FOR_ALL_BB (bb)
|
||||
/* We also stream abstract functions where we stream only stuff needed for
|
||||
debug info. */
|
||||
if (gimple_has_body_p (function))
|
||||
{
|
||||
gimple_stmt_iterator gsi;
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
streamer_write_uhwi (ob, 1);
|
||||
output_struct_function_base (ob, fn);
|
||||
|
||||
/* Output all the SSA names used in the function. */
|
||||
output_ssa_names (ob, fn);
|
||||
|
||||
/* Output any exception handling regions. */
|
||||
output_eh_regions (ob, fn);
|
||||
|
||||
|
||||
/* We will renumber the statements. The code that does this uses
|
||||
the same ordering that we use for serializing them so we can use
|
||||
the same code on the other end and not have to write out the
|
||||
statement numbers. We do not assign UIDs to PHIs here because
|
||||
virtual PHIs get re-computed on-the-fly which would make numbers
|
||||
inconsistent. */
|
||||
set_gimple_stmt_max_uid (cfun, 0);
|
||||
FOR_ALL_BB (bb)
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
|
||||
gimple_stmt_iterator gsi;
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple stmt = gsi_stmt (gsi);
|
||||
gimple_set_uid (stmt, inc_gimple_stmt_max_uid (cfun));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Output the code for the function. */
|
||||
FOR_ALL_BB_FN (bb, fn)
|
||||
output_bb (ob, bb, fn);
|
||||
/* Output the code for the function. */
|
||||
FOR_ALL_BB_FN (bb, fn)
|
||||
output_bb (ob, bb, fn);
|
||||
|
||||
/* The terminator for this function. */
|
||||
streamer_write_record_start (ob, LTO_null);
|
||||
/* The terminator for this function. */
|
||||
streamer_write_record_start (ob, LTO_null);
|
||||
|
||||
output_cfg (ob, fn);
|
||||
output_cfg (ob, fn);
|
||||
|
||||
pop_cfun ();
|
||||
}
|
||||
else
|
||||
streamer_write_uhwi (ob, 0);
|
||||
|
||||
/* Create a section to hold the pickled output of this function. */
|
||||
produce_asm (ob, function);
|
||||
|
||||
destroy_output_block (ob);
|
||||
|
||||
pop_cfun ();
|
||||
}
|
||||
|
||||
|
||||
@ -1966,7 +1967,7 @@ lto_output (void)
|
||||
#endif
|
||||
decl_state = lto_new_out_decl_state ();
|
||||
lto_push_out_decl_state (decl_state);
|
||||
if (gimple_has_body_p (node->symbol.decl))
|
||||
if (gimple_has_body_p (node->symbol.decl) || !flag_wpa)
|
||||
output_function (node);
|
||||
else
|
||||
copy_function (node);
|
||||
@ -2149,9 +2150,9 @@ write_symbol (struct streamer_tree_cache_d *cache,
|
||||
if (!TREE_PUBLIC (t)
|
||||
|| is_builtin_fn (t)
|
||||
|| DECL_ABSTRACT (t)
|
||||
|| TREE_CODE (t) == RESULT_DECL
|
||||
|| (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t)))
|
||||
return;
|
||||
gcc_assert (TREE_CODE (t) != RESULT_DECL);
|
||||
|
||||
gcc_assert (TREE_CODE (t) == VAR_DECL
|
||||
|| TREE_CODE (t) == FUNCTION_DECL);
|
||||
@ -2254,7 +2255,7 @@ output_symbol_p (symtab_node node)
|
||||
and devirtualization. We do not want to see them in symbol table as
|
||||
references unless they are really used. */
|
||||
cnode = dyn_cast <cgraph_node> (node);
|
||||
if (cnode && DECL_EXTERNAL (cnode->symbol.decl)
|
||||
if (cnode && (!node->symbol.definition || DECL_EXTERNAL (cnode->symbol.decl))
|
||||
&& cnode->callers)
|
||||
return true;
|
||||
|
||||
@ -2262,7 +2263,7 @@ output_symbol_p (symtab_node node)
|
||||
part of the compilation unit until they are used by folding. Some symbols,
|
||||
like references to external construction vtables can not be referred to at all.
|
||||
We decide this at can_refer_decl_in_current_unit_p. */
|
||||
if (DECL_EXTERNAL (node->symbol.decl))
|
||||
if (!node->symbol.definition || DECL_EXTERNAL (node->symbol.decl))
|
||||
{
|
||||
int i;
|
||||
struct ipa_ref *ref;
|
||||
|
@ -1,3 +1,10 @@
|
||||
2013-08-02 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* lto.c (lto_materialize_function): Do not push struct function.
|
||||
* lto-partition.c (get_symbol_class): Handle abstracts correctly.
|
||||
(may_need_named_section_p): Even abstract origins may need
|
||||
named section.
|
||||
|
||||
2013-07-30 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* Make-lang.in (lto/lto.o:): Depend on CONTEXT_H and
|
||||
|
@ -56,6 +56,10 @@ get_symbol_class (symtab_node node)
|
||||
/* Inline clones are always duplicated.
|
||||
This include external delcarations. */
|
||||
cgraph_node *cnode = dyn_cast <cgraph_node> (node);
|
||||
|
||||
if (DECL_ABSTRACT (node->symbol.decl))
|
||||
return SYMBOL_EXTERNAL;
|
||||
|
||||
if (cnode && cnode->global.inlined_to)
|
||||
return SYMBOL_DUPLICATE;
|
||||
|
||||
@ -840,8 +844,6 @@ may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node)
|
||||
return false;
|
||||
if (symtab_real_symbol_p (node))
|
||||
return false;
|
||||
if (!cnode->global.inlined_to && !cnode->clones)
|
||||
return false;
|
||||
return (!encoder
|
||||
|| (lto_symtab_encoder_lookup (encoder, node) != LCC_NOT_FOUND
|
||||
&& lto_symtab_encoder_encode_body_p (encoder,
|
||||
|
@ -225,7 +225,6 @@ lto_materialize_function (struct cgraph_node *node)
|
||||
|
||||
gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
|
||||
|
||||
push_struct_function (decl);
|
||||
announce_function (decl);
|
||||
lto_input_function_body (file_data, decl, data);
|
||||
if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
|
||||
@ -233,7 +232,6 @@ lto_materialize_function (struct cgraph_node *node)
|
||||
lto_stats.num_function_bodies++;
|
||||
lto_free_section_data (file_data, LTO_section_function_body, name,
|
||||
data, len);
|
||||
pop_cfun ();
|
||||
ggc_collect ();
|
||||
}
|
||||
}
|
||||
|
@ -678,12 +678,7 @@ static void
|
||||
lto_input_ts_decl_non_common_tree_pointers (struct lto_input_block *ib,
|
||||
struct data_in *data_in, tree expr)
|
||||
{
|
||||
if (TREE_CODE (expr) == FUNCTION_DECL)
|
||||
{
|
||||
DECL_ARGUMENTS (expr) = streamer_read_chain (ib, data_in);
|
||||
DECL_RESULT (expr) = stream_read_tree (ib, data_in);
|
||||
}
|
||||
else if (TREE_CODE (expr) == TYPE_DECL)
|
||||
if (TREE_CODE (expr) == TYPE_DECL)
|
||||
DECL_ORIGINAL_TYPE (expr) = stream_read_tree (ib, data_in);
|
||||
DECL_VINDEX (expr) = stream_read_tree (ib, data_in);
|
||||
}
|
||||
|
@ -606,12 +606,7 @@ static void
|
||||
write_ts_decl_non_common_tree_pointers (struct output_block *ob, tree expr,
|
||||
bool ref_p)
|
||||
{
|
||||
if (TREE_CODE (expr) == FUNCTION_DECL)
|
||||
{
|
||||
streamer_write_chain (ob, DECL_ARGUMENTS (expr), ref_p);
|
||||
stream_write_tree (ob, DECL_RESULT (expr), ref_p);
|
||||
}
|
||||
else if (TREE_CODE (expr) == TYPE_DECL)
|
||||
if (TREE_CODE (expr) == TYPE_DECL)
|
||||
stream_write_tree (ob, DECL_ORIGINAL_TYPE (expr), ref_p);
|
||||
stream_write_tree (ob, DECL_VINDEX (expr), ref_p);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user