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:
parent
cb1b497ec1
commit
155c92a7a0
8 changed files with 66 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue