https://gcc.gnu.org/g:e3121605d2a5507b4ec456ad28f133c4f11f67b6

commit r17-5659-ge3121605d2a5507b4ec456ad28f133c4f11f67b6
Author: Jakub Jelinek <[email protected]>
Date:   Wed Oct 28 11:58:37 2026 +0100

    gimple-fold-range: For range_from_readonly_var handle also STRING_CSTs and 
RAW_DATA_CSTs [PR127879]
    
    When writing the PR127685 fix/workaround, I've noticed the comment
    about RAW_DATA_CST and decided to implement it.  WHen playing with
    testcases, I've noticed it doesn't handle even more important case,
    STRING_CST.
    RAW_DATA_CST is less important because it usually appears only for
    larger chunks, CPP_EMBED should usually appear for 64+ bytes in
    the #embed directive and being turned into RAW_DATA_CST, similarly the
    optimizations to turn large array initializers into RAW_DATA_CST usually
    need 64+ bytes or more.  Sure, e.g. C designated initializers then can
    break it into smaller pieces, down to even 2 bytes in it, but
    the vrp-cstload-limit param has 255 as the upper limit (why?) and
    checks the whole size of the corresponding complete object, not even
    its subobject, so to handle RAW_DATA_CST, one needs to bump the limit I
    think.
    On the other side, the C/C++ braced_list_to_string optimization can
    turn initializers like {,un}signed char xyz[] = { 1, 2, 3 };
    into = "\1\2\3", even for much smaller sizes.
    
    Anyway, both of these IMHO need to be handled inside of
    accumulate_range_from_array_ref, because that is where we know the
    indexes, can check if a specific byte in those intersects the index range
    and in that case, we don't need to build_int_cst just to throw it away
    and can just create a wide_int and union that.  In both of these cases
    we can do this only for the end of the component path and have to verify
    m_type is integral and with CHAR_BIT precision.  It can be either
    signed or unsigned, we need to either sign or zero extend the host byte
    from STRING_CST or RAW_DATA_CST when creating the wide_int.
    
    2026-10-28  Jakub Jelinek  <[email protected]>
    
            PR tree-optimization/127879
            * gimple-range-fold.cc (ctor_ref_range::accumulate_range): Remove
            comment about RAW_DATA_CST.  Allow also STRING_CST, not just
            CONSTRUCTOR.
            (ctor_ref_range::accumulate_range_from_component_ref): Punt if
            init is not a CONSTRUCTOR.
            (ctor_ref_range::accumulate_range_from_array_ref): Handle
            init being a STRING_CST.  Handle RAW_DATA_CSTs inside of a
            CONSTRUCTOR.
            (fold_using_range::range_from_readonly_var): Allow ctor being
            a STRING_CST, rather than only a CONSTRUCTOR.
    
            * gcc.dg/tree-ssa/vrp-from-cst-agg-14.c: New test.
            * gcc.dg/tree-ssa/vrp-from-cst-agg-15.c: New test.
            * gcc.dg/tree-ssa/vrp-from-cst-agg-16.c: New test.
            * gcc.dg/tree-ssa/vrp-from-cst-agg-17.c: New test.
            * gcc.dg/tree-ssa/vrp-from-cst-agg-18.c: New test.
            * gcc.dg/tree-ssa/vrp-from-cst-agg-19.c: New test.
    
    Reviewed-by: Richard Biener <[email protected]>

Diff:
---
 gcc/gimple-range-fold.cc                           | 109 ++++++++++++++++++++-
 .../gcc.dg/tree-ssa/vrp-from-cst-agg-14.c          |  78 +++++++++++++++
 .../gcc.dg/tree-ssa/vrp-from-cst-agg-15.c          |  29 ++++++
 .../gcc.dg/tree-ssa/vrp-from-cst-agg-16.c          |  29 ++++++
 .../gcc.dg/tree-ssa/vrp-from-cst-agg-17.c          |  66 +++++++++++++
 .../gcc.dg/tree-ssa/vrp-from-cst-agg-18.c          |  28 ++++++
 .../gcc.dg/tree-ssa/vrp-from-cst-agg-19.c          |  28 ++++++
 7 files changed, 363 insertions(+), 4 deletions(-)

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 3391916ff0db..72a74a737cbd 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -1041,8 +1041,7 @@ ctor_ref_range::accumulate_range (tree init, unsigned i)
 {
   if (i == m_component_path.length ())
     return accumulate_range_from_scalar (init);
-  /* TODO: Perhaps handle RAW_DATA_CST too.  */
-  if (TREE_CODE (init) != CONSTRUCTOR)
+  if (TREE_CODE (init) != CONSTRUCTOR && TREE_CODE (init) != STRING_CST)
     return false;
 
   tree ref = m_component_path[i];
@@ -1112,6 +1111,8 @@ ctor_ref_range::accumulate_range_from_component_ref (tree 
init, unsigned i,
 {
   unsigned ix;
   tree index, val;
+  if (TREE_CODE (init) != CONSTRUCTOR)
+    return false;
   if (TYPE_MAIN_VARIANT (TREE_TYPE (init)) == DECL_CONTEXT (fld))
     FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), ix, index, val)
       {
@@ -1212,6 +1213,51 @@ ctor_ref_range::accumulate_range_from_array_ref (tree 
init, unsigned i,
   unsigned ix;
   tree index, val;
 
+  if (TREE_CODE (init) == STRING_CST)
+    {
+      if (i != m_component_path.length ()
+         || !INTEGRAL_TYPE_P (m_type)
+         || TYPE_PRECISION (m_type) != CHAR_BIT
+         || !useless_type_conversion_p (m_type, TREE_TYPE (TREE_TYPE (init)))
+         || wi::gtu_p (max + 1 - min, TREE_STRING_LENGTH (init)))
+       return false;
+      for (unsigned j = 0; j < idx_r.num_pairs (); ++j)
+       {
+         wide_int l = idx_r.lower_bound (j);
+         wide_int u = idx_r.upper_bound (j);
+         if (wi::lt_p (u, min, TYPE_SIGN (type))
+             || wi::gt_p (l, max, TYPE_SIGN (type)))
+           continue;
+         l = wi::max (l, min, TYPE_SIGN (type));
+         u = wi::min (u, max, TYPE_SIGN (type));
+         unsigned n = (l - min).to_uhwi ();
+         unsigned e = (u - min).to_uhwi ();
+         /* Note, if we'd have more than 256 iterations of the loops
+            below or even across all the outer loop iterations, it might
+            be more efficient to have a 256 bools array or 256-bit bitmask,
+            gather which bytes are seen and then union_ those which were
+            seen.  Given the current param limits this can't ever happen.  */
+         wide_int wi_cst;
+         if (TYPE_UNSIGNED (m_type))
+           for (; n <= e; ++n)
+             {
+               wi_cst
+                 = wi::uhwi ((unsigned char) TREE_STRING_POINTER (init)[n],
+                             CHAR_BIT);
+               m_r.union_ (int_range<1> (m_type, wi_cst, wi_cst));
+             }
+         else
+           for (; n <= e; ++n)
+             {
+               wi_cst
+                 = wi::shwi ((signed char) TREE_STRING_POINTER (init)[n],
+                             CHAR_BIT);
+               m_r.union_ (int_range<1> (m_type, wi_cst, wi_cst));
+             }
+       }
+      return true;
+    }
+
   // Build a range with the entire domain, and take out any elements which are
   // initialized.  If there's anything left in that range, it means there are
   // missing elements and we should add a [0, 0] to the final range.
@@ -1238,7 +1284,61 @@ ctor_ref_range::accumulate_range_from_array_ref (tree 
init, unsigned i,
       missing.intersect (int_range<2> (type, lo, hi, VR_ANTI_RANGE));
       next = wi::add (hi, 1);
 
-      if (intersects_p (idx_r, lo, hi) && !accumulate_range (val, i))
+      if (TREE_CODE (val) == RAW_DATA_CST)
+       {
+         if (!intersects_p (idx_r, lo, hi))
+           continue;
+
+         if (i != m_component_path.length ()
+             || !INTEGRAL_TYPE_P (m_type)
+             || TYPE_PRECISION (m_type) != CHAR_BIT
+             || !useless_type_conversion_p (m_type,
+                                            TREE_TYPE (val)))
+           return false;
+
+         for (unsigned j = 0; j < idx_r.num_pairs (); ++j)
+           {
+             wide_int l = idx_r.lower_bound (j);
+             wide_int u = idx_r.upper_bound (j);
+             if (wi::lt_p (u, lo, TYPE_SIGN (type))
+                 || wi::gt_p (l, hi, TYPE_SIGN (type)))
+               continue;
+             l = wi::max (l, lo, TYPE_SIGN (type));
+             u = wi::min (u, hi, TYPE_SIGN (type));
+             unsigned n = (l - lo).to_uhwi ();
+             unsigned e = (u - lo).to_uhwi ();
+             /* Note, if we'd have more than 256 iterations of the loops
+                below or even across all the outer loop iterations, it might
+                be more efficient to have a 256 bools array or 256-bit
+                bitmask, gather which bytes are seen and then union_ those
+                which were seen.  Given the current param limits this can't
+                ever happen.  */
+             wide_int wi_cst;
+             if (TYPE_UNSIGNED (m_type))
+               for (; n <= e; ++n)
+                 {
+                   wi_cst = wi::uhwi (RAW_DATA_UCHAR_ELT (val, n), CHAR_BIT);
+                   m_r.union_ (int_range<1> (m_type, wi_cst, wi_cst));
+                 }
+             else
+               for (; n <= e; ++n)
+                 {
+                   wi_cst = wi::shwi (RAW_DATA_SCHAR_ELT (val, n), CHAR_BIT);
+                   m_r.union_ (int_range<1> (m_type, wi_cst, wi_cst));
+                 }
+           }
+         continue;
+       }
+
+      if (lo == hi)
+       {
+         if (!idx_r.contains_p (lo))
+           continue;
+       }
+      else if (!intersects_p (idx_r, lo, hi))
+       continue;
+
+      if (!accumulate_range (val, i))
        return false;
     }
 
@@ -1308,7 +1408,8 @@ fold_using_range::range_from_readonly_var (vrange &r, 
gimple *stmt,
      the right part of the constructor then.  */
   tree ctor = ctor_for_folding (t);
   if (!ctor
-      || TREE_CODE (ctor) != CONSTRUCTOR)
+      || (TREE_CODE (ctor) != CONSTRUCTOR
+         && TREE_CODE (ctor) != STRING_CST))
     return false;
 
   value_range tmp (type);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-14.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-14.c
new file mode 100644
index 000000000000..eacc6ae00f43
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-14.c
@@ -0,0 +1,78 @@
+/* PR tree-optimization/127879 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized --param vrp-cstload-limit=255" } */
+/* { dg-final { scan-tree-dump-times "PHI <(?:-1\\\(\[0-9]*\\\), 
1|1\\\(\[0-9]*\\\), -1)\\\(\[0-9]*\\\)>" 4 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = \[abce]\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = d.b\\\[" "optimized" } } */
+
+const unsigned char a[] = { 100, 108, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 
0, 24, 18, 35, 98 };
+const unsigned char b[] = { 100, 108, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           0, 24, 18, 35, 98 };
+const struct { int a; unsigned char b; } c[] = { { 0, 100 }, { 0, 108 }, { 0, 
48 }, { 0, 49 }, { 0, 50 }, { 0, 51 },
+                                                { 0, 52 }, { 0, 53 }, { 0, 54 
}, { 0, 55 }, { 0, 56 }, { 0, 57 },
+                                                { 0, 0 }, { 0, 24 }, { 0, 18 
}, { 0, 35 }, { 0, 98 } };
+const struct { int a; unsigned char b[]; } d = { 0, { 100, 108, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57, 0, 24, 18, 35, 98 } };
+const unsigned char e[] = { 100, 108, 48, 48, 90, 1, 108, 53, 54, 55, 56, 57, 
0, 24, 18, 35, 98 };
+
+int
+foo (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (a[x] >= 48 && a[x] <= 57)
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x < 2 || x >= 220)
+    return -1;
+  if (b[x] >= 48 && b[x] <= 57)
+    return 1;
+  return 0;
+}
+
+int
+baz (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (c[x].b >= 48 && c[x].b <= 57)
+    return 1;
+  return 0;
+}
+
+int
+qux (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (d.b[x] >= 48 && d.b[x] <= 57)
+    return 1;
+  return 0;
+}
+
+int
+xyzzy (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (x >= 4 && x <= 6)
+    return -2;
+  if (e[x] >= 48 && e[x] <= 57)
+    return 1;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-15.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-15.c
new file mode 100644
index 000000000000..fd798e3d3c05
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-15.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/127879 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fexec-charset=UTF-8" } */
+/* { dg-final { scan-tree-dump-times "PHI <(?:-1\\\(\[0-9]*\\\), 
1|1\\\(\[0-9]*\\\), -1)\\\(\[0-9]*\\\)>" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = a\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = b.b\\\[" "optimized" } } */
+
+const unsigned char a[] = " !0123456789\0{}~";
+const struct { int a; unsigned char b[]; } b = { 0, " !0123456789\0{}~" };
+
+int
+foo (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (a[x] >= '0' && a[x] <= '9')
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (b.b[x] >= '0' && b.b[x] <= '9')
+    return 1;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-16.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-16.c
new file mode 100644
index 000000000000..cb6bba3e4ac5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-16.c
@@ -0,0 +1,29 @@
+/* PR tree-optimization/127879 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "PHI <(?:-1\\\(\[0-9]*\\\), 
1|1\\\(\[0-9]*\\\), -1)\\\(\[0-9]*\\\)>" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = a\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump-not " = b.b\\\[" "optimized" } } */
+
+const signed char a[] = { 28, -36, -2, -1, 2, 4, -3, -4, 1, 3, 0, 5, -37, 29 };
+const struct { int a; signed char b[]; } b = { 0, { 28, -36, -2, -1, 2, 4, -3, 
-4, 1, 3, 0, 5, -37, 29 } };
+
+int
+foo (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (a[x] >= -4 && a[x] <= 5)
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (b.b[x] >= -4 && b.b[x] <= 5)
+    return 1;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-17.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-17.c
new file mode 100644
index 000000000000..ea0ef7167316
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-17.c
@@ -0,0 +1,66 @@
+/* PR tree-optimization/127879 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized --param vrp-cstload-limit=255" } */
+/* { dg-final { scan-tree-dump " = a\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump " = b\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump " = c\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump " = d.b\\\[" "optimized" } } */
+
+const unsigned char a[] = { 100, 108, 48, 49, 50, 51, 52, 53, 58, 55, 56, 57, 
0, 24, 18, 35, 98 };
+const unsigned char b[] = { 100, 108, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 47, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 49, 50, 
51, 52, 53, 54, 55, 56, 57,
+                           0, 24, 18, 35, 98 };
+const struct { int a; unsigned char b; } c[] = { { 0, 100 }, { 0, 108 }, { 0, 
48 }, { 0, 49 }, { 0, 50 }, { 0, 51 },
+                                                { 0, 52 }, { 0, 58 }, { 0, 54 
}, { 0, 55 }, { 0, 56 }, { 0, 57 },
+                                                { 0, 0 }, { 0, 24 }, { 0, 18 
}, { 0, 35 }, { 0, 98 } };
+const struct { int a; unsigned char b[]; } d = { 0, { 100, 108, 48, 49, 50, 
51, 47, 53, 54, 55, 56, 57, 0, 24, 18, 35, 98 } };
+
+int
+foo (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (a[x] >= 48 && a[x] <= 57)
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x < 2 || x >= 220)
+    return -1;
+  if (b[x] >= 48 && b[x] <= 57)
+    return 1;
+  return 0;
+}
+
+int
+baz (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (c[x].b >= 48 && c[x].b <= 57)
+    return 1;
+  return 0;
+}
+
+int
+qux (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (d.b[x] >= 48 && d.b[x] <= 57)
+    return 1;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-18.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-18.c
new file mode 100644
index 000000000000..ff4331bd9ca3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-18.c
@@ -0,0 +1,28 @@
+/* PR tree-optimization/127879 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fexec-charset=UTF-8" } */
+/* { dg-final { scan-tree-dump " = a\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump " = b.b\\\[" "optimized" } } */
+
+const unsigned char a[] = " !012345+789\0{}~";
+const struct { int a; unsigned char b[]; } b = { 0, " !01234567+9\0{}~" };
+
+int
+foo (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (a[x] >= '0' && a[x] <= '9')
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (b.b[x] >= '0' && b.b[x] <= '9')
+    return 1;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-19.c 
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-19.c
new file mode 100644
index 000000000000..e6175d451b80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-from-cst-agg-19.c
@@ -0,0 +1,28 @@
+/* PR tree-optimization/127879 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " = a\\\[" "optimized" } } */
+/* { dg-final { scan-tree-dump " = b.b\\\[" "optimized" } } */
+
+const signed char a[] = { 28, -36, -2, -1, 2, 4, -3, -4, 1, 3, 0, -5, -37, 29 
};
+const struct { int a; signed char b[]; } b = { 0, { 28, -36, -2, -1, 2, 4, -3, 
-4, 1, 3, 0, -5, -37, 29 } };
+
+int
+foo (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (a[x] >= -4 && a[x] <= 5)
+    return 1;
+  return 0;
+}
+
+int
+bar (int x)
+{
+  if (x < 2 || x >= 12)
+    return -1;
+  if (b.b[x] >= -4 && b.b[x] <= 5)
+    return 1;
+  return 0;
+}

Reply via email to