https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127515
--- Comment #3 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Richard Biener <[email protected]>: https://gcc.gnu.org/g:471022256e4705314aedf21c53bc351ece88ff43 commit r17-4520-g471022256e4705314aedf21c53bc351ece88ff43 Author: Richard Biener <[email protected]> Date: Mon Sep 21 12:15:02 2026 +0200 tree-optimization/127515 - ivopts: fix bound when counter wraps on first increment iv_elimination_compare_lt turns a loop with the exit test i < b, entered with i = a and a pointer p = base + a stepping in lockstep with i, into a loop with the exit test p < p_0 - a + b, so as to eliminate the counter. The number of iterations of the loop is (a + 1 > b) ? 0 : b - a - 1 and the fix for PR tree-optimization/113703 made sure that the bound is not derived from it, since converting b - a to the type of the offsets is not value preserving when the loop rolls zero times and b - a is negative. But the reasoning also assumes that a + 1 does not wrap around in the type of a, which need not be the case: if a is the maximum value of its type, then a + 1 is zero, a + 1 > b is false whatever b is, so the loop rolls and its number of iterations is b, whereas b - a computed on the offsets is b - a and not b + 1. For example, with void f (char *p, unsigned int i, unsigned int n) { p -= i; do { *p = 1; p -= 1; i++; } while (i < n); } called as f (p, -1, 1), the loop iterates twice but the bound is computed as p_0 + ((sizetype) 0xffffffff - (sizetype) 1), i.e. p_0 + 0xfffffffe instead of p_0 - 2, so the loop exits at the first test. So build the bound out of a + 1 and b + 1 instead of a and b, converting a + 1 to the type of the offsets as a whole instead of rewriting it into a and 1, and computing b + 1 in the type of the offsets, where it cannot wrap around. The difference of the two offsets is then the number of iterations of the loop in the wrapping case too, since a + 1 is zero there. Require the new pair of offsets to be non-negative and to not overflow as well. Co-Authored-By: Claude Opus 5 <[email protected]> PR tree-optimization/113703 PR tree-optimization/127515 * tree-ssa-loop-ivopts.cc (iv_elimination_compare_lt): Also record A + 1 when matching the number of iterations. Convert it to OFF_TYPE as a whole, compute B + 1 in OFF_TYPE and require both to be non-negative scaled offsets that do not overflow. Build the bound out of them instead of A and B. * gcc.dg/torture/pr113703-5.c: New test. * gcc.dg/torture/pr113703-6.c: New test.
