Commit e8114fba by Richard Guenther Committed by Richard Biener

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
parent d3d3011f
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> 2009-03-28 Jan Hubicka <jh@suse.cz>
* cgraph.c (dump_cgraph_node): Add replace output flag by process. * cgraph.c (dump_cgraph_node): Add replace output flag by process.
......
2009-03-28 Richard Guenther <rguenther@suse.de> 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 PR tree-optimization/38513
* gcc.dg/tree-ssa/ssa-fre-21.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-21.c: New testcase.
* gcc.dg/tree-ssa/ssa-dse-11.c: Adjust. * gcc.dg/tree-ssa/ssa-dse-11.c: Adjust.
......
/* { 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" } } */
...@@ -320,52 +320,45 @@ get_default_value (tree var) ...@@ -320,52 +320,45 @@ get_default_value (tree var)
{ {
tree sym = SSA_NAME_VAR (var); tree sym = SSA_NAME_VAR (var);
prop_value_t val = { UNINITIALIZED, NULL_TREE }; prop_value_t val = { UNINITIALIZED, NULL_TREE };
tree cst_val; gimple stmt;
if (!is_gimple_reg (var)) stmt = SSA_NAME_DEF_STMT (var);
{
/* Short circuit for regular CCP. We are not interested in any if (gimple_nop_p (stmt))
non-register when DO_STORE_CCP is false. */
val.lattice_val = VARYING;
}
else if ((cst_val = get_symbol_constant_value (sym)) != NULL_TREE)
{ {
/* Globals and static variables declared 'const' take their /* Variables defined by an empty statement are those used
initial value. */ before being initialized. If VAR is a local variable, we
val.lattice_val = CONSTANT; can assume initially that it is UNDEFINED, otherwise we must
val.value = cst_val; consider it VARYING. */
if (is_gimple_reg (sym) && TREE_CODE (sym) != PARM_DECL)
val.lattice_val = UNDEFINED;
else
val.lattice_val = VARYING;
} }
else else if (is_gimple_assign (stmt)
{ /* Value-returning GIMPLE_CALL statements assign to
gimple stmt = SSA_NAME_DEF_STMT (var); a variable, and are treated similarly to GIMPLE_ASSIGN. */
|| (is_gimple_call (stmt)
if (gimple_nop_p (stmt)) && gimple_call_lhs (stmt) != NULL_TREE)
|| gimple_code (stmt) == GIMPLE_PHI)
{
tree cst;
if (gimple_assign_single_p (stmt)
&& DECL_P (gimple_assign_rhs1 (stmt))
&& (cst = get_symbol_constant_value (gimple_assign_rhs1 (stmt))))
{ {
/* Variables defined by an empty statement are those used val.lattice_val = CONSTANT;
before being initialized. If VAR is a local variable, we val.value = cst;
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 else
{ /* Any other variable defined by an assignment or a PHI node
/* Otherwise, VAR will never take on a constant value. */ is considered UNDEFINED. */
val.lattice_val = VARYING; val.lattice_val = UNDEFINED;
} }
else
{
/* Otherwise, VAR will never take on a constant value. */
val.lattice_val = VARYING;
} }
return val; return val;
...@@ -501,6 +494,7 @@ likely_value (gimple stmt) ...@@ -501,6 +494,7 @@ likely_value (gimple stmt)
bool has_constant_operand, has_undefined_operand, all_undefined_operands; bool has_constant_operand, has_undefined_operand, all_undefined_operands;
tree use; tree use;
ssa_op_iter iter; ssa_op_iter iter;
unsigned i;
enum gimple_code code = gimple_code (stmt); enum gimple_code code = gimple_code (stmt);
...@@ -516,33 +510,11 @@ likely_value (gimple stmt) ...@@ -516,33 +510,11 @@ likely_value (gimple stmt)
if (gimple_has_volatile_ops (stmt)) if (gimple_has_volatile_ops (stmt))
return VARYING; 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. */ /* Arrive here for more complex cases. */
has_constant_operand = false; has_constant_operand = false;
has_undefined_operand = false; has_undefined_operand = false;
all_undefined_operands = true; 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); prop_value_t *val = get_value (use);
...@@ -555,6 +527,17 @@ likely_value (gimple stmt) ...@@ -555,6 +527,17 @@ likely_value (gimple stmt)
has_constant_operand = true; 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 /* If the operation combines operands like COMPLEX_EXPR make sure to
not mark the result UNDEFINED if only one part of the result is not mark the result UNDEFINED if only one part of the result is
undefined. */ undefined. */
...@@ -585,11 +568,11 @@ likely_value (gimple stmt) ...@@ -585,11 +568,11 @@ likely_value (gimple stmt)
if (has_undefined_operand) if (has_undefined_operand)
return VARYING; 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 if (has_constant_operand
/* We do not consider virtual operands here -- load from read-only || gimple_references_memory_p (stmt))
memory may have only VARYING virtual operands, but still be
constant. */
|| ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
return CONSTANT; return CONSTANT;
return VARYING; return VARYING;
...@@ -605,9 +588,6 @@ surely_varying_stmt_p (gimple stmt) ...@@ -605,9 +588,6 @@ surely_varying_stmt_p (gimple stmt)
if (gimple_has_volatile_ops (stmt)) if (gimple_has_volatile_ops (stmt))
return true; 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 /* If it is a call and does not return a value or is not a
builtin and not an indirect call, it is varying. */ builtin and not an indirect call, it is varying. */
if (is_gimple_call (stmt)) if (is_gimple_call (stmt))
...@@ -619,6 +599,10 @@ surely_varying_stmt_p (gimple stmt) ...@@ -619,6 +599,10 @@ surely_varying_stmt_p (gimple stmt)
return true; 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 /* Anything other than assignments and conditional jumps are not
interesting for CCP. */ interesting for CCP. */
if (gimple_code (stmt) != GIMPLE_ASSIGN if (gimple_code (stmt) != GIMPLE_ASSIGN
...@@ -657,10 +641,7 @@ ccp_initialize (void) ...@@ -657,10 +641,7 @@ ccp_initialize (void)
/* If the statement will not produce a constant, mark /* If the statement will not produce a constant, mark
all its outputs VARYING. */ all its outputs VARYING. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS) FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
{ set_value_varying (def);
if (is_varying)
set_value_varying (def);
}
} }
prop_set_simulate_again (stmt, !is_varying); prop_set_simulate_again (stmt, !is_varying);
} }
...@@ -953,6 +934,16 @@ ccp_fold (gimple stmt) ...@@ -953,6 +934,16 @@ ccp_fold (gimple stmt)
return fold_unary (VIEW_CONVERT_EXPR, return fold_unary (VIEW_CONVERT_EXPR,
TREE_TYPE (rhs), val->value); 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); return fold_const_aggregate_ref (rhs);
} }
else if (kind == tcc_declaration) else if (kind == tcc_declaration)
...@@ -1144,6 +1135,9 @@ fold_const_aggregate_ref (tree t) ...@@ -1144,6 +1135,9 @@ fold_const_aggregate_ref (tree t)
unsigned HOST_WIDE_INT cnt; unsigned HOST_WIDE_INT cnt;
tree cfield, cval; tree cfield, cval;
if (TREE_CODE_CLASS (TREE_CODE (t)) == tcc_declaration)
return get_symbol_constant_value (t);
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case ARRAY_REF: case ARRAY_REF:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment