cgraph.h (struct varpool_node): Add const_value_known.

* 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.

From-SVN: r163808
This commit is contained in:
Jan Hubicka 2010-09-03 12:15:54 +02:00 committed by Jan Hubicka
parent cb1b497ec1
commit 155c92a7a0
8 changed files with 66 additions and 11 deletions

View File

@ -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

View File

@ -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) \

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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. */

View File

@ -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. */