Hi,

On Fri, Nov 15 2024, Martin Jambor wrote:
> Hi,
>
> On Thu, Nov 07 2024, Aldy Hernandez wrote:
>> Jan Hubicka <hubi...@ucw.cz> writes:
>>
>>>> > 2024-11-01  Martin Jambor  <mjam...@suse.cz>
>>>> >
>>>> >         * ipa-prop.cc (ipa_compute_jump_functions_for_edge): When 
>>>> > creating
>>>> >         value-range jump functions from pointer type constant zero, do so
>>>> >         as if it was not a pointer.
>>>> > ---
>>>> >  gcc/ipa-prop.cc | 3 ++-
>>>> >  1 file changed, 2 insertions(+), 1 deletion(-)
>>>> >
>>>> > diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
>>>> > index 9bd2e4bc60c..012f8a32386 100644
>>>> > --- a/gcc/ipa-prop.cc
>>>> > +++ b/gcc/ipa-prop.cc
>>>> > @@ -2368,7 +2368,8 @@ ipa_compute_jump_functions_for_edge (struct 
>>>> > ipa_func_body_info *fbi,
>>>> >         }
>>>> >
>>>> >        value_range vr (TREE_TYPE (arg));
>>>> > -      if (POINTER_TYPE_P (TREE_TYPE (arg)))
>>>> > +      if (POINTER_TYPE_P (TREE_TYPE (arg))
>>>> > +         && !zerop (arg))
>>>> 
>>>> integer_zerop (arg) - I also think this deserves a comment.
>
> thanks for the pointer, I was not aware of that function.  But given
> Honza's and Aldi's feedback, I may take a different path.
>
>>>
>>> Comment would indeed be nice.  It is not clear to me why special
>>> handling is needed here and ranger does not give the same or better
>>> value range than one we compute based on alignment+offset and non-zero
>>> ness?
>>
>> Yeah, this doesn't smell right.  Martin, could you look at what's going on?
>
> If you quickly glance at the code it is not surprising.  The pointer
> handling code looks if it knows that the argument is non-zero, and
> depending on that either starts with a (freshly initialized) non_zero or
> varying value_range.  Afterwards, it proceeds to attempt to imbue it
> with alignment info.  That is, the code does not try to store the result
> of the get_range_query into the jump function, it is simply interested
> in the non-NULLness.
>
> I thought that was intentional but given Aldy's reaction perhaps it
> wasn't, so I decided to be bolder and rework the code a bit.  Please see
> an alternative patch below.
>
>>
>>>
>>> The code was needed since we did not have value ranges for pointer typed
>>> SSA names, but do we still need to special case them these days?
>>
>> Note that the prange implementation doesn't do anything extra we weren't
>> already doing with irange for pointers.  And the original code didn't
>> update ranges or value/mask pairs based on alignment, so you probably
>> still have to keep doing whatever alignment magic you were doing.
>
> I also work with the assumption that the extra code is necessary but my
> understanding of ranger and its capabilities is limited.
>
> Below is the new patch which has also passed bootstrap and testing on
> x86_64-linux on its own and along with the verifier patch.
>

Ping, please.

Martin


