lto-streamer.h (enum LTO_tags): Add LTO_tree_scc.

2013-06-17  Richard Biener  <rguenther@suse.de>

	* lto-streamer.h (enum LTO_tags): Add LTO_tree_scc.
	(lto_input_scc): Declare.
	(lto_input_tree_1): Likewise.
	(struct lto_stats_d): Add num_tree_bodies_output and
	num_pickle_refs_output.
	* lto-streamer-in.c (lto_read_body): Use streamer_tree_cache_get_tree.
	(lto_read_tree_1): Split out from ...
	(lto_read_tree): ... this.
	(lto_input_scc): New function.
	(lto_input_tree_1): Split out from ...
	(lto_input_tree): ... this.  Handle LTO_tree_scc.
	(lto_data_in_create): Create the streamer cache without hashes.
	* lto-streamer-out.c (create_output_block): Create the streamer
	cache with hashes when not doing WPA.
	(lto_write_tree_1): Split out from ...
	(lto_write_tree): ... this.
	(get_symbol_initial_value): New function.
	(lto_output_tree_1): Split out from ...
	(lto_output_tree): ... this.  Write trees as series of SCCs
	using a DFS walk via DFS_write_tree.
	(struct sccs, struct scc_entry): New types.
	(next_dfs_num, sccstack, sccstate, sccstate_obstack): New globals.
	(DFS_write_tree_body): New function.
	(DFS_write_tree): Likewise.
	(hash_tree): Likewise.
	(scc_entry_compare): Likewise.
	(hash_scc): Likewise.
	(tree_is_indexable): DEBUG_EXPR_DECLs are local entities.
	* tree-streamer-in.c (lto_input_ts_list_tree_pointers): Stream
	TREE_CHAIN as regular reference.
	(streamer_read_integer_cst): Remove.
	(streamer_get_pickled_tree): Adjust.
	* tree-streamer-out.c (streamer_write_chain): Disable streaming
	of DECL_EXTERNALs in BLOCK_VARS for now.
	(write_ts_list_tree_pointers): Stream TREE_CHAIN as regular
	reference.
	* tree-streamer.c (streamer_tree_cache_add_to_node_array):
	Add hash value argument and record that if hashes are recorded
	in the cache.
	(streamer_tree_cache_insert_1): Adjust.
	(streamer_tree_cache_insert): Likewise.
	(streamer_tree_cache_insert_at): Rename to ...
	(streamer_tree_cache_replace_tree): ... this and adjust.
	(streamer_tree_cache_append): Adjust.
	(record_common_node): Likewise.
	(streamer_tree_cache_create): Add argument whether to
	record hash values together with trees.
	(streamer_tree_cache_delete): Adjust.
	* tree-streamer.h (struct streamer_tree_cache_d): Add
	vector of hashes.
	(streamer_read_integer_cst): Remove.
	(streamer_tree_cache_insert): Adjust.
	(streamer_tree_cache_append): Likewise.
	(streamer_tree_cache_insert_at): Rename to ...
	(streamer_tree_cache_replace_tree): ... this and adjust.
	(streamer_tree_cache_create): Add argument whether to record hashes.
	(streamer_tree_cache_get): Rename to ...
	(streamer_tree_cache_get_tree): ... this.
	(streamer_tree_cache_get_hash): New function.
	* tree.c (cache_integer_cst): New function.
	* tree.h (cache_integer_cst): Declare.
	(ANON_AGGRNAME_FORMAT, ANON_AGGRNAME_P): Move here from cp/cp-tree.h.
	* lto-symtab.c (lto_varpool_replace_node): Only release
	DECL_INITIAL of non-prevailing decls.
	* varpool.c (varpool_remove_initializer): Do not release
	DECL_INITIAL when we are still in CGRAPH_LTO_STREAMING.

	cp/
	* cp-tree.h (ANON_AGGRNAME_FORMAT, ANON_AGGRNAME_P): Move to tree.h.

	lto/
	* Make-lang.in (lto.o): Add $(DATA_STREAMER_H) dependency.
	* lto.c: Include data-streamer.h.
	(lto_read_in_decl_state): Use streamer_tree_cache_get_tree.
	(gimple_type_leader_entry_s, gimple_type_leader,
	gimple_lookup_type_leader): Remove.
	(gtc_visit): Simplify.
	(gimple_types_compatible_p): Likewise.
	(gimple_register_type_1): Likewise.  Merge into ...
	(gimple_register_type): ... this.  Keep it as legacy for
	statistics purposes for now.
	(fixup_integer_cst): Remove.
	(LTO_FIXUP_TREE, lto_fixup_types, lto_ft_*): Simplify and
	rename to ...
	(MAYBE_REMEMBER_WITH_VARS, maybe_remember_with_vars,
	maybe_remember_with_vars_*): ... these.
	(uniquify_nodes): Remove.
	(lto_fixup_prevailing_type): New function.
	(struct tree_scc, struct tree_scc_hasher): New type and hasher.
	(tree_scc_hash, tree_scc_hash_obstack): New globals.
	(num_merged_types, num_prevailing_types, num_not_merged_types,
	num_not_merged_types_in_same_scc, total_scc_size, num_sccs_read,
	total_scc_size_merged, num_sccs_merged, num_scc_compares,
	num_scc_compare_collisions): New global counters.
	(compare_tree_sccs_1): New function.
	(compare_tree_sccs): Likewise.
	(unify_scc): Likewise.
	(lto_read_decls): Stream in tree SCCs and unify them on the
	way in.  Finalize prevailing SCC tree members.
	(read_cgraph_and_symbols): Do not initialize or free gimple_type_leader.
	Allocate and free tree_scc_hash_obstack and tree_scc_hash, do not bother
	to ggc-collect during merging.
	(print_lto_report_1): Adjust for new merging code.

