aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2025-08-29 12:15:09 +0200
committerRichard Biener <rguenth@gcc.gnu.org>2025-09-04 10:14:26 +0200
commitcba74d2cde528af210e37a06652493b2ca38079c (patch)
treee5fa40e42e19eac3fb24c2867057a48136476356 /gcc
parent95afbe4c7633459b59d434550888decc41b4d44f (diff)
downloadgcc-cba74d2cde528af210e37a06652493b2ca38079c.zip
gcc-cba74d2cde528af210e37a06652493b2ca38079c.tar.gz
gcc-cba74d2cde528af210e37a06652493b2ca38079c.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-pr61247.c17
-rw-r--r--gcc/tree-scalar-evolution.cc32
2 files changed, 48 insertions, 1 deletions
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 0000000..96270c1
--- /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 3b3748a..ecdef75 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);