diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-01-09 10:31:51 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-01-09 10:31:51 +0100 |
commit | b1d4e5b51375efd285378173375d634ad6ba8462 (patch) | |
tree | 3448d9754e51e55f36534e647fb08db2cb669594 | |
parent | 4d3fd59953bcf423dd0859a2c6b95b5260aed71d (diff) | |
download | gcc-b1d4e5b51375efd285378173375d634ad6ba8462.zip gcc-b1d4e5b51375efd285378173375d634ad6ba8462.tar.gz gcc-b1d4e5b51375efd285378173375d634ad6ba8462.tar.bz2 |
vect: Ensure both NITERSM1 and NITERS are INTEGER_CSTs or neither of them [PR113210]
On the following testcase e.g. on riscv64 or aarch64 (latter with
-O3 -march=armv8-a+sve ) we ICE, because while NITERS is INTEGER_CST,
NITERSM1 is a complex expression like
(short unsigned int) (a.0_1 + 255) + 1 > 256 ? ~(short unsigned int) (a.0_1 + 255) : 0
where a.0_1 is unsigned char. The condition is never true, so the above
is equivalent to just 0, but only when trying to fold the above with
PLUS_EXPR 1 we manage to simplify it (first
~(short unsigned int) (a.0_1 + 255)
to
-(short unsigned int) (a.0_1 + 255)
and then
(short unsigned int) (a.0_1 + 255) + 1 > 256 ? -(short unsigned int) (a.0_1 + 255) : 1
to
(short unsigned int) (a.0_1 + 255) >= 256 ? -(short unsigned int) (a.0_1 + 255) : 1
and only at this point we fold the condition to be false.
But the vectorizer seems to assume that if NITERS is known (i.e. suitable
INTEGER_CST) then NITERSM1 also is, so the following hack ensures that if
NITERS folds into INTEGER_CST NITERSM1 will be one as well.
2024-01-09 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/113210
* tree-vect-loop.cc (vect_get_loop_niters): If non-INTEGER_CST
value in *number_of_iterationsm1 PLUS_EXPR 1 is folded into
INTEGER_CST, recompute *number_of_iterationsm1 as the INTEGER_CST
minus 1.
* gcc.c-torture/compile/pr113210.c: New test.
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr113210.c | 13 | ||||
-rw-r--r-- | gcc/tree-vect-loop.cc | 13 |
2 files changed, 26 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr113210.c b/gcc/testsuite/gcc.c-torture/compile/pr113210.c new file mode 100644 index 0000000..0aa0780 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr113210.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/113210 */ + +unsigned char a, c; +unsigned short b; + +void +foo (void) +{ + c = a + 255; + b = c; + while (++b > 256) + ; +} diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 9dd573e..cfea907 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -941,9 +941,22 @@ vect_get_loop_niters (class loop *loop, const_edge main_exit, tree *assumptions, ??? For UINT_MAX latch executions this number overflows to zero for loops like do { n++; } while (n != 0); */ if (niter && !chrec_contains_undetermined (niter)) + { niter = fold_build2 (PLUS_EXPR, TREE_TYPE (niter), unshare_expr (niter), build_int_cst (TREE_TYPE (niter), 1)); + if (TREE_CODE (niter) == INTEGER_CST + && TREE_CODE (*number_of_iterationsm1) != INTEGER_CST) + { + /* If we manage to fold niter + 1 into INTEGER_CST even when + niter is some complex expression, ensure back + *number_of_iterationsm1 is an INTEGER_CST as well. See + PR113210. */ + *number_of_iterationsm1 + = fold_build2 (PLUS_EXPR, TREE_TYPE (niter), niter, + build_minus_one_cst (TREE_TYPE (niter))); + } + } *number_of_iterations = niter; } |