On Tue, Dec 3, 2024 at 12:09 PM Martin Jambor <mjam...@suse.cz> wrote:
>
> Hi,
>
> sorry for re-posting this but my mail client broke threading when
> saving the email as Draft somehow and I really hope to still get this
> testcase working for GCC 15:
>
> On Fri, Nov 15 2024, Richard Biener wrote:
> > On Fri, Nov 15, 2024 at 1:45 PM Jan Hubicka <hubi...@ucw.cz> wrote:
> >> >
> >> > The patch only ever skips just one conversion, never a chain of them and
> [ 12 more citation lines. Click/Enter to show. ]
> >> > deliberately so, for the reasons shown in the example.
> >> >
> >> > However, I have just realized that combining pass_through jump functions
> >> > during inlining may unfortunately have exactly the same effect, so we
> >> > indeed need to be more careful.
> >>
> >> Ah, right.  I was thinking if I can trigger someting like this and this
> >> option did not came to my mind.
> >> >
> >> > The motivating example converts a bool (integer with precision one) to
> >> > an int, so what about the patch below which allows converting between
> >> > integers and to a higher precision?  (Assuming the patch will pass
> >> > bootstrap and testing on x86_64-linux which is underway).
> >>
> >> Allowing only conversion that monotonously increase precision looks.
>
> As in "looks better?"  Or perhaps even "looks good?"
>
> >> Perhaps Richi may have opinion here.
> >> In a way this is similar to what we do in gimple_call_builtin that has
> [ 13 more citation lines. Click/Enter to show. ]
> >> some type checking and also allows widening conversions.  So perhaps
> >> this can be unified.
> >>
> >> I just noticed that testusite has few examples that, for example, define
> >>
> >> void *calloc (long, long)
> >>
> >> and this makes the test fail since parameter is really unsigned long
> >> and in the turn we disable some calloc optimizations even though this
> >> does not affect code generation.  Some passes use
> >> gimple_call_builtin while other look up callee decl by hand.
> >
> > I think all conversions that are not value changing (based on incoming 
> > range)
> > are OK.  Even signed int with [3, 10] -> unsigned char [3, 10] would be OK.
> > But signed int with [-1, 1] -> unsigned char [0, 1] [ 0xff ] might
> > cause problems.
>
> Right, I was not going to use ranges for this because I suspected that
> more often than not the range would be unknown.  But if that's the
> suggestion, would something like the following (only very mildly tested)
> function be OK?
>
> I kept the type check because it looks quite a bit cheaper and would
> work also for conversions between integers with the same precision but
> different signedness which we can safely fold_convert between as well.

Maybe you can use range_fits_type_p?  (aka int_fits_type_p for INTEGER_CSTs)

What I was saying is that your change looks OK (but it can be possibly improved
upon).

> ---------- 8< ----------
>
> /* If T is an SSA_NAME that is the result of a simple type conversion
>    statement from an integer type to another integer which is known to
>    be able to represent the values the operand of conversion can hold,
>    return the operand of that conversion, otherwise return T.  */
>
> static tree
> skip_a_safe_conversion_op (tree t)
> {
>   if (TREE_CODE (t) != SSA_NAME
>       || SSA_NAME_IS_DEFAULT_DEF (t))
>     return t;
>
>   gimple *def = SSA_NAME_DEF_STMT (t);
>   if (!is_gimple_assign (def)
>       || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))
>       || !INTEGRAL_TYPE_P (TREE_TYPE (t))
>       || !INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (def))))
>     return t;
>
>   tree rhs1 = gimple_assign_rhs1 (def);
>   if (TYPE_PRECISION (TREE_TYPE (t))
>       >= TYPE_PRECISION (TREE_TYPE (rhs1)))
>     return gimple_assign_rhs1 (def);
>
>   if (!ipa_vr_supported_type_p (TREE_TYPE (rhs1)))
>     return t;
>   value_range vr (TREE_TYPE (rhs1));
>   if (!get_range_query (cfun)->range_of_expr (vr, rhs1, def)
>       || vr.undefined_p ())
>     return t;
>
>   widest_int new_minv = wi::to_widest (TYPE_MIN_VALUE (TREE_TYPE (t)));
>   widest_int new_maxv = wi::to_widest (TYPE_MAX_VALUE (TREE_TYPE (t)));
>   irange &ir = as_a<irange> (vr);
>   if (new_minv <= widest_int::from (ir.lower_bound (),
>                                     TYPE_SIGN (TREE_TYPE (rhs1)))
>       && new_maxv >= widest_int::from (ir.upper_bound (),
>                                        TYPE_SIGN (TREE_TYPE (rhs1))))
>     return gimple_assign_rhs1 (def);
>
>   return t;
> }
>
> ---------- 8< ----------
>
> Note that while the value-range based approach also works for the
> motivating test-case, that is simply because lower_bound() and
> upper_bound() methods invoked on a VARYING value range of an integer
> type yield the minimum and maximum value respectively.  This happens
> because get_range_query (cfun)->range_of_expr invoked to find the range
> of _1 at the conversion statement in the function below indeed gives
> back a VARYING one.
>
> __attribute__((noinline))
> int foo (int (*<T3e3>) (int) f)
> {
>   _Bool _1;
>   int _2;
>   int _6;
>
>   <bb 2> [local count: 1073741824]:
>   _1 = f_3(D) == 0B;
>   _2 = (int) _1;
>   _6 = bar (_2);
>   return _6;
>
> }
>
> On the other hand, when I added a simple fprintf before the return in
> the above function when we were able to determine that the conversion is
> safe from a value range and not from simply looking at the precision and
> then ran make stage2-bubble (C, C++ and Fortran), it did trigger 269
> times.  So there is some potential even if it is not huge.
>
> I think that the motivating test case is a useful one and so I'd like to
> get some form of the patch in for GCC 15.  I'll be grateful for any
> feedback on how to determine a conversion is safe.
>
> Martin
>

Reply via email to