re PR tree-optimization/38180 (CCP does not propagate through constant initializers)

2009-03-28  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/38180
	* tree-ssa-ccp.c (get_default_value): Simplify.
	(likely_value): Likewise.
	(surely_varying_stmt_p): Properly handle VOP case.
	(ccp_initialize): Likewise.
	(ccp_fold): Handle propagating through *&.
	(fold_const_aggregate_ref): Also handle decls.

	* gcc.dg/tree-ssa/ssa-ccp-24.c: New testcase.

From-SVN: r145184
This commit is contained in:
Richard Guenther 2009-03-28 12:52:13 +00:00 committed by Richard Biener
parent d3d3011f93
commit e8114fbacc
4 changed files with 106 additions and 74 deletions

View File

@ -1,3 +1,13 @@
2009-03-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38180
* tree-ssa-ccp.c (get_default_value): Simplify.
(likely_value): Likewise.
(surely_varying_stmt_p): Properly handle VOP case.
(ccp_initialize): Likewise.
(ccp_fold): Handle propagating through *&.
(fold_const_aggregate_ref): Also handle decls.
2009-03-28 Jan Hubicka <jh@suse.cz>
* cgraph.c (dump_cgraph_node): Add replace output flag by process.

View File

@ -1,3 +1,8 @@
2009-03-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38180
* gcc.dg/tree-ssa/ssa-ccp-24.c: New testcase.
2009-03-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/38513

View File

@ -0,0 +1,23 @@
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-ccp1" } */
static const int x;
int foo()
{
const int *p = &x;
int y = *p;
return y + 1;
}
static const int x2[3] = { 1, 0, 2 };
int bar()
{
int i = 1;
const int *p = &x2[i];
int y = *p;
return y + 1;
}
/* { dg-final { scan-tree-dump-times "return 1;" 2 "ccp1" } } */
/* { dg-final { cleanup-tree-dump "ccp1" } } */

View File

@ -320,52 +320,45 @@ get_default_value (tree var)
{
tree sym = SSA_NAME_VAR (var);
prop_value_t val = { UNINITIALIZED, NULL_TREE };
tree cst_val;
if (!is_gimple_reg (var))
gimple stmt;
stmt = SSA_NAME_DEF_STMT (var);
if (gimple_nop_p (stmt))
{
/* Short circuit for regular CCP. We are not interested in any
non-register when DO_STORE_CCP is false. */
val.lattice_val = VARYING;
/* Variables defined by an empty statement are those used
before being initialized. If VAR is a local variable, we
can assume initially that it is UNDEFINED, otherwise we must
consider it VARYING. */
if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
val.lattice_val = UNDEFINED;
else
val.lattice_val = VARYING;
}
else if ((cst_val = get_symbol_constant_value (sym)) != NULL_TREE)
else if (is_gimple_assign (stmt)
/* Value-returning GIMPLE_CALL statements assign to
a variable, and are treated similarly to GIMPLE_ASSIGN. */
|| (is_gimple_call (stmt)
&& gimple_call_lhs (stmt) != NULL_TREE)
|| gimple_code (stmt) == GIMPLE_PHI)
{
/* Globals and static variables declared 'const' take their
initial value. */
val.lattice_val = CONSTANT;
val.value = cst_val;
tree cst;
if (gimple_assign_single_p (stmt)
&& DECL_P (gimple_assign_rhs1 (stmt))
&& (cst = get_symbol_constant_value (gimple_assign_rhs1 (stmt))))
{
val.lattice_val = CONSTANT;
val.value = cst;
}
else
/* Any other variable defined by an assignment or a PHI node
is considered UNDEFINED. */
val.lattice_val = UNDEFINED;
}
else
{
gimple stmt = SSA_NAME_DEF_STMT (var);
if (gimple_nop_p (stmt))
{
/* Variables defined by an empty statement are those used
before being initialized. If VAR is a local variable, we
can assume initially that it is UNDEFINED, otherwise we must
consider it VARYING. */
if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
val.lattice_val = UNDEFINED;
else
val.lattice_val = VARYING;
}
else if (is_gimple_assign (stmt)
/* Value-returning GIMPLE_CALL statements assign to
a variable, and are treated similarly to GIMPLE_ASSIGN. */
|| (is_gimple_call (stmt)
&& gimple_call_lhs (stmt) != NULL_TREE)
|| gimple_code (stmt) == GIMPLE_PHI)
{
/* Any other variable defined by an assignment or a PHI node
is considered UNDEFINED. */
val.lattice_val = UNDEFINED;
}
else
{
/* Otherwise, VAR will never take on a constant value. */
val.lattice_val = VARYING;
}
/* Otherwise, VAR will never take on a constant value. */
val.lattice_val = VARYING;
}
return val;
@ -501,6 +494,7 @@ likely_value (gimple stmt)
bool has_constant_operand, has_undefined_operand, all_undefined_operands;
tree use;
ssa_op_iter iter;
unsigned i;
enum gimple_code code = gimple_code (stmt);
@ -516,33 +510,11 @@ likely_value (gimple stmt)
if (gimple_has_volatile_ops (stmt))
return VARYING;
/* If we are not doing store-ccp, statements with loads
and/or stores will never fold into a constant. */
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return VARYING;
/* Note that only a GIMPLE_SINGLE_RHS assignment can satisfy
is_gimple_min_invariant, so we do not consider calls or
other forms of assignment. */
if (gimple_assign_single_p (stmt)
&& is_gimple_min_invariant (gimple_assign_rhs1 (stmt)))
return CONSTANT;
if (code == GIMPLE_COND
&& is_gimple_min_invariant (gimple_cond_lhs (stmt))
&& is_gimple_min_invariant (gimple_cond_rhs (stmt)))
return CONSTANT;
if (code == GIMPLE_SWITCH
&& is_gimple_min_invariant (gimple_switch_index (stmt)))
return CONSTANT;
/* Arrive here for more complex cases. */
has_constant_operand = false;
has_undefined_operand = false;
all_undefined_operands = true;
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
prop_value_t *val = get_value (use);
@ -555,6 +527,17 @@ likely_value (gimple stmt)
has_constant_operand = true;
}
/* There may be constants in regular rhs operands. */
for (i = is_gimple_call (stmt) + gimple_has_lhs (stmt);
i < gimple_num_ops (stmt); ++i)
{
tree op = gimple_op (stmt, i);
if (!op || TREE_CODE (op) == SSA_NAME)
continue;
if (is_gimple_min_invariant (op))
has_constant_operand = true;
}
/* If the operation combines operands like COMPLEX_EXPR make sure to
not mark the result UNDEFINED if only one part of the result is
undefined. */
@ -585,11 +568,11 @@ likely_value (gimple stmt)
if (has_undefined_operand)
return VARYING;
/* We do not consider virtual operands here -- load from read-only
memory may have only VARYING virtual operands, but still be
constant. */
if (has_constant_operand
/* We do not consider virtual operands here -- load from read-only
memory may have only VARYING virtual operands, but still be
constant. */
|| ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
|| gimple_references_memory_p (stmt))
return CONSTANT;
return VARYING;
@ -605,9 +588,6 @@ surely_varying_stmt_p (gimple stmt)
if (gimple_has_volatile_ops (stmt))
return true;
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return true;
/* If it is a call and does not return a value or is not a
builtin and not an indirect call, it is varying. */
if (is_gimple_call (stmt))
@ -619,6 +599,10 @@ surely_varying_stmt_p (gimple stmt)
return true;
}
/* Any other store operation is not interesting. */
else if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
return true;
/* Anything other than assignments and conditional jumps are not
interesting for CCP. */
if (gimple_code (stmt) != GIMPLE_ASSIGN
@ -657,10 +641,7 @@ ccp_initialize (void)
/* If the statement will not produce a constant, mark
all its outputs VARYING. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
{
if (is_varying)
set_value_varying (def);
}
set_value_varying (def);
}
prop_set_simulate_again (stmt, !is_varying);
}
@ -953,6 +934,16 @@ ccp_fold (gimple stmt)
return fold_unary (VIEW_CONVERT_EXPR,
TREE_TYPE (rhs), val->value);
}
else if (TREE_CODE (rhs) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME)
{
prop_value_t *val = get_value (TREE_OPERAND (rhs, 0));
if (val->lattice_val == CONSTANT
&& TREE_CODE (val->value) == ADDR_EXPR
&& useless_type_conversion_p (TREE_TYPE (rhs),
TREE_TYPE (TREE_TYPE (val->value))))
rhs = TREE_OPERAND (val->value, 0);
}
return fold_const_aggregate_ref (rhs);
}
else if (kind == tcc_declaration)
@ -1144,6 +1135,9 @@ fold_const_aggregate_ref (tree t)
unsigned HOST_WIDE_INT cnt;
tree cfield, cval;
if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
return get_symbol_constant_value (t);
switch (TREE_CODE (t))
{
case ARRAY_REF: