https://gcc.gnu.org/g:cba74d2cde528af210e37a06652493b2ca38079c

commit r16-3562-gcba74d2cde528af210e37a06652493b2ca38079c
Author: Richard Biener <rguent...@suse.de>
Date:   Fri Aug 29 12:15:09 2025 +0200

    tree-optimization/61247 - handle peeled converted IV in SCEV
    
    The following handles SCEV analysis of a peeled converted IV if
    that IV is known to not overflow.  For
    
      # _15 = PHI <_4(6), 0(5)>
      # i_18 = PHI <i_11(6), 0(5)>
      i_11 = i_18 + 1;
      _4 = (long unsigned int) i_11;
    
    we cannot analyze _15 directly since the SCC has a widening
    conversion.  But we can analyze _4 to (long unsigned int) {1, +, 1}_1
    which is "peeled" (it's from after the first iteration of _15).
    If the un-peeled IV {0, +, 1}_1 has the same initial value as _15
    and it does not overflow then _15 can be analyzed as
    {0ul, +, 1ul}_1.
    
    The following implements this in simplify_peeled_chrec.
    
            PR tree-optimization/61247
            * tree-scalar-evolution.cc (simplify_peeled_chrec):
            Handle the case of a converted peeled chrec.
    
            * gcc.dg/vect/vect-pr61247.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/vect/vect-pr61247.c | 17 +++++++++++++++++
 gcc/tree-scalar-evolution.cc             | 32 +++++++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr61247.c 
b/gcc/testsuite/gcc.dg/vect/vect-pr61247.c
new file mode 100644
index 000000000000..96270c1cd415
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr61247.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+#include <stddef.h>
+
+int foo (int *p, size_t sz)
+{
+  int sum = 0;
+  for (unsigned i = 0; i < sz; ++i)
+    sum += p[i];
+  return sum;
+}
+
+/* The possibly wrapping IV together header copying confused SCEV
+   enough to fail vectorization even when versioning with niter
+   assumptions.  */
+/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" } } */
diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc
index 3b3748aba67f..ecdef7529a63 100644
--- a/gcc/tree-scalar-evolution.cc
+++ b/gcc/tree-scalar-evolution.cc
@@ -1354,7 +1354,37 @@ simplify_peeled_chrec (class loop *loop, tree arg, tree 
init_cond)
   hash_map<tree, name_expansion *> *peeled_chrec_map = NULL;
 
   ev = instantiate_parameters (loop, analyze_scalar_evolution (loop, arg));
-  if (ev == NULL_TREE || TREE_CODE (ev) != POLYNOMIAL_CHREC)
+  if (ev == NULL_TREE)
+    return chrec_dont_know;
+
+  /* Support the case where we can derive the original CHREC from the
+     peeled one if that's a converted other IV.  This can be done
+     when the original unpeeled converted IV does not overflow and
+     has the same initial value.  */
+  if (CONVERT_EXPR_P (ev)
+      && TREE_CODE (init_cond) == INTEGER_CST
+      && TREE_CODE (TREE_OPERAND (ev, 0)) == POLYNOMIAL_CHREC
+      && (TYPE_PRECISION (TREE_TYPE (ev))
+         > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (ev, 0))))
+      && (!TYPE_UNSIGNED (TREE_TYPE (ev))
+         || TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (ev, 0)))))
+    {
+      left = CHREC_LEFT (TREE_OPERAND (ev, 0));
+      right = CHREC_RIGHT (TREE_OPERAND (ev, 0));
+      tree left_before = chrec_fold_minus (TREE_TYPE (TREE_OPERAND (ev, 0)),
+                                          left, right);
+      if (TREE_CODE (left_before) == INTEGER_CST
+         && wi::to_widest (init_cond) == wi::to_widest (left_before)
+         && !scev_probably_wraps_p (NULL_TREE, left_before, right, NULL,
+                                    loop, false))
+       return build_polynomial_chrec (loop->num, init_cond,
+                                      chrec_convert (TREE_TYPE (ev),
+                                                     right, NULL,
+                                                     false, NULL_TREE));
+      return chrec_dont_know;
+    }
+
+  if (TREE_CODE (ev) != POLYNOMIAL_CHREC)
     return chrec_dont_know;
 
   left = CHREC_LEFT (ev);

Reply via email to