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:
parent
a0e33cbcd8
commit
ee03e71d47
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) */
|
||||
|
||||
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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 *);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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) \
|
||||
|
|
1403
gcc/lto/lto.c
1403
gcc/lto/lto.c
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
93
gcc/tree.c
93
gcc/tree.c
|
@ -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. */
|
||||
|
||||
|
|
24
gcc/tree.h
24
gcc/tree.h
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue