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:
parent
d3d3011f93
commit
e8114fbacc
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" } } */
|
||||
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue