> 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

Reply via email to