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.
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.
> 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