On Thu, Oct 15, 2026 at 10:51 AM Jakub Jelinek <[email protected]> wrote:
>
> On Thu, Oct 15, 2026 at 10:19:40AM +0200, Richard Biener wrote:
> > On Thu, Oct 15, 2026 at 10:00 AM Jakub Jelinek <[email protected]> wrote:
> > > + 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 (int n = 0; wi::leu_p (next, max); ++n, next = next + 1)
> > > + if (intersects_p (idx_r, next, next))
> >
> > Surely walking the idx_r representation (which is an ordered set of
> > intervals?)
> > would be more efficient?
>
> Sure, I was thinking about doing that, especially for RAW_DATA_CSTs, those
> often can be really huge (up to 2GiB each). But given the drastically low
> limit on this I've decided not to make the code too large/complex:
> -param=vrp-cstload-limit=
> Common Joined UInteger Var(param_vrp_cstload_limit) Init(32) IntegerRange(0,
> 255) Optimization Param
> Maximum number of steps when inferring a value range from a load from a
> constant aggregate.
> and because its implementation actually doesn't do what it documents:
> unsigned HOST_WIDE_INT limit = param_vrp_cstload_limit;
> if (!limit)
> return false;
>
> tree t = gimple_assign_rhs1 (stmt);
> if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (TREE_TYPE (t))))
> return false;
> limit *= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (t)));
> ...
> if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (t))
> || tree_to_uhwi (DECL_SIZE_UNIT (t)) > limit)
> return false;
> so it is not about the number of steps, but about the size of the whole
> const variable.
Oh, yeah - I remember asking for that for general CTORs. I wonder whether
for STRING_CST and RAW_DATA_CST we could instead limit
MIN (vr.upper_bound - vr.lower_bound, size), thus allow inspecting 32
elements of a [10000] array because we can efficiently access the Nth
element for STRING_CST (and RAW_DATA_CST?) rather than having
to walk (or besarch) the CTOR.
> Say if I have
> const struct S { char a[2000000]; int b[32]; } c = { ... };
> and try to check range of c.b[i], then it just punts, even when
> it actually has just 32 elements. And with the 255 upper
> bound for this it will simply never have too many steps.
>
> Now, if we change this, say stop multiplying the limit and comparing it to
> the byte size, but instead add m_cnt member, add if (--m_cnt == 0) return
> false; to accumulate_range_from_scalar and these two spots, then yes, it
> might make sense to be more efficient even here.
>
> > > + {
> > > + wide_int wi_cst;
> > > + if (TYPE_UNSIGNED (m_type))
> > > + wi_cst = wi::uhwi ((unsigned char) TREE_STRING_POINTER
> > > (init)[n],
> > > + CHAR_BIT);
> > > + else
> > > + 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));
> >
> > and for the sake of efficiency collecting the unsigned chars visited
> > (256 bit sbitmap?) and unioning each duplicate at most once or even
> > building an irange from a sorted set of elements directly.
>
> Something like that might be a win only if the loop has 256+ in-range
> elements. Which currently it will never have, if we don't bump the param,
> even if we do use m_cnt, it will never have it either.
True. I was missing the limit was enforced on the decl upthread.
That said, having a way to iterate over a range might be a nice thing to have,
at least adding a comment that this is what we are essentially doing might be
good. I don't see anything besides num_pairs(), not even in the
private irange API though.
Richard.
> > If we are talking about efficiency. I'd be fine with the existing
> > code - ISTR we have
> > an upper limit --param how many values we visit, but this doesn't
> > enforce it (param_vrp_cstload_limit)?
>
> Jakub
>