> The following testcase shows that we are bad at identifying inductions
> that will be optimized away after vectorizing them because SCEV doesn't
> handle vectorized defs.  The following rolls a simpler identification
> of SSA cycles covering a PHI and an assignment with a binary operator
> with a constant second operand.
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu.
> 
> Note, I also have a more general approach (will reply to this mail
> with an RFC).

Looks good to me.  This clearly be generalized to more complicated
expressions, so that is what you plan to do next?

Honza
> 
> Any comments on this particular change?
> 
>       PR tree-optimization/110991
>       * tree-ssa-loop-ivcanon.cc (constant_after_peeling): Handle
>       VIEW_CONVERT_EXPR <op>, handle more simple IV-like SSA cycles
>       that will end up constant.
> 
>       * gcc.dg/tree-ssa/cunroll-16.c: New testcase.
> ---
>  gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c | 17 ++++++++
>  gcc/tree-ssa-loop-ivcanon.cc               | 46 +++++++++++++++++++++-
>  2 files changed, 62 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c
> 
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c
> new file mode 100644
> index 00000000000..9bb66ff8299
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cunroll-16.c
> @@ -0,0 +1,17 @@
> +/* PR/110991 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-cunroll-details -fdump-tree-optimized" } */
> +
> +static unsigned char a;
> +static signed char b;
> +void foo(void);
> +int main() {
> +  a = 25;
> +  for (; a > 13; --a)
> +    b = a > 127 ?: a << 3;
> +  if (!b)
> +    foo();
> +}
> +
> +/* { dg-final { scan-tree-dump "optimized: loop with \[0-9\]\+ iterations 
> completely unrolled" "cunroll" } } */
> +/* { dg-final { scan-tree-dump-not "foo" "optimized" } } */
> diff --git a/gcc/tree-ssa-loop-ivcanon.cc b/gcc/tree-ssa-loop-ivcanon.cc
> index a895e8e65be..99e50ee2efe 100644
> --- a/gcc/tree-ssa-loop-ivcanon.cc
> +++ b/gcc/tree-ssa-loop-ivcanon.cc
> @@ -166,6 +166,11 @@ constant_after_peeling (tree op, gimple *stmt, class 
> loop *loop)
>    if (CONSTANT_CLASS_P (op))
>      return true;
>  
> +  /* Get at the actual SSA operand.  */
> +  if (handled_component_p (op)
> +      && TREE_CODE (TREE_OPERAND (op, 0)) == SSA_NAME)
> +    op = TREE_OPERAND (op, 0);
> +
>    /* We can still fold accesses to constant arrays when index is known.  */
>    if (TREE_CODE (op) != SSA_NAME)
>      {
> @@ -198,7 +203,46 @@ constant_after_peeling (tree op, gimple *stmt, class 
> loop *loop)
>    tree ev = analyze_scalar_evolution (loop, op);
>    if (chrec_contains_undetermined (ev)
>        || chrec_contains_symbols (ev))
> -    return false;
> +    {
> +      if (ANY_INTEGRAL_TYPE_P (TREE_TYPE (op)))
> +     {
> +       gassign *ass = nullptr;
> +       gphi *phi = nullptr;
> +       if (is_a <gassign *> (SSA_NAME_DEF_STMT (op)))
> +         {
> +           ass = as_a <gassign *> (SSA_NAME_DEF_STMT (op));
> +           if (TREE_CODE (gimple_assign_rhs1 (ass)) == SSA_NAME)
> +             phi = dyn_cast <gphi *>
> +                     (SSA_NAME_DEF_STMT (gimple_assign_rhs1  (ass)));
> +         }
> +       else if (is_a <gphi *> (SSA_NAME_DEF_STMT (op)))
> +         {
> +           phi = as_a <gphi *> (SSA_NAME_DEF_STMT (op));
> +           if (gimple_bb (phi) == loop->header)
> +             {
> +               tree def = gimple_phi_arg_def_from_edge
> +                 (phi, loop_latch_edge (loop));
> +               if (TREE_CODE (def) == SSA_NAME
> +                   && is_a <gassign *> (SSA_NAME_DEF_STMT (def)))
> +                 ass = as_a <gassign *> (SSA_NAME_DEF_STMT (def));
> +             }
> +         }
> +       if (ass && phi)
> +         {
> +           tree rhs1 = gimple_assign_rhs1 (ass);
> +           if (gimple_assign_rhs_class (ass) == GIMPLE_BINARY_RHS
> +               && CONSTANT_CLASS_P (gimple_assign_rhs2 (ass))
> +               && rhs1 == gimple_phi_result (phi)
> +               && gimple_bb (phi) == loop->header
> +               && (gimple_phi_arg_def_from_edge (phi, loop_latch_edge (loop))
> +                   == gimple_assign_lhs (ass))
> +               && (CONSTANT_CLASS_P (gimple_phi_arg_def_from_edge
> +                                      (phi, loop_preheader_edge (loop)))))
> +             return true;
> +         }
> +     }
> +      return false;
> +    }
>    return true;
>  }
>  
> -- 
> 2.35.3

Reply via email to