[PATCH][alias-improvements] Fix CCP regressions, fix PR38180
Richard Guenther
richard.guenther@gmail.com
Sat Mar 28 13:13:00 GMT 2009
On Wed, Nov 26, 2008 at 1:25 PM, Richard Guenther <rguenther@suse.de> wrote:
>
> This fixes the CCP regressions on the alias-improvements branch which
> were because the VOP related checks in CCP are done wrong, so with
> VOPs enabled during early optimization we miss some propagations
> (and we did so on the trunk for later passes). I took the opportunity
> to also fix PR38180 on the way.
>
> Bootstrapped and tested on x86_64-unknown-linux-gnu, installed on the
> branch. The remaining ssa-ccp-2.c pieces that fail are FRE related.
Merged to trunk as rev. 145184 after re-bootstrapping and testing there.
Richard.
> Richard.
>
> 2008-11-26 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.
>
> Index: alias-improvements/gcc/tree-ssa-ccp.c
> ===================================================================
> *** alias-improvements.orig/gcc/tree-ssa-ccp.c 2008-11-25 21:28:30.000000000 +0100
> --- alias-improvements/gcc/tree-ssa-ccp.c 2008-11-26 12:05:41.000000000 +0100
> *************** get_default_value (tree var)
> *** 318,369 ****
> {
> 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)
> {
> ! /* Globals and static variables declared 'const' take their
> ! initial value. */
> ! val.lattice_val = CONSTANT;
> ! val.value = cst_val;
> }
> ! 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;
> ! }
> }
>
> return val;
> --- 318,362 ----
> {
> tree sym = SSA_NAME_VAR (var);
> prop_value_t val = { UNINITIALIZED, NULL_TREE };
> ! gimple stmt;
> !
> ! 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)
> ! {
> ! 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
> ! {
> ! /* Otherwise, VAR will never take on a constant value. */
> ! val.lattice_val = VARYING;
> }
>
> return val;
> *************** likely_value (gimple stmt)
> *** 499,504 ****
> --- 492,498 ----
> 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);
>
> *************** likely_value (gimple stmt)
> *** 514,546 ****
> 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)
> {
> prop_value_t *val = get_value (use);
>
> --- 508,518 ----
> if (gimple_has_volatile_ops (stmt))
> return VARYING;
>
> /* 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)
> {
> prop_value_t *val = get_value (use);
>
> *************** likely_value (gimple stmt)
> *** 553,558 ****
> --- 525,541 ----
> 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. */
> *************** likely_value (gimple stmt)
> *** 583,593 ****
> if (has_undefined_operand)
> return VARYING;
>
> 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))
> return CONSTANT;
>
> return VARYING;
> --- 566,576 ----
> 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
> ! || gimple_references_memory_p (stmt))
> return CONSTANT;
>
> return VARYING;
> *************** surely_varying_stmt_p (gimple stmt)
> *** 603,611 ****
> 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))
> --- 586,591 ----
> *************** surely_varying_stmt_p (gimple stmt)
> *** 617,622 ****
> --- 597,606 ----
> 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
> *************** ccp_initialize (void)
> *** 655,664 ****
> /* 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);
> ! }
> }
> prop_set_simulate_again (stmt, !is_varying);
> }
> --- 639,645 ----
> /* 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)
> ! set_value_varying (def);
> }
> prop_set_simulate_again (stmt, !is_varying);
> }
> *************** ccp_fold (gimple stmt)
> *** 947,952 ****
> --- 928,943 ----
> 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)
> *************** fold_const_aggregate_ref (tree t)
> *** 1151,1156 ****
> --- 1142,1150 ----
> 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:
> Index: alias-improvements/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c
> ===================================================================
> *** /dev/null 1970-01-01 00:00:00.000000000 +0000
> --- alias-improvements/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c 2008-11-26 12:10:38.000000000 +0100
> ***************
> *** 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" } } */
> +
>
More information about the Gcc-patches
mailing list