> ---------- 8< -------------------- 8< -------------------- 8< ----------
>
> When looking into cases where we know an actual argument of a call is
> a constant but we don't generate a singleton value-range for the jump
> function, I found out that the special handling of pointer constants
> does not work well for constant zero pointer values.  In fact the code
> only attempts to see if it can figure out that an argument is not zero
> and if it can figure out any alignment information.
>
> With this patch, we try to use the value_range that ranger can give us
> in the jump function if we can and we query ranger for all kinds of
> arguments, not just SSA_NAMES (and so also pointer integer constants).
> If we cannot figure out a useful range we fall back again on figuring
> out non-NULLness with tree_single_nonzero_warnv_p.
>
> With this patch, we generate
>
>   [prange] struct S * [0, 0] MASK 0x0 VALUE 0x0
>
> instead of for example:
>
>   [prange] struct S * [0, +INF] MASK 0xfffffffffffffff0 VALUE 0x0
>
> for a zero constant passed in a call.
>
> If you are wondering why we check whether the value range obtained
> from range_of_expr can be undefined, even when the function returns
> true, that is because that can apparently happen for default-definition
> SSA_NAMEs.
>
> gcc/ChangeLog:
>
> 2024-11-15  Martin Jambor  <mjam...@suse.cz>
>
>       * ipa-prop.cc (ipa_compute_jump_functions_for_edge): Try harder to
>       use the value range obtained from ranger for pointer values.
> ---
>  gcc/ipa-prop.cc | 35 ++++++++++++++++-------------------
>  1 file changed, 16 insertions(+), 19 deletions(-)
>
> diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
> index fd0d9b7c15c..50ec8e0cf28 100644
> --- a/gcc/ipa-prop.cc
> +++ b/gcc/ipa-prop.cc
> @@ -2382,28 +2382,27 @@ ipa_compute_jump_functions_for_edge (struct 
> ipa_func_body_info *fbi,
>        value_range vr (TREE_TYPE (arg));
>        if (POINTER_TYPE_P (TREE_TYPE (arg)))
>       {
> -       bool addr_nonzero = false;
> -       bool strict_overflow = false;
> -
> -       if (TREE_CODE (arg) == SSA_NAME
> -           && param_type
> -           && get_range_query (cfun)->range_of_expr (vr, arg, cs->call_stmt)
> -           && vr.nonzero_p ())
> -         addr_nonzero = true;
> -       else if (tree_single_nonzero_warnv_p (arg, &strict_overflow))
> -         addr_nonzero = true;
> -
> -       if (addr_nonzero)
> -         vr.set_nonzero (TREE_TYPE (arg));
> -
> +       if (!get_range_query (cfun)->range_of_expr (vr, arg, cs->call_stmt)
> +           || vr.varying_p ()
> +           || vr.undefined_p ())
> +         {
> +           bool strict_overflow = false;
> +           if (tree_single_nonzero_warnv_p (arg, &strict_overflow))
> +             vr.set_nonzero (TREE_TYPE (arg));
> +           else
> +             vr.set_varying (TREE_TYPE (arg));
> +         }
> +       gcc_assert (!vr.undefined_p ());
>         unsigned HOST_WIDE_INT bitpos;
> -       unsigned align, prec = TYPE_PRECISION (TREE_TYPE (arg));
> +       unsigned align = BITS_PER_UNIT;
>  
> -       get_pointer_alignment_1 (arg, &align, &bitpos);
> +       if (!vr.singleton_p ())
> +         get_pointer_alignment_1 (arg, &align, &bitpos);
>  
>         if (align > BITS_PER_UNIT
>             && opt_for_fn (cs->caller->decl, flag_ipa_bit_cp))
>           {
> +           unsigned prec = TYPE_PRECISION (TREE_TYPE (arg));
>             wide_int mask
>               = wi::bit_and_not (wi::mask (prec, false, prec),
>                                  wide_int::from (align / BITS_PER_UNIT - 1,
> @@ -2411,12 +2410,10 @@ ipa_compute_jump_functions_for_edge (struct 
> ipa_func_body_info *fbi,
>             wide_int value = wide_int::from (bitpos / BITS_PER_UNIT, prec,
>                                              UNSIGNED);
>             irange_bitmask bm (value, mask);
> -           if (!addr_nonzero)
> -             vr.set_varying (TREE_TYPE (arg));
>             vr.update_bitmask (bm);
>             ipa_set_jfunc_vr (jfunc, vr);
>           }
> -       else if (addr_nonzero)
> +       else if (!vr.varying_p ())
>           ipa_set_jfunc_vr (jfunc, vr);
>         else
>           gcc_assert (!jfunc->m_vr);
> -- 
> 2.47.0

Reply via email to