https://gcc.gnu.org/g:ac27d2e11708eb999fab1b26c053df4f3bd8fd0c
commit r17-5333-gac27d2e11708eb999fab1b26c053df4f3bd8fd0c Author: Richard Biener <[email protected]> Date: Mon Oct 19 13:10:19 2026 +0200 tree-optimization/127966 - wrong niter with iteration over STRING_CST The following fixes a sign-extension issue with loop_niter_by_eval simulating an iteration over a STRING_CST by performing the compare in uint8_t type. PR tree-optimization/127966 * tree-ssa-loop-niter.cc (loop_niter_by_eval): Perform the comparison of the STRING_CST element with the terminating constant in uint8_t type. * gcc.dg/torture/pr127966.c: New testcase. Diff: --- gcc/testsuite/gcc.dg/torture/pr127966.c | 11 +++++++++++ gcc/tree-ssa-loop-niter.cc | 9 +++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/gcc/testsuite/gcc.dg/torture/pr127966.c b/gcc/testsuite/gcc.dg/torture/pr127966.c new file mode 100644 index 000000000000..a8dd1d4d47bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr127966.c @@ -0,0 +1,11 @@ +/* { dg-do run } */ + +int main() +{ + int i = 0; + while (((unsigned char *)"\x80\x80")[i] == 128) + i++; + if (i != 2) + __builtin_abort (); + return 0; +} diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index bbfa16c6d6ba..f9f8222e6311 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -3725,6 +3725,7 @@ loop_niter_by_eval (class loop *loop, edge exit) tree mem = gimple_assign_rhs1 (def); affine_iv iv; if (TYPE_MODE (TREE_TYPE (mem)) == TYPE_MODE (char_type_node) + && CHAR_TYPE_SIZE == 8 && simple_iv (loop, loop, TREE_OPERAND (mem, 0), &iv, false) && tree_fits_uhwi_p (TREE_OPERAND (mem, 1)) @@ -3740,6 +3741,7 @@ loop_niter_by_eval (class loop *loop, edge exit) { str = TREE_OPERAND (str, 0); unsigned i = 0; + uint8_t op1 = TREE_INT_CST_LOW (op[1]); for (unsigned HOST_WIDE_INT idx = (tree_to_uhwi (TREE_OPERAND (mem, 1)) + tree_to_uhwi (off)); @@ -3747,10 +3749,9 @@ loop_niter_by_eval (class loop *loop, edge exit) && i < MAX_ITERATIONS_TO_TRACK; idx += tree_to_uhwi (iv.step), ++i) { - int res = compare_tree_int - (op[1], TREE_STRING_POINTER (str)[idx]); - if ((cmp == NE_EXPR && res == 0) - || (cmp == EQ_EXPR && res != 0)) + uint8_t c = TREE_STRING_POINTER (str)[idx]; + if ((cmp == NE_EXPR && op1 == c) + || (cmp == EQ_EXPR && op1 != c)) return build_int_cst (unsigned_type_node, i); } }
