From 8edeb88bb61fcfb4c20ce37f15946286cc8558fc Mon Sep 17 00:00:00 2001 From: rguenth Date: Sat, 28 Mar 2009 12:52:13 +0000 Subject: [PATCH] 2009-03-28 Richard Guenther 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145184 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 10 ++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c | 23 +++++ gcc/tree-ssa-ccp.c | 144 ++++++++++++++--------------- 4 files changed, 107 insertions(+), 75 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f6adff6..4b746cd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2009-03-28 Richard Guenther + + 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 * cgraph.c (dump_cgraph_node): Add replace output flag by process. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1cc8e4f..a2e329e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,10 @@ 2009-03-28 Richard Guenther + PR tree-optimization/38180 + * gcc.dg/tree-ssa/ssa-ccp-24.c: New testcase. + +2009-03-28 Richard Guenther + PR tree-optimization/38513 * gcc.dg/tree-ssa/ssa-fre-21.c: New testcase. * gcc.dg/tree-ssa/ssa-dse-11.c: Adjust. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c new file mode 100644 index 0000000..84f69e9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c @@ -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" } } */ + diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 5080cc3..26b6722 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -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)) - { - /* Short circuit for regular CCP. We are not interested in any - non-register when DO_STORE_CCP is false. */ - val.lattice_val = VARYING; - } - else if ((cst_val = get_symbol_constant_value (sym)) != NULL_TREE) + gimple stmt; + + stmt = SSA_NAME_DEF_STMT (var); + + if (gimple_nop_p (stmt)) { - /* Globals and static variables declared 'const' take their - initial value. */ - val.lattice_val = CONSTANT; - val.value = cst_val; + /* 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 - { - gimple stmt = SSA_NAME_DEF_STMT (var); - - if (gimple_nop_p (stmt)) + 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) + { + 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 - 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; + val.lattice_val = CONSTANT; + val.value = cst; } else - { - /* Otherwise, VAR will never take on a constant value. */ - val.lattice_val = VARYING; - } + /* 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; } 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: -- 2.7.4