On Thu, Oct 15, 2026 at 12:08 PM Jakub Jelinek <[email protected]> wrote:
>
> On Thu, Oct 15, 2026 at 11:09:27AM +0200, Richard Biener wrote:
> > 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.
>
> If we change what the param means, then sure, we can do all kinds of stuff.
> Note, for COMPONENT_REFs, we also walk the CONSTRUCTOR_ELTS (though unlike
> the array cases we have early exit in that case instead of walking
> everything). And (at least when using FIELD_DECL pointer comparison (see my
> previously posted workaround patch for the slower case), the COMPONENT_REF
> check is much cheaper compile time wise than the intersect_p + union_
> thing. So, if we let the limit propagate in m_cnt member and let each
> function decrement it by whatever cost it sees and punt if we run out of
> limit, we can do different things for the different cases.
Given we'd throw away the partly computed information I'd rather be
able to upfront
check if we'll run into the limit - that's why it's done upfront but
as said for STRING_CST
and maybe also RAW_DATA_CST we have a better idea (upper bound) of
costs involved.
ISTR suggesting that we put some (on the side?) summary about CTORs we have
processed once, for example the total number (including recursive CTORs) of CTOR
elements involved. That could yield to a better estimate.
> Count the COMPONENT_REFs checks or not? If yes, count with the same cost (1
> for each, or count COMPONENT_REFs as 1 and ARRAY_REFs as 2 or 4)?
> For ARRAY_REFs CONSTRUCTOR, CONSTRUCTOR_NELTS is I guess what we care about,
> if we have say { [32 ... 1024] = 42 }; then no matter what the array size
> is, we need to do just one intersects_p and one union_.
> For STRING_CST and RAW_DATA_CSTs, we could then say count number of
> intersecting bytes
> wide_int cnt = wi::zero (TYPE_PRECISION (type));
> for (unsigned i = 0; i < idx_r.num_pairs (); ++i)
> {
> wide_int l = idx_r.lower_bound (i);
> wide_int u = idx_r.upper_bound (i);
> 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));
> cnt += u - l + 1;
> }
> (where for RAW_DATA_CST min/max are actually lo and hi).
> And then punt if we don't have at least cnt actions till limit (or
> for RAW_DATA_CST that minus 1, because we've already counted the
> RAW_DATA_CST in the CONSTRUCTOR_NELTS). Otherwise we could decide
> on how to implement it based on the exact cnt value, TREE_STRING_LENGTH
> / RAW_DATA_LENGTH, for small TREE_STRING_LENGTH/RAW_DATA_LENGTH it isn't
> worth to do anything extra and can do what I posted in the patch, for
> very long sizes of those we need to do the smart walk on indexes
> (basically exactly the same loop as above, just instead of the cnt += u - l
> + 1 loop over the elements), and based on whether cnt > 256 + epsilon
> or not it could also switch in between doing union_ on each case or having
> a 256 bool array, gather what bytes appear and then loop over that array
> and union_ that.
> Or, for small TREE_STRING_LENGTH / RAW_DATA_LENGTH, even don't do the above
> cnt computation and just do what the patch does and count that length into
> the limit, and only if it is larger do the smarter things.
>
> Do you want those changes as part of this patch, or can that be done
> incrementally?
I think changes to the param heuristic should be done as followup. Feel free to
improve the STRING_CST/RAW_DATA_CST processing though as you say
with the current param value it shouldn't matter much in practice.
Richard.
>
> Jakub
>