aboutsummaryrefslogtreecommitdiff
path: root/gcc/varpool.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-07-11 19:43:44 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2014-07-11 17:43:44 +0000
commit0b83e6882437a80458a7435cf434fbdccb37fa60 (patch)
tree559538902f5da455d349414895289f88f3911435 /gcc/varpool.c
parent01a92e704282e69fc3ec7d817637b8074454168d (diff)
downloadgcc-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.c169
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;