From-SVN: r200151
This commit is contained in:
Richard Biener 2013-06-17 15:08:24 +00:00 committed by Richard Biener
parent a0e33cbcd8
commit ee03e71d47
18 changed files with 2395 additions and 606 deletions

View File

@ -1,3 +1,72 @@
2013-06-17 Richard Biener <rguenther@suse.de>
* lto-streamer.h (enum LTO_tags): Add LTO_tree_scc.
(lto_input_scc): Declare.
(lto_input_tree_1): Likewise.
(struct lto_stats_d): Add num_tree_bodies_output and
num_pickle_refs_output.
* lto-streamer-in.c (lto_read_body): Use streamer_tree_cache_get_tree.
(lto_read_tree_1): Split out from ...
(lto_read_tree): ... this.
(lto_input_scc): New function.
(lto_input_tree_1): Split out from ...
(lto_input_tree): ... this. Handle LTO_tree_scc.
(lto_data_in_create): Create the streamer cache without hashes.
* lto-streamer-out.c (create_output_block): Create the streamer
cache with hashes when not doing WPA.
(lto_write_tree_1): Split out from ...
(lto_write_tree): ... this.
(get_symbol_initial_value): New function.
(lto_output_tree_1): Split out from ...
(lto_output_tree): ... this. Write trees as series of SCCs
using a DFS walk via DFS_write_tree.
(struct sccs, struct scc_entry): New types.
(next_dfs_num, sccstack, sccstate, sccstate_obstack): New globals.
(DFS_write_tree_body): New function.
(DFS_write_tree): Likewise.
(hash_tree): Likewise.
(scc_entry_compare): Likewise.
(hash_scc): Likewise.
(tree_is_indexable): DEBUG_EXPR_DECLs are local entities.
* tree-streamer-in.c (lto_input_ts_list_tree_pointers): Stream
TREE_CHAIN as regular reference.
(streamer_read_integer_cst): Remove.
(streamer_get_pickled_tree): Adjust.
* tree-streamer-out.c (streamer_write_chain): Disable streaming
of DECL_EXTERNALs in BLOCK_VARS for now.
(write_ts_list_tree_pointers): Stream TREE_CHAIN as regular
reference.
* tree-streamer.c (streamer_tree_cache_add_to_node_array):
Add hash value argument and record that if hashes are recorded
in the cache.
(streamer_tree_cache_insert_1): Adjust.
(streamer_tree_cache_insert): Likewise.
(streamer_tree_cache_insert_at): Rename to ...
(streamer_tree_cache_replace_tree): ... this and adjust.
(streamer_tree_cache_append): Adjust.
(record_common_node): Likewise.
(streamer_tree_cache_create): Add argument whether to
record hash values together with trees.
(streamer_tree_cache_delete): Adjust.
* tree-streamer.h (struct streamer_tree_cache_d): Add
vector of hashes.
(streamer_read_integer_cst): Remove.
(streamer_tree_cache_insert): Adjust.
(streamer_tree_cache_append): Likewise.
(streamer_tree_cache_insert_at): Rename to ...
(streamer_tree_cache_replace_tree): ... this and adjust.
(streamer_tree_cache_create): Add argument whether to record hashes.
(streamer_tree_cache_get): Rename to ...
(streamer_tree_cache_get_tree): ... this.
(streamer_tree_cache_get_hash): New function.
* tree.c (cache_integer_cst): New function.
* tree.h (cache_integer_cst): Declare.
(ANON_AGGRNAME_FORMAT, ANON_AGGRNAME_P): Move here from cp/cp-tree.h.
* lto-symtab.c (lto_varpool_replace_node): Only release
DECL_INITIAL of non-prevailing decls.
* varpool.c (varpool_remove_initializer): Do not release
DECL_INITIAL when we are still in CGRAPH_LTO_STREAMING.
2013-06-16 Jürgen Urban <JuergenUrban@gmx.de>
* config/mips/mips.h (ISA_HAS_MUL3): Include TARGET_MIPS5900.

View File

@ -1,3 +1,7 @@
2013-06-17 Richard Biener <rguenther@suse.de>
* cp-tree.h (ANON_AGGRNAME_FORMAT, ANON_AGGRNAME_P): Move to tree.h.
2013-06-17 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/16128

View File

@ -4345,8 +4345,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
#define VFIELD_NAME "_vptr."
#define VFIELD_NAME_FORMAT "_vptr.%s"
#define ANON_AGGRNAME_FORMAT "._%d"
#else /* NO_DOT_IN_LABEL */
#ifndef NO_DOLLAR_IN_LABEL
@ -4357,7 +4355,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
#define VFIELD_BASE "$vf"
#define VFIELD_NAME "_vptr$"
#define VFIELD_NAME_FORMAT "_vptr$%s"
#define ANON_AGGRNAME_FORMAT "$_%d"
#else /* NO_DOLLAR_IN_LABEL */
@ -4376,12 +4373,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
sizeof (VFIELD_NAME) - 1))
#define VFIELD_NAME_FORMAT "__vptr_%s"
#define ANON_AGGRNAME_PREFIX "__anon_"
#define ANON_AGGRNAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), ANON_AGGRNAME_PREFIX, \
sizeof (ANON_AGGRNAME_PREFIX) - 1))
#define ANON_AGGRNAME_FORMAT "__anon_%d"
#endif /* NO_DOLLAR_IN_LABEL */
#endif /* NO_DOT_IN_LABEL */
@ -4418,11 +4409,6 @@ extern GTY(()) vec<tree, va_gc> *local_classes;
#define VFIELD_NAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), VFIELD_NAME, sizeof(VFIELD_NAME)-1))
/* For anonymous aggregate types, we need some sort of name to
hold on to. In practice, this should not appear, but it should
not be harmful if it does. */
#define ANON_AGGRNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == JOINER \
&& IDENTIFIER_POINTER (ID_NODE)[1] == '_')
#endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */

View File

@ -1016,7 +1016,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
unsigned i;
for (i = len; i-- > from;)
{
tree t = cache->nodes[i];
tree t = streamer_tree_cache_get_tree (cache, i);
if (t == NULL_TREE)
continue;
@ -1056,12 +1056,43 @@ lto_input_function_body (struct lto_file_decl_data *file_data,
}
/* Read the physical representation of a tree node EXPR from
input block IB using the per-file context in DATA_IN. */
static void
lto_read_tree_1 (struct lto_input_block *ib, struct data_in *data_in, tree expr)
{
/* Read all the bitfield values in EXPR. Note that for LTO, we
only write language-independent bitfields, so no more unpacking is
needed. */
streamer_read_tree_bitfields (ib, data_in, expr);
/* Read all the pointer fields in EXPR. */
streamer_read_tree_body (ib, data_in, expr);
/* Read any LTO-specific data not read by the tree streamer. */
if (DECL_P (expr)
&& TREE_CODE (expr) != FUNCTION_DECL
&& TREE_CODE (expr) != TRANSLATION_UNIT_DECL)
DECL_INITIAL (expr) = stream_read_tree (ib, data_in);
/* We should never try to instantiate an MD or NORMAL builtin here. */
if (TREE_CODE (expr) == FUNCTION_DECL)
gcc_assert (!streamer_handle_as_builtin_p (expr));
#ifdef LTO_STREAMER_DEBUG
/* Remove the mapping to RESULT's original address set by
streamer_alloc_tree. */
lto_orig_address_remove (expr);
#endif
}
/* Read the physical representation of a tree node with tag TAG from
input block IB using the per-file context in DATA_IN. */
static tree
lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
enum LTO_tags tag)
enum LTO_tags tag, hashval_t hash)
{
/* Instantiate a new tree node. */
tree result = streamer_alloc_tree (ib, data_in, tag);
@ -1069,49 +1100,83 @@ lto_read_tree (struct lto_input_block *ib, struct data_in *data_in,
/* Enter RESULT in the reader cache. This will make RESULT
available so that circular references in the rest of the tree
structure can be resolved in subsequent calls to stream_read_tree. */
streamer_tree_cache_append (data_in->reader_cache, result);
streamer_tree_cache_append (data_in->reader_cache, result, hash);
/* Read all the bitfield values in RESULT. Note that for LTO, we
only write language-independent bitfields, so no more unpacking is
needed. */
streamer_read_tree_bitfields (ib, data_in, result);
/* Read all the pointer fields in RESULT. */
streamer_read_tree_body (ib, data_in, result);
/* Read any LTO-specific data not read by the tree streamer. */
if (DECL_P (result)
&& TREE_CODE (result) != FUNCTION_DECL
&& TREE_CODE (result) != TRANSLATION_UNIT_DECL)
DECL_INITIAL (result) = stream_read_tree (ib, data_in);
/* We should never try to instantiate an MD or NORMAL builtin here. */
if (TREE_CODE (result) == FUNCTION_DECL)
gcc_assert (!streamer_handle_as_builtin_p (result));
lto_read_tree_1 (ib, data_in, result);
/* end_marker = */ streamer_read_uchar (ib);
#ifdef LTO_STREAMER_DEBUG
/* Remove the mapping to RESULT's original address set by
streamer_alloc_tree. */
lto_orig_address_remove (result);
#endif
return result;
}
/* Populate the reader cache with trees materialized from the SCC
following in the IB, DATA_IN stream. */
hashval_t
lto_input_scc (struct lto_input_block *ib, struct data_in *data_in,
unsigned *len, unsigned *entry_len)
{
/* A blob of unnamed tree nodes, fill the cache from it and
recurse. */
unsigned size = streamer_read_uhwi (ib);
hashval_t scc_hash = streamer_read_uhwi (ib);
unsigned scc_entry_len = 1;
if (size == 1)
{
enum LTO_tags tag = streamer_read_record_start (ib);
lto_input_tree_1 (ib, data_in, tag, scc_hash);
}
else
{
unsigned int first = data_in->reader_cache->nodes.length ();
tree result;
scc_entry_len = streamer_read_uhwi (ib);
/* Materialize size trees by reading their headers. */
for (unsigned i = 0; i < size; ++i)
{
enum LTO_tags tag = streamer_read_record_start (ib);
if (tag == LTO_null
|| (tag >= LTO_field_decl_ref && tag <= LTO_global_decl_ref)
|| tag == LTO_tree_pickle_reference
|| tag == LTO_builtin_decl
|| tag == LTO_integer_cst
|| tag == LTO_tree_scc)
gcc_unreachable ();
result = streamer_alloc_tree (ib, data_in, tag);
streamer_tree_cache_append (data_in->reader_cache, result, 0);
}
/* Read the tree bitpacks and references. */
for (unsigned i = 0; i < size; ++i)
{
result = streamer_tree_cache_get_tree (data_in->reader_cache,
first + i);
lto_read_tree_1 (ib, data_in, result);
/* end_marker = */ streamer_read_uchar (ib);
}
}
*len = size;
*entry_len = scc_entry_len;
return scc_hash;
}
/* Read a tree from input block IB using the per-file context in
DATA_IN. This context is used, for example, to resolve references
to previously read nodes. */
tree
lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
lto_input_tree_1 (struct lto_input_block *ib, struct data_in *data_in,
enum LTO_tags tag, hashval_t hash)
{
enum LTO_tags tag;
tree result;
tag = streamer_read_record_start (ib);
gcc_assert ((unsigned) tag < (unsigned) LTO_NUM_TAGS);
if (tag == LTO_null)
@ -1137,19 +1202,39 @@ lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
}
else if (tag == LTO_integer_cst)
{
/* For shared integer constants we only need the type and its hi/low
words. */
result = streamer_read_integer_cst (ib, data_in);
/* For shared integer constants in singletons we can use the existing
tree integer constant merging code. */
tree type = stream_read_tree (ib, data_in);
unsigned HOST_WIDE_INT low = streamer_read_uhwi (ib);
HOST_WIDE_INT high = streamer_read_hwi (ib);
result = build_int_cst_wide (type, low, high);
streamer_tree_cache_append (data_in->reader_cache, result, hash);
}
else if (tag == LTO_tree_scc)
{
unsigned len, entry_len;
/* Input and skip the SCC. */
lto_input_scc (ib, data_in, &len, &entry_len);
/* Recurse. */
return lto_input_tree (ib, data_in);
}
else
{
/* Otherwise, materialize a new node from IB. */
result = lto_read_tree (ib, data_in, tag);
result = lto_read_tree (ib, data_in, tag, hash);
}
return result;
}
tree
lto_input_tree (struct lto_input_block *ib, struct data_in *data_in)
{
return lto_input_tree_1 (ib, data_in, streamer_read_record_start (ib), 0);
}
/* Input toplevel asms. */
@ -1220,7 +1305,7 @@ lto_data_in_create (struct lto_file_decl_data *file_data, const char *strings,
data_in->strings = strings;
data_in->strings_len = len;
data_in->globals_resolution = resolutions;
data_in->reader_cache = streamer_tree_cache_create ();
data_in->reader_cache = streamer_tree_cache_create (false);
return data_in;
}

File diff suppressed because it is too large Load Diff

View File

@ -227,6 +227,13 @@ print_lto_report (const char *s)
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
lto_stats.num_output_symtab_nodes);
fprintf (stderr, "[%s] # of output tree pickle references: "
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
lto_stats.num_pickle_refs_output);
fprintf (stderr, "[%s] # of output tree bodies: "
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
lto_stats.num_tree_bodies_output);
fprintf (stderr, "[%s] # callgraph partitions: "
HOST_WIDE_INT_PRINT_UNSIGNED "\n", s,
lto_stats.num_cgraph_partitions);

View File

@ -199,6 +199,9 @@ enum LTO_tags
/* EH try/catch node. */
LTO_eh_catch,
/* Special for global streamer. A blob of unnamed tree nodes. */
LTO_tree_scc,
/* References to indexable tree nodes. These objects are stored in
tables that are written separately from the function bodies that
reference them. This way they can be instantiated even when the
@ -421,6 +424,8 @@ struct lto_stats_d
unsigned HOST_WIDE_INT num_compressed_il_bytes;
unsigned HOST_WIDE_INT num_input_il_bytes;
unsigned HOST_WIDE_INT num_uncompressed_il_bytes;
unsigned HOST_WIDE_INT num_tree_bodies_output;
unsigned HOST_WIDE_INT num_pickle_refs_output;
};
/* Entry of LTO symtab encoder. */
@ -854,6 +859,10 @@ tree lto_input_tree_ref (struct lto_input_block *, struct data_in *,
struct function *, enum LTO_tags);
void lto_tag_check_set (enum LTO_tags, int, ...);
void lto_init_eh (void);
hashval_t lto_input_scc (struct lto_input_block *, struct data_in *,
unsigned *, unsigned *);
tree lto_input_tree_1 (struct lto_input_block *, struct data_in *,
enum LTO_tags, hashval_t hash);
tree lto_input_tree (struct lto_input_block *, struct data_in *);

View File

