diff options
author | Richard Biener <rguenther@suse.de> | 2025-08-29 12:15:09 +0200 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2025-09-04 10:14:26 +0200 |
commit | cba74d2cde528af210e37a06652493b2ca38079c (patch) | |
tree | e5fa40e42e19eac3fb24c2867057a48136476356 /gcc | |
parent | 95afbe4c7633459b59d434550888decc41b4d44f (diff) | |
download | gcc-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.c | 17 | ||||
-rw-r--r-- | gcc/tree-scalar-evolution.cc | 32 |
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); |