> 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