summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-03 10:15:54 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-03 10:15:54 +0000
commit9d924a14cb3657941ca4f1406f1b710fec343aec (patch)
tree557b00c4e086e7d798393273321f3907a7d16cb4 /gcc
parentbf0e72b2492b09bb9be1c0aa55a6991dec33f374 (diff)
downloadgcc-9d924a14cb3657941ca4f1406f1b710fec343aec.tar.gz
* cgraph.h (struct varpool_node): Add const_value_known.
(varpool_decide_const_value_known): Declare. * tree-ssa-ccp.c (fold_const_aggregate_ref): Update initializer folding. * lto-cgraph.c (lto_output_varpool_node): Store const_value_known. (input_varpool_node): Restore const_value_known. * tree-ssa-loop-ivcanon (constant_after_peeling): Check varpool for initializer folding. * ipa.c (ipa_discover_readonly_nonaddressable_var, function_and_variable_visibility): Compute const_value_known. * gimple-fold.c (get_symbol_constant_value): Use varpool for initializer folding. * varpool.c (varpool_decide_const_value_known): New function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163808 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/gimple-fold.c8
-rw-r--r--gcc/ipa.c5
-rw-r--r--gcc/lto-cgraph.c2
-rw-r--r--gcc/tree-ssa-ccp.c9
-rw-r--r--gcc/tree-ssa-loop-ivcanon.c4
-rw-r--r--gcc/varpool.c31
8 files changed, 66 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bfd0889d13b..612e0205399 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2010-09-03 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.h (struct varpool_node): Add const_value_known.
+ (varpool_decide_const_value_known): Declare.
+ * tree-ssa-ccp.c (fold_const_aggregate_ref): Update initializer folding.
+ * lto-cgraph.c (lto_output_varpool_node): Store const_value_known.
+ (input_varpool_node): Restore const_value_known.
+ * tree-ssa-loop-ivcanon (constant_after_peeling): Check varpool for
+ initializer folding.
+ * ipa.c (ipa_discover_readonly_nonaddressable_var,
+ function_and_variable_visibility): Compute const_value_known.
+ * gimple-fold.c (get_symbol_constant_value): Use varpool for initializer
+ folding.
+ * varpool.c (varpool_decide_const_value_known): New function.
+
2010-09-03 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md: Remove empty prepartion statements
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index f77a280d12f..c868d329542 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -503,6 +503,8 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
During WPA output it is used to mark nodes that are present in
multiple partitions. */
unsigned in_other_partition : 1;
+ /* True when variable is constant and its value is known. */
+ unsigned int const_value_known : 1;
};
/* Every top level asm statement is put into a cgraph_asm_node. */
@@ -726,6 +728,7 @@ void varpool_empty_needed_queue (void);
bool varpool_extra_name_alias (tree, tree);
const char * varpool_node_name (struct varpool_node *node);
void varpool_reset_queue (void);
+bool varpool_decide_const_value_known (struct varpool_node *node);
/* Walk all reachable static variables. */
#define FOR_EACH_STATIC_VARIABLE(node) \
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 8a48316f00d..033023a9fa7 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -38,9 +38,9 @@ along with GCC; see the file COPYING3. If not see
tree
get_symbol_constant_value (tree sym)
{
- if (TREE_STATIC (sym)
- && (TREE_READONLY (sym)
- || TREE_CODE (sym) == CONST_DECL))
+ if ((TREE_STATIC (sym) || DECL_EXTERNAL (sym))
+ && (TREE_CODE (sym) == CONST_DECL
+ || varpool_get_node (sym)->const_value_known))
{
tree val = DECL_INITIAL (sym);
if (val)
@@ -65,8 +65,6 @@ get_symbol_constant_value (tree sym)
have zero as the initializer if they may not be
overridden at link or run time. */
if (!val
- && !DECL_EXTERNAL (sym)
- && targetm.binds_local_p (sym)
&& (INTEGRAL_TYPE_P (TREE_TYPE (sym))
|| SCALAR_FLOAT_TYPE_P (TREE_TYPE (sym))))
return fold_convert (TREE_TYPE (sym), integer_zero_node);
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 021398b6748..b199796fcdb 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -561,6 +561,7 @@ ipa_discover_readonly_nonaddressable_vars (void)
if (dump_file)
fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
TREE_READONLY (vnode->decl) = 1;
+ vnode->const_value_known |= varpool_decide_const_value_known (vnode);
}
}
if (dump_file)
@@ -767,6 +768,9 @@ function_and_variable_visibility (bool whole_program)
|| ! (ADDR_SPACE_GENERIC_P
(TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
DECL_COMMON (vnode->decl) = 0;
+ /* Even extern variables might have initializers known.
+ See, for example testsuite/g++.dg/opt/static3.C */
+ vnode->const_value_known |= varpool_decide_const_value_known (vnode);
}
for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
{
@@ -801,6 +805,7 @@ function_and_variable_visibility (bool whole_program)
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
cgraph_make_decl_local (vnode->decl);
}
+ vnode->const_value_known |= varpool_decide_const_value_known (vnode);
gcc_assert (TREE_STATIC (vnode->decl));
}
pointer_set_destroy (aliased_nodes);
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 22b49161067..dac5c321814 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -575,6 +575,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->finalized, 1);
bp_pack_value (&bp, node->alias, 1);
+ bp_pack_value (&bp, node->const_value_known, 1);
gcc_assert (!node->alias || !node->extra_name);
gcc_assert (node->finalized || !node->analyzed);
gcc_assert (node->needed);
@@ -1106,6 +1107,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->force_output = bp_unpack_value (&bp, 1);
node->finalized = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1);
+ node->const_value_known = bp_unpack_value (&bp, 1);
node->analyzed = node->finalized;
node->used_from_other_partition = bp_unpack_value (&bp, 1);
node->in_other_partition = bp_unpack_value (&bp, 1);
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 5551df2d5a3..8c42a633665 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -1348,7 +1348,8 @@ fold_const_aggregate_ref (tree t)
case VAR_DECL:
if (!TREE_READONLY (base)
|| TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
- || !targetm.binds_local_p (base))
+ || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+ && !varpool_get_node (base)->const_value_known))
return NULL_TREE;
ctor = DECL_INITIAL (base);
@@ -1435,7 +1436,8 @@ fold_const_aggregate_ref (tree t)
case VAR_DECL:
if (!TREE_READONLY (base)
|| TREE_CODE (TREE_TYPE (base)) != RECORD_TYPE
- || !targetm.binds_local_p (base))
+ || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+ && !varpool_get_node (base)->const_value_known))
return NULL_TREE;
ctor = DECL_INITIAL (base);
@@ -1509,7 +1511,8 @@ fold_const_aggregate_ref (tree t)
if (!TREE_READONLY (base)
|| TREE_CODE (TREE_TYPE (base)) != ARRAY_TYPE
- || !targetm.binds_local_p (base))
+ || ((TREE_STATIC (base) || DECL_EXTERNAL (base))
+ && !varpool_get_node (base)->const_value_known))
return NULL_TREE;
ctor = DECL_INITIAL (base);
diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c
index b0d45bc4b41..2ced3070d48 100644
--- a/gcc/tree-ssa-loop-ivcanon.c
+++ b/gcc/tree-ssa-loop-ivcanon.c
@@ -165,9 +165,7 @@ constant_after_peeling (tree op, gimple stmt, struct loop *loop)
if ((DECL_P (base)
&& TREE_STATIC (base)
&& TREE_READONLY (base)
- && (DECL_INITIAL (base)
- || (!DECL_EXTERNAL (base)
- && targetm.binds_local_p (base))))
+ && varpool_get_node (base)->const_value_known)
|| CONSTANT_CLASS_P (base))
{
/* If so, see if we understand all the indices. */
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 817a3197901..eac488fa79b 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -359,6 +359,37 @@ decide_is_variable_needed (struct varpool_node *node, tree decl)
return true;
}
+/* Return if NODE is constant and its initial value is known (so we can do
+ constant folding). The decision depends on whole program decisions
+ and can not be recomputed at ltrans stage for variables from other
+ partitions. For this reason the new value should be always combined
+ with the previous knowledge. */
+
+bool
+varpool_decide_const_value_known (struct varpool_node *node)
+{
+ tree decl = node->decl;
+
+ gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl));
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ if (!TREE_READONLY (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 (decl)
+ && (DECL_EXTERNAL (decl)
+ || DECL_REPLACEABLE_P (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;
+}
+
/* Mark DECL as finalized. By finalizing the declaration, frontend instruct the
middle end to output the variable to asm file, if needed or externally
visible. */