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

Reply via email to