[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