aboutsummaryrefslogtreecommitdiff
path: root/gcc/varpool.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-06-19 20:06:12 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2013-06-19 18:06:12 +0000
commit6a6dac5293ee21d9aed0d394a0cb23948bb1efad (patch)
tree1d4237222ae0ad0d8207eb6ee9f94b244ffae6e5 /gcc/varpool.c
parent216c12abf6eccbcf5c5ff1898e8b063a494af40c (diff)
downloadgcc-6a6dac5293ee21d9aed0d394a0cb23948bb1efad.zip
gcc-6a6dac5293ee21d9aed0d394a0cb23948bb1efad.tar.gz
gcc-6a6dac5293ee21d9aed0d394a0cb23948bb1efad.tar.bz2
cgraph.h (const_value_known_p): Replace by ...
* cgraph.h (const_value_known_p): Replace by ... (ctor_for_folding): .. this one. * cgraphunit.c (process_function_and_variable_attributes): Use it. * lto-cgraph.c (compute_ltrans_boundary): Use ctor_for_folding. * expr.c (expand_expr_real_1): Likewise. (string_constant): Likewise. * tree-ssa-loop-ivcanon.c (constant_after_peeling): Likewise. * ipa.c (process_references): Likewise. (symtab_remove_unreachable_nodes): Likewise. * ipa-inline-analysis.c (param_change_prob): Likewise. * gimple-fold.c (canonicalize_constructor_val): Likewise. (get_base_constructor): Likwise. * varpool.c (varpool_remove_node): Likewise. (varpool_remove_initializer): LIkewise. (dump_varpool_node): LIkwise. (const_value_known_p): Rewrite to ... (ctor_for_folding): ... this one. * lto-partition.c (add_references_to_partition): Use ctor_for_folding. * gcc.dg/tree-ssa/attr-alias-2.c: New testcase. From-SVN: r200211
Diffstat (limited to 'gcc/varpool.c')
-rw-r--r--gcc/varpool.c90
1 files changed, 71 insertions, 19 deletions
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 80e98b3..b426757 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -66,12 +66,15 @@ void
varpool_remove_node (struct varpool_node *node)
{
symtab_unregister_node ((symtab_node)node);
+ tree init;
/* 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. */
- if (!const_value_known_p (node->symbol.decl))
+ if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node)
varpool_remove_initializer (node);
+ else
+ DECL_INITIAL (node->symbol.decl) = init;
ggc_free (node);
}
@@ -109,7 +112,7 @@ dump_varpool_node (FILE *f, struct varpool_node *node)
fprintf (f, " output");
if (TREE_READONLY (node->symbol.decl))
fprintf (f, " read-only");
- if (const_value_known_p (node->symbol.decl))
+ if (ctor_for_folding (node->symbol.decl) != error_mark_node)
fprintf (f, " const-value-known");
fprintf (f, "\n");
}
@@ -144,44 +147,93 @@ varpool_node_for_asm (tree asmname)
}
/* Return if DECL is constant and its initial value is known (so we can do
- constant folding using DECL_INITIAL (decl)). */
+ constant folding using DECL_INITIAL (decl)).
+ Return ERROR_MARK_NODE when value is unknown. */
-bool
-const_value_known_p (tree decl)
+tree
+ctor_for_folding (tree decl)
{
+ struct varpool_node *node, *real_node;
+ tree real_decl;
+
if (TREE_CODE (decl) != VAR_DECL
- &&TREE_CODE (decl) != CONST_DECL)
- return false;
+ && TREE_CODE (decl) != CONST_DECL)
+ return error_mark_node;
if (TREE_CODE (decl) == CONST_DECL
|| DECL_IN_CONSTANT_POOL (decl))
- return true;
+ return DECL_INITIAL (decl);
+
+ if (TREE_THIS_VOLATILE (decl))
+ return error_mark_node;
+
+ /* Do not care about automatic variables. Those are never initialized
+ anyway, because gimplifier exapnds the code*/
+ if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+ {
+ gcc_assert (!TREE_PUBLIC (decl));
+ return error_mark_node;
+ }
gcc_assert (TREE_CODE (decl) == VAR_DECL);
- if (!TREE_READONLY (decl) || TREE_THIS_VOLATILE (decl))
- return false;
+ node = varpool_get_node (decl);
+ if (node)
+ {
+ real_node = varpool_variable_node (node);
+ real_decl = real_node->symbol.decl;
+ }
+ else
+ real_decl = decl;
+
+ /* See if we are dealing with alias.
+ In most cases alias is just alternative symbol pointing to a given
+ constructor. This allows us to use interposition rules of DECL
+ constructor of REAL_NODE. However weakrefs are special by being just
+ alternative name of their target (if defined). */
+ if (decl != real_decl)
+ {
+ gcc_assert (!DECL_INITIAL (decl)
+ || DECL_INITIAL (decl) == error_mark_node);
+ if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+ {
+ node = varpool_alias_target (node);
+ decl = node->symbol.decl;
+ }
+ }
- /* Gimplifier takes away constructors of local vars */
- if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
- return DECL_INITIAL (decl) != NULL;
+ /* 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));
+ return DECL_INITIAL (real_decl);
+ }
+
+ /* If thre is no constructor, we have nothing to do. */
+ if (DECL_INITIAL (real_decl) == error_mark_node)
+ return error_mark_node;
- gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
+ /* 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 (decl)
- && (DECL_EXTERNAL (decl)
- || decl_replaceable_p (decl)))
- return false;
+ if (!DECL_INITIAL (real_decl)
+ && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
+ 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 true;
+ return DECL_INITIAL (real_decl);
}
/* Add the variable DECL to the varpool.