> Hi, > > since the IPA-CP lattices for value ranges cannot hold more values and > don't have any "variable" flag, we initialize them to bottom for > non-local nodes. However, that means we don't make use of known > information gathered in jump functions when the corresponding node is > cloned for some other reason. This patch allows collection of the > information and only does not use them for the original non-local > nodes.
Since IPA predicates can tell you if function will simplify by known value range, I think we should eventually start handling VRP based cloining by same path as we currently do constants and devirtulalization. Common example are NULL pointer checks and overflow checks that are common in C++ code... > > Bootstrapped, LTO-bootstrapped and tested on x86_64, OK for master? > > Thanks, > > Martin > > > gcc/ChangeLog: > > 2025-11-04 Martin Jambor <[email protected]> > > * ipa-cp.cc (set_all_contains_variable): New parameter > INCLUDE_SIMPLE, make setting bits and vr lattices to bottom > conditional on it. > (initialize_node_lattices): Pass false to the second parameter of > set_all_contains_variable. > (ipcp_store_vr_results): Skip non-local nodes. > --- > gcc/ipa-cp.cc | 21 ++++++++++++++++----- > 1 file changed, 16 insertions(+), 5 deletions(-) > > diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc > index 915d29b4bb2..fcb3123b9ed 100644 > --- a/gcc/ipa-cp.cc > +++ b/gcc/ipa-cp.cc > @@ -1322,17 +1322,23 @@ intersect_argaggs_with (vec<ipa_argagg_value> &elts, > } > > /* Mark bot aggregate and scalar lattices as containing an unknown variable, > - return true is any of them has not been marked as such so far. */ > + return true is any of them has not been marked as such so far. If > + INCLUDE_SIMPLE is true, also set the lattices that can only hold one value > + to bottom. */ > > static inline bool > -set_all_contains_variable (class ipcp_param_lattices *plats) > +set_all_contains_variable (class ipcp_param_lattices *plats, > + bool include_simple = true) > { > bool ret; > ret = plats->itself.set_contains_variable (); > ret |= plats->ctxlat.set_contains_variable (); > ret |= set_agg_lats_contain_variable (plats); > - ret |= plats->bits_lattice.set_to_bottom (); > - ret |= plats->m_value_range.set_to_bottom (); > + if (include_simple) > + { > + ret |= plats->bits_lattice.set_to_bottom (); > + ret |= plats->m_value_range.set_to_bottom (); It took me a whlie to understand this. So the first three values are those where we handle clonning for diffeent contextes, while bits and value ranges does not (yet). > + } > return ret; > } > > @@ -1477,7 +1483,7 @@ initialize_node_lattices (struct cgraph_node *node) > { > plats->m_value_range.init (type); > if (variable) > - set_all_contains_variable (plats); > + set_all_contains_variable (plats, false); So here we will start propagating even if function can be called externally. > } > } > > @@ -6323,6 +6329,11 @@ ipcp_store_vr_results (void) > bool do_vr = true; > bool do_bits = true; > > + /* If the function is not local, the gathered information is only > useful > + for clones. */ > + if (!node->local) > + continue; Assume we have A->B->C where A sets value ranges, B can be called externally and C is local and would benefit from known range. If we clone B then we will end up A->B'->C B ->C and C will not see the value range passed from A? However if we decide to clone C for some other reason we will have A->B'->C' B ->C and here C' will see the value range and C will not? I do not see how you can distinguish these situation as ipcp_store_vr_results time? Honza
