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).

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