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.
This commit is contained in:
Richard Biener 2025-08-29 12:15:09 +02:00 committed by Richard Biener
parent 95afbe4c76
commit cba74d2cde
2 changed files with 48 additions and 1 deletions

View File

@ -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" } } */

View File

@ -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);