@ -97,7 +97,8 @@ lto_varpool_replace_node (struct varpool_node *vnode,
ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list);
/* Be sure we can garbage collect the initializer. */
if (DECL_INITIAL (vnode->symbol.decl))
if (DECL_INITIAL (vnode->symbol.decl)
&& vnode->symbol.decl != prevailing_node->symbol.decl)
DECL_INITIAL (vnode->symbol.decl) = error_mark_node;
/* Finally remove the replaced node. */
varpool_remove_node (vnode);

View File

@ -1,3 +1,38 @@
2013-06-17 Richard Biener <rguenther@suse.de>
* Make-lang.in (lto.o): Add $(DATA_STREAMER_H) dependency.
* lto.c: Include data-streamer.h.
(lto_read_in_decl_state): Use streamer_tree_cache_get_tree.
(gimple_type_leader_entry_s, gimple_type_leader,
gimple_lookup_type_leader): Remove.
(gtc_visit): Simplify.
(gimple_types_compatible_p): Likewise.
(gimple_register_type_1): Likewise. Merge into ...
(gimple_register_type): ... this. Keep it as legacy for
statistics purposes for now.
(fixup_integer_cst): Remove.
(LTO_FIXUP_TREE, lto_fixup_types, lto_ft_*): Simplify and
rename to ...
(MAYBE_REMEMBER_WITH_VARS, maybe_remember_with_vars,
maybe_remember_with_vars_*): ... these.
(uniquify_nodes): Remove.
(lto_fixup_prevailing_type): New function.
(struct tree_scc, struct tree_scc_hasher): New type and hasher.
(tree_scc_hash, tree_scc_hash_obstack): New globals.
(num_merged_types, num_prevailing_types, num_not_merged_types,
num_not_merged_types_in_same_scc, total_scc_size, num_sccs_read,
total_scc_size_merged, num_sccs_merged, num_scc_compares,
num_scc_compare_collisions): New global counters.
(compare_tree_sccs_1): New function.
(compare_tree_sccs): Likewise.
(unify_scc): Likewise.
(lto_read_decls): Stream in tree SCCs and unify them on the
way in. Finalize prevailing SCC tree members.
(read_cgraph_and_symbols): Do not initialize or free gimple_type_leader.
Allocate and free tree_scc_hash_obstack and tree_scc_hash, do not bother
to ggc-collect during merging.
(print_lto_report_1): Adjust for new merging code.
2013-06-12 Jan Hubicka <jh@suse.cz>
* lto.c (read_cgraph_and_symbols): Set cgraph into streaming state.

View File

@ -85,7 +85,7 @@ lto/lto.o: lto/lto.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(OPTS_H) \
langhooks.h $(VEC_H) $(BITMAP_H) pointer-set.h $(IPA_PROP_H) \
$(COMMON_H) debug.h $(GIMPLE_H) $(LTO_H) $(LTO_TREE_H) \
$(LTO_TAGS_H) $(LTO_STREAMER_H) $(SPLAY_TREE_H) gt-lto-lto.h \
$(TREE_STREAMER_H) lto/lto-partition.h
$(TREE_STREAMER_H) $(DATA_STREAMER_H) lto/lto-partition.h
lto/lto-partition.o: lto/lto-partition.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
toplev.h $(TREE_H) $(TM_H) \
$(CGRAPH_H) $(TIMEVAR_H) \

File diff suppressed because it is too large Load Diff

View File

