diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-07-11 19:43:44 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-07-11 17:43:44 +0000 |
commit | 0b83e6882437a80458a7435cf434fbdccb37fa60 (patch) | |
tree | 559538902f5da455d349414895289f88f3911435 /gcc/varpool.c | |
parent | 01a92e704282e69fc3ec7d817637b8074454168d (diff) | |
download | gcc-0b83e6882437a80458a7435cf434fbdccb37fa60.zip gcc-0b83e6882437a80458a7435cf434fbdccb37fa60.tar.gz gcc-0b83e6882437a80458a7435cf434fbdccb37fa60.tar.bz2 |
vapool.c: Include tree-ssa-alias.h, gimple.h and lto-streamer.h
* vapool.c: Include tree-ssa-alias.h, gimple.h and lto-streamer.h
(varpool_get_constructor): New function.
(varpool_ctor_useable_for_folding_p): Break out from ...
(ctor_for_folding): ... here; use varpool_get_constructor.
(varpool_assemble_decl): Likewise.
* lto-streamer.h (struct output_block): Turn cgraph_node
to symbol filed.
(lto_input_variable_constructor): Declare.
* ipa-visibility.c (function_and_variable_visibility): Use
varpool_get_constructor.
* cgraph.h (varpool_get_constructor): Declare.
(varpool_ctor_useable_for_folding_p): New function.
* lto-streamer-out.c (get_symbol_initial_value): Take encoder
parameter; return error_mark_node for non-trivial constructors.
(lto_write_tree_1, DFS_write_tree): UPdate use of
get_symbol_initial_value.
(output_function): Update initialization of symbol.
(output_constructor): New function.
(copy_function): Rename to ..
(copy_function_or_variable): ... this one; handle vars too.
(lto_output): Output variable sections.
* lto-streamer-in.c (input_constructor): New function.
(lto_read_body): Rename from ...
(lto_read_body_or_constructor): ... this one; handle vars
too.
(lto_input_variable_constructor): New function.
* ipa-prop.c (ipa_prop_write_jump_functions,
ipa_prop_write_all_agg_replacement): Update.
* lto-cgraph.c (compute_ltrans_boundary): Use it.
(output_cgraph_opt_summary): Set symbol to NULL.
* lto-partition.c (add_references_to_partition): Use
varpool_ctor_useable_for_folding_p.
* lto.c (lto_read_in_decl_state): Update sanity check.
From-SVN: r212467
Diffstat (limited to 'gcc/varpool.c')
-rw-r--r-- | gcc/varpool.c | 169 |
1 files changed, 117 insertions, 52 deletions
diff --git a/gcc/varpool.c b/gcc/varpool.c index 79f07bf..2b379cc 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -35,6 +35,9 @@ along with GCC; see the file COPYING3. If not see #include "gimple-expr.h" #include "flags.h" #include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "gimple.h" +#include "lto-streamer.h" const char * const tls_model_names[]={"none", "tls-emulated", "tls-real", "tls-global-dynamic", "tls-local-dynamic", @@ -163,19 +166,17 @@ varpool_node_for_decl (tree decl) void varpool_remove_node (varpool_node *node) { - tree init; varpool_call_node_removal_hooks (node); symtab_unregister_node (node); - /* Because we remove references from external functions before final compilation, - we may end up removing useful constructors. - FIXME: We probably want to trace boundaries better. */ + /* When streaming we can have multiple nodes associated with decl. */ if (cgraph_state == CGRAPH_LTO_STREAMING) ; - else if ((init = ctor_for_folding (node->decl)) == error_mark_node) + /* Keep constructor when it may be used for folding. We remove + references to external variables before final compilation. */ + else if (DECL_INITIAL (node->decl) && DECL_INITIAL (node->decl) != error_mark_node + && !varpool_ctor_useable_for_folding_p (node)) varpool_remove_initializer (node); - else - DECL_INITIAL (node->decl) = init; ggc_free (node); } @@ -215,7 +216,7 @@ dump_varpool_node (FILE *f, varpool_node *node) fprintf (f, " used-by-single-function"); if (TREE_READONLY (node->decl)) fprintf (f, " read-only"); - if (ctor_for_folding (node->decl) != error_mark_node) + if (varpool_ctor_useable_for_folding_p (node)) fprintf (f, " const-value-known"); if (node->writeonly) fprintf (f, " write-only"); @@ -253,9 +254,101 @@ varpool_node_for_asm (tree asmname) return NULL; } -/* Return if DECL is constant and its initial value is known (so we can do - constant folding using DECL_INITIAL (decl)). - Return ERROR_MARK_NODE when value is unknown. */ +/* When doing LTO, read NODE's constructor from disk if it is not already present. */ + +tree +varpool_get_constructor (struct varpool_node *node) +{ + struct lto_file_decl_data *file_data; + const char *data, *name; + size_t len; + tree decl = node->decl; + + if (DECL_INITIAL (node->decl) != error_mark_node + || !in_lto_p) + return DECL_INITIAL (node->decl); + + file_data = node->lto_file_data; + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + + /* We may have renamed the declaration, e.g., a static function. */ + name = lto_get_decl_name_mapping (file_data, name); + + data = lto_get_section_data (file_data, LTO_section_function_body, + name, &len); + if (!data) + fatal_error ("%s: section %s is missing", + file_data->file_name, + name); + + lto_input_variable_constructor (file_data, node, data); + lto_stats.num_function_bodies++; + lto_free_section_data (file_data, LTO_section_function_body, name, + data, len); + lto_free_function_in_decl_state_for_node (node); + return DECL_INITIAL (node->decl); +} + +/* Return ture if NODE has constructor that can be used for folding. */ + +bool +varpool_ctor_useable_for_folding_p (varpool_node *node) +{ + varpool_node *real_node = node; + + if (real_node->alias && real_node->definition) + real_node = varpool_variable_node (node); + + if (TREE_CODE (node->decl) == CONST_DECL + || DECL_IN_CONSTANT_POOL (node->decl)) + return true; + if (TREE_THIS_VOLATILE (node->decl)) + return false; + + /* If we do not have a constructor, we can't use it. */ + if (DECL_INITIAL (real_node->decl) == error_mark_node + && !real_node->lto_file_data) + return false; + + /* Vtables are defined by their types and must match no matter of interposition + rules. */ + if (DECL_VIRTUAL_P (node->decl)) + { + /* The C++ front end creates VAR_DECLs for vtables of typeinfo + classes not defined in the current TU so that it can refer + to them from typeinfo objects. Avoid returning NULL_TREE. */ + return DECL_INITIAL (real_node->decl) != NULL; + } + + /* Alias of readonly variable is also readonly, since the variable is stored + in readonly memory. We also accept readonly aliases of non-readonly + locations assuming that user knows what he is asking for. */ + if (!TREE_READONLY (node->decl) && !TREE_READONLY (real_node->decl)) + return false; + + /* Variables declared 'const' without an initializer + have zero as the initializer if they may not be + overridden at link or run time. */ + if (!DECL_INITIAL (real_node->decl) + && (DECL_EXTERNAL (node->decl) || decl_replaceable_p (node->decl))) + return false; + + /* Variables declared `const' with an initializer are considered + to not be overwritable with different initializer by default. + + ??? Previously we behaved so for scalar variables but not for array + accesses. */ + return true; +} + +/* If DECL is constant variable and its initial value is known (so we can + do constant folding), return its constructor (DECL_INITIAL). This may + be an expression or NULL when DECL is initialized to 0. + Return ERROR_MARK_NODE otherwise. + + In LTO this may actually trigger reading the constructor from disk. + For this reason varpool_ctor_useable_for_folding_p should be used when + the actual constructor value is not needed. */ tree ctor_for_folding (tree decl) @@ -284,7 +377,7 @@ ctor_for_folding (tree decl) gcc_assert (TREE_CODE (decl) == VAR_DECL); - node = varpool_get_node (decl); + real_node = node = varpool_get_node (decl); if (node) { real_node = varpool_variable_node (node); @@ -302,54 +395,25 @@ ctor_for_folding (tree decl) { gcc_assert (!DECL_INITIAL (decl) || DECL_INITIAL (decl) == error_mark_node); - if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) + if (node->weakref) { node = varpool_alias_target (node); decl = node->decl; } } - /* Vtables are defined by their types and must match no matter of interposition - rules. */ - if (DECL_VIRTUAL_P (real_decl)) - { - gcc_checking_assert (TREE_READONLY (real_decl)); - if (DECL_INITIAL (real_decl)) - return DECL_INITIAL (real_decl); - else - { - /* The C++ front end creates VAR_DECLs for vtables of typeinfo - classes not defined in the current TU so that it can refer - to them from typeinfo objects. Avoid returning NULL_TREE. */ - gcc_checking_assert (!COMPLETE_TYPE_P (DECL_CONTEXT (real_decl))); - return error_mark_node; - } - } - - /* If there is no constructor, we have nothing to do. */ - if (DECL_INITIAL (real_decl) == error_mark_node) - return error_mark_node; - - /* Non-readonly alias of readonly variable is also de-facto readonly, - because the variable itself is in readonly section. - We also honnor READONLY flag on alias assuming that user knows - what he is doing. */ - if (!TREE_READONLY (decl) && !TREE_READONLY (real_decl)) - return error_mark_node; - - /* Variables declared 'const' without an initializer - have zero as the initializer if they may not be - overridden at link or run time. */ - if (!DECL_INITIAL (real_decl) - && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl))) + if ((!DECL_VIRTUAL_P (real_decl) + || DECL_INITIAL (real_decl) == error_mark_node + || !DECL_INITIAL (real_decl)) + && (!node || !varpool_ctor_useable_for_folding_p (node))) return error_mark_node; - /* Variables declared `const' with an initializer are considered - to not be overwritable with different initializer by default. - - ??? Previously we behaved so for scalar variables but not for array - accesses. */ - return DECL_INITIAL (real_decl); + /* OK, we can return constructor. See if we need to fetch it from disk + in LTO mode. */ + if (DECL_INITIAL (real_decl) != error_mark_node + || !in_lto_p) + return DECL_INITIAL (real_decl); + return varpool_get_constructor (real_node); } /* Add the variable DECL to the varpool. @@ -471,6 +535,7 @@ varpool_assemble_decl (varpool_node *node) if (!node->in_other_partition && !DECL_EXTERNAL (decl)) { + varpool_get_constructor (node); assemble_variable (decl, 0, 1, 0); gcc_assert (TREE_ASM_WRITTEN (decl)); node->definition = true; |