+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.
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)
}
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
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))
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
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;
basic_block bb;
struct cgraph_node *node;
- fn = DECL_STRUCT_FUNCTION (fn_decl);
tag = streamer_read_record_start (ib);
+ 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 ();
- lto_tag_check (tag, LTO_function);
+ 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);
/* 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);
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;
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;
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));
}
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));
}
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)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ /* We also stream abstract functions where we stream only stuff needed for
+ debug info. */
+ if (gimple_has_body_p (function))
+ {
+ 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 ();
}
#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);
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);
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;
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;
+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
/* 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;
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,
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)
lto_stats.num_function_bodies++;
lto_free_section_data (file_data, LTO_section_function_body, name,
data, len);
- pop_cfun ();
ggc_collect ();
}
}
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);
}
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);
}