@ -122,10 +122,10 @@ unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
else
TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_USED (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_PRIVATE (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TREE_CODE (expr) != TREE_BINFO)
TREE_PRIVATE (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_PROTECTED (expr) = (unsigned) bp_unpack_value (bp, 1);
TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
if (TYPE_P (expr))
@ -351,8 +351,6 @@ unpack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
TYPE_NONALIASED_COMPONENT (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_PACKED (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr)
= (unsigned) bp_unpack_value (bp, 2);
TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
TYPE_PRECISION (expr) = bp_unpack_var_len_unsigned (bp);
@ -811,7 +809,7 @@ lto_input_ts_list_tree_pointers (struct lto_input_block *ib,
{
TREE_PURPOSE (expr) = stream_read_tree (ib, data_in);
TREE_VALUE (expr) = stream_read_tree (ib, data_in);
TREE_CHAIN (expr) = streamer_read_chain (ib, data_in);
TREE_CHAIN (expr) = stream_read_tree (ib, data_in);
}
@ -1021,19 +1019,6 @@ streamer_read_tree_body (struct lto_input_block *ib, struct data_in *data_in,
}
/* Read and INTEGER_CST node from input block IB using the per-file
context in DATA_IN. */
tree
streamer_read_integer_cst (struct lto_input_block *ib, struct data_in *data_in)
{
tree type = stream_read_tree (ib, data_in);
unsigned HOST_WIDE_INT low = streamer_read_uhwi (ib);
HOST_WIDE_INT high = streamer_read_hwi (ib);
return build_int_cst_wide (type, low, high);
}
/* Read an index IX from input block IB and return the tree node at
DATA_IN->FILE_DATA->GLOBALS_INDEX[IX]. */
@ -1047,7 +1032,7 @@ streamer_get_pickled_tree (struct lto_input_block *ib, struct data_in *data_in)
ix = streamer_read_uhwi (ib);
expected_tag = streamer_read_enum (ib, LTO_tags, LTO_NUM_TAGS);
result = streamer_tree_cache_get (data_in->reader_cache, ix);
result = streamer_tree_cache_get_tree (data_in->reader_cache, ix);
gcc_assert (result
&& TREE_CODE (result) == lto_tag_to_tree_code (expected_tag));
@ -1091,7 +1076,7 @@ streamer_get_builtin_tree (struct lto_input_block *ib, struct data_in *data_in)
if (asmname)
set_builtin_user_assembler_name (result, asmname);
streamer_tree_cache_append (data_in->reader_cache, result);
streamer_tree_cache_append (data_in->reader_cache, result, 0);
return result;
}

View File

@ -95,10 +95,10 @@ pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1);
else
bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
bp_pack_value (bp, TREE_USED (expr), 1);
bp_pack_value (bp, TREE_NOTHROW (expr), 1);
bp_pack_value (bp, TREE_STATIC (expr), 1);
bp_pack_value (bp, TREE_PRIVATE (expr), 1);
if (TREE_CODE (expr) != TREE_BINFO)
bp_pack_value (bp, TREE_PRIVATE (expr), 1);
bp_pack_value (bp, TREE_PROTECTED (expr), 1);
bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
if (TYPE_P (expr))
@ -298,12 +298,15 @@ pack_ts_type_common_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, TYPE_NONALIASED_COMPONENT (expr), 1);
bp_pack_value (bp, TYPE_PACKED (expr), 1);
bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
bp_pack_value (bp, TYPE_CONTAINS_PLACEHOLDER_INTERNAL (expr), 2);
bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
bp_pack_value (bp, TYPE_READONLY (expr), 1);
bp_pack_var_len_unsigned (bp, TYPE_PRECISION (expr));
bp_pack_var_len_unsigned (bp, TYPE_ALIGN (expr));
bp_pack_var_len_int (bp, TYPE_ALIAS_SET (expr) == 0 ? 0 : -1);
/* Make sure to preserve the fact whether the frontend would assign
alias-set zero to this type. */
bp_pack_var_len_int (bp, (TYPE_ALIAS_SET (expr) == 0
|| (!in_lto_p
&& get_alias_set (expr) == 0)) ? 0 : -1);
}
@ -491,9 +494,10 @@ streamer_write_chain (struct output_block *ob, tree t, bool ref_p)
to the global decls section as we do not want to have them
enter decl merging. This is, of course, only for the call
for streaming BLOCK_VARS, but other callers are safe. */
/* ??? FIXME wrt SCC streaming. Drop these for now. */
if (VAR_OR_FUNCTION_DECL_P (t)
&& DECL_EXTERNAL (t))
stream_write_tree_shallow_non_ref (ob, t, ref_p);
; /* stream_write_tree_shallow_non_ref (ob, t, ref_p); */
else
stream_write_tree (ob, t, ref_p);
@ -553,7 +557,13 @@ static void
write_ts_decl_minimal_tree_pointers (struct output_block *ob, tree expr,
bool ref_p)
{
stream_write_tree (ob, DECL_NAME (expr), ref_p);
/* Drop names that were created for anonymous entities. */
if (DECL_NAME (expr)
&& TREE_CODE (DECL_NAME (expr)) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (DECL_NAME (expr)))
stream_write_tree (ob, NULL_TREE, ref_p);
else
stream_write_tree (ob, DECL_NAME (expr), ref_p);
stream_write_tree (ob, DECL_CONTEXT (expr), ref_p);
}
@ -716,7 +726,7 @@ write_ts_list_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
{
stream_write_tree (ob, TREE_PURPOSE (expr), ref_p);
stream_write_tree (ob, TREE_VALUE (expr), ref_p);
streamer_write_chain (ob, TREE_CHAIN (expr), ref_p);
stream_write_tree (ob, TREE_CHAIN (expr), ref_p);
}
@ -842,6 +852,8 @@ streamer_write_tree_body (struct output_block *ob, tree expr, bool ref_p)
{
enum tree_code code;
lto_stats.num_tree_bodies_output++;
code = TREE_CODE (expr);
if (CODE_CONTAINS_STRUCT (code, TS_TYPED))

View File

@ -92,16 +92,24 @@ streamer_check_handled_ts_structures (void)
static void
streamer_tree_cache_add_to_node_array (struct streamer_tree_cache_d *cache,
unsigned ix, tree t)
unsigned ix, tree t, hashval_t hash)
{
/* Make sure we're either replacing an old element or
appending consecutively. */
gcc_assert (ix <= cache->nodes.length ());
if (ix == cache->nodes.length ())
cache->nodes.safe_push (t);
{
cache->nodes.safe_push (t);
if (cache->hashes.exists ())
cache->hashes.safe_push (hash);
}
else
cache->nodes[ix] = t;
{
cache->nodes[ix] = t;
if (cache->hashes.exists ())
cache->hashes[ix] = hash;
}
}
@ -117,7 +125,7 @@ streamer_tree_cache_add_to_node_array (struct streamer_tree_cache_d *cache,
static bool
streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
tree t, unsigned *ix_p,
tree t, hashval_t hash, unsigned *ix_p,
bool insert_at_next_slot_p)
{
void **slot;
@ -136,7 +144,7 @@ streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
ix = *ix_p;
*slot = (void *)(size_t) (ix + 1);
streamer_tree_cache_add_to_node_array (cache, ix, t);
streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
/* Indicate that the item was not present in the cache. */
existed_p = false;
@ -151,7 +159,7 @@ streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
location, and ENTRY->TO does not match *IX_P, add T to
the requested location slot. */
ix = *ix_p;
streamer_tree_cache_add_to_node_array (cache, ix, t);
streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
*slot = (void *)(size_t) (ix + 1);
}
@ -174,30 +182,33 @@ streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
bool
streamer_tree_cache_insert (struct streamer_tree_cache_d *cache, tree t,
unsigned *ix_p)
hashval_t hash, unsigned *ix_p)
{
return streamer_tree_cache_insert_1 (cache, t, ix_p, true);
return streamer_tree_cache_insert_1 (cache, t, hash, ix_p, true);
}
/* Insert tree node T in CACHE at slot IX. If T already
existed in the cache return true. Otherwise, return false. */
/* Replace the tree node with T in CACHE at slot IX. */
bool
streamer_tree_cache_insert_at (struct streamer_tree_cache_d *cache,
tree t, unsigned ix)
void
streamer_tree_cache_replace_tree (struct streamer_tree_cache_d *cache,
tree t, unsigned ix)
{
return streamer_tree_cache_insert_1 (cache, t, &ix, false);
hashval_t hash = 0;
if (cache->hashes.exists ())
hash = streamer_tree_cache_get_hash (cache, ix);
streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
}
/* Appends tree node T to CACHE, even if T already existed in it. */
void
streamer_tree_cache_append (struct streamer_tree_cache_d *cache, tree t)
streamer_tree_cache_append (struct streamer_tree_cache_d *cache,
tree t, hashval_t hash)
{
unsigned ix = cache->nodes.length ();
streamer_tree_cache_insert_1 (cache, t, &ix, false);
streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
}
/* Return true if tree node T exists in CACHE, otherwise false. If IX_P is
@ -257,7 +268,10 @@ record_common_node (struct streamer_tree_cache_d *cache, tree node)
if (!node)
node = error_mark_node;
streamer_tree_cache_append (cache, node);
/* ??? FIXME, devise a better hash value. But the hash needs to be equal
for all frontend and lto1 invocations. So just use the position
in the cache as hash value. */
streamer_tree_cache_append (cache, node, cache->nodes.length ());
if (POINTER_TYPE_P (node)
|| TREE_CODE (node) == COMPLEX_TYPE
@ -305,13 +319,16 @@ preload_common_nodes (struct streamer_tree_cache_d *cache)
/* Create a cache of pickled nodes. */
struct streamer_tree_cache_d *
streamer_tree_cache_create (void)
streamer_tree_cache_create (bool with_hashes)
{
struct streamer_tree_cache_d *cache;
cache = XCNEW (struct streamer_tree_cache_d);
cache->node_map = pointer_map_create ();
cache->nodes.create (165);
if (with_hashes)
cache->hashes.create (165);
/* Load all the well-known tree nodes that are always created by
the compiler on startup. This prevents writing them out
@ -332,5 +349,6 @@ streamer_tree_cache_delete (struct streamer_tree_cache_d *c)
pointer_map_destroy (c->node_map);
c->nodes.release ();
c->hashes.release ();
free (c);
}

View File

@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see
T. The reconstructed T is inserted in some array so that when
the reference index for T is found in the input stream, it can be
used to look up into the array to get the reconstructed T. */
struct streamer_tree_cache_d
{
/* The mapping between tree nodes and slots into the nodes array. */
@ -50,6 +51,8 @@ struct streamer_tree_cache_d
/* The nodes pickled so far. */
vec<tree> nodes;
/* The node hashes (if available). */
vec<hashval_t> hashes;
};
/* Return true if tree node EXPR should be streamed as a builtin. For
@ -71,7 +74,6 @@ tree streamer_alloc_tree (struct lto_input_block *, struct data_in *,
void streamer_read_tree_body (struct lto_input_block *, struct data_in *, tree);
tree streamer_get_pickled_tree (struct lto_input_block *, struct data_in *);
tree streamer_get_builtin_tree (struct lto_input_block *, struct data_in *);
tree streamer_read_integer_cst (struct lto_input_block *, struct data_in *);
struct bitpack_d streamer_read_tree_bitfields (struct lto_input_block *,
struct data_in *, tree);
@ -89,22 +91,31 @@ void streamer_write_builtin (struct output_block *, tree);
/* In tree-streamer.c. */
void streamer_check_handled_ts_structures (void);
bool streamer_tree_cache_insert (struct streamer_tree_cache_d *, tree,
unsigned *);
bool streamer_tree_cache_insert_at (struct streamer_tree_cache_d *, tree,
unsigned);
void streamer_tree_cache_append (struct streamer_tree_cache_d *, tree);
hashval_t, unsigned *);
void streamer_tree_cache_replace_tree (struct streamer_tree_cache_d *, tree,
unsigned);
void streamer_tree_cache_append (struct streamer_tree_cache_d *, tree,
hashval_t);
bool streamer_tree_cache_lookup (struct streamer_tree_cache_d *, tree,
unsigned *);
struct streamer_tree_cache_d *streamer_tree_cache_create (void);
struct streamer_tree_cache_d *streamer_tree_cache_create (bool);
void streamer_tree_cache_delete (struct streamer_tree_cache_d *);
/* Return the tree node at slot IX in CACHE. */
static inline tree
streamer_tree_cache_get (struct streamer_tree_cache_d *cache, unsigned ix)
streamer_tree_cache_get_tree (struct streamer_tree_cache_d *cache, unsigned ix)
{
return cache->nodes[ix];
}
/* Return the tree hash value at slot IX in CACHE. */
static inline hashval_t
streamer_tree_cache_get_hash (struct streamer_tree_cache_d *cache, unsigned ix)
{
return cache->hashes[ix];
}
#endif /* GCC_TREE_STREAMER_H */

View File

@ -1266,6 +1266,99 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
return t;
}
void
cache_integer_cst (tree t)
{
tree type = TREE_TYPE (t);
HOST_WIDE_INT hi = TREE_INT_CST_HIGH (t);
unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (t);
int ix = -1;
int limit = 0;
gcc_assert (!TREE_OVERFLOW (t));
switch (TREE_CODE (type))
{
case NULLPTR_TYPE:
gcc_assert (hi == 0 && low == 0);
/* Fallthru. */
case POINTER_TYPE:
case REFERENCE_TYPE:
/* Cache NULL pointer. */
if (!hi && !low)
{
limit = 1;
ix = 0;
}
break;
case BOOLEAN_TYPE:
/* Cache false or true. */
limit = 2;
if (!hi && low < 2)
ix = low;
break;
case INTEGER_TYPE:
case OFFSET_TYPE:
if (TYPE_UNSIGNED (type))
{
/* Cache 0..N */
limit = INTEGER_SHARE_LIMIT;
if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
ix = low;
}
else
{
/* Cache -1..N */
limit = INTEGER_SHARE_LIMIT + 1;
if (!hi && low < (unsigned HOST_WIDE_INT)INTEGER_SHARE_LIMIT)
ix = low + 1;
else if (hi == -1 && low == -(unsigned HOST_WIDE_INT)1)
ix = 0;
}
break;
case ENUMERAL_TYPE:
break;
default:
gcc_unreachable ();
}
if (ix >= 0)
{
/* Look for it in the type's vector of small shared ints. */
if (!TYPE_CACHED_VALUES_P (type))
{
TYPE_CACHED_VALUES_P (type) = 1;
TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
}
gcc_assert (TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) == NULL_TREE);
TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
}
else
{
/* Use the cache of larger shared ints. */
void **slot;
slot = htab_find_slot (int_cst_hash_table, t, INSERT);
/* If there is already an entry for the number verify it's the
same. */
if (*slot)
{
gcc_assert (TREE_INT_CST_LOW ((tree)*slot) == low
&& TREE_INT_CST_HIGH ((tree)*slot) == hi);
return;
}
/* Otherwise insert this one into the hash table. */
*slot = t;
}
}
/* Builds an integer constant in TYPE such that lowest BITS bits are ones
and the rest are zeros. */

View File

@ -5637,6 +5637,7 @@ extern const_tree strip_invariant_refs (const_tree);
extern tree lhd_gcc_personality (void);
extern void assign_assembler_name_if_neeeded (tree);
extern void warn_deprecated_use (tree, tree);
extern void cache_integer_cst (tree);
/* In cgraph.c */
@ -6582,4 +6583,27 @@ builtin_decl_implicit_p (enum built_in_function fncode)
&& builtin_info.implicit_p[uns_fncode]);
}
/* For anonymous aggregate types, we need some sort of name to
hold on to. In practice, this should not appear, but it should
not be harmful if it does. */
#ifndef NO_DOT_IN_LABEL
#define ANON_AGGRNAME_FORMAT "._%d"
#define ANON_AGGRNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '.' \
&& IDENTIFIER_POINTER (ID_NODE)[1] == '_')
#else /* NO_DOT_IN_LABEL */
#ifndef NO_DOLLAR_IN_LABEL
#define ANON_AGGRNAME_FORMAT "$_%d"
#define ANON_AGGRNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '$' \
&& IDENTIFIER_POINTER (ID_NODE)[1] == '_')
#else /* NO_DOLLAR_IN_LABEL */
#define ANON_AGGRNAME_PREFIX "__anon_"
#define ANON_AGGRNAME_P(ID_NODE) \
(!strncmp (IDENTIFIER_POINTER (ID_NODE), ANON_AGGRNAME_PREFIX, \
sizeof (ANON_AGGRNAME_PREFIX) - 1))
#define ANON_AGGRNAME_FORMAT "__anon_%d"
#endif /* NO_DOLLAR_IN_LABEL */
#endif /* NO_DOT_IN_LABEL */
#endif /* GCC_TREE_H */

View File

@ -84,7 +84,12 @@ varpool_remove_initializer (struct varpool_node *node)
/* Keep vtables for BINFO folding. */
&& !DECL_VIRTUAL_P (node->symbol.decl)
/* FIXME: http://gcc.gnu.org/PR55395 */
&& debug_info_level == DINFO_LEVEL_NONE)
&& debug_info_level == DINFO_LEVEL_NONE
/* When doing declaration merging we have duplicate
entries for given decl. Do not attempt to remove
the boides, or we will end up remiving
wrong one. */
&& cgraph_state != CGRAPH_LTO_STREAMING)
DECL_INITIAL (node->symbol.decl) = error_mark_node;
}