On Tue, Sep 4, 2018 at 3:51 PM Aldy Hernandez <al...@redhat.com> wrote:
>
>
>
> On 09/04/2018 09:41 AM, Richard Biener wrote:
> > On Tue, Sep 4, 2018 at 3:21 PM Aldy Hernandez <al...@redhat.com> wrote:
> >>
> >>
> >>
> >> On 09/04/2018 08:29 AM, Richard Biener wrote:
> >>> On Tue, Sep 4, 2018 at 2:09 PM Aldy Hernandez <al...@redhat.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 09/04/2018 07:42 AM, Richard Biener wrote:
> >>>>> On Thu, Aug 30, 2018 at 9:39 AM Aldy Hernandez <al...@redhat.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> On 08/29/2018 12:32 PM, David Malcolm wrote:
> >>>>>>> On Wed, 2018-08-29 at 06:54 -0400, Aldy Hernandez wrote:
> >>>>>>>> Never say never.  Just when I thought I was done...
> >>>>>>>>
> >>>>>>>> It looks like I need the special casing we do for pointer types in
> >>>>>>>> extract_range_from_binary_expr_1.
> >>>>>>>>
> >>>>>>>> The code is simple enough that we could just duplicate it anywhere
> >>>>>>>> we
> >>>>>>>> need it, but I hate code duplication and keeping track of multiple
> >>>>>>>> versions of the same thing.
> >>>>>>>>
> >>>>>>>> No change in functionality.
> >>>>>>>>
> >>>>>>>> Tested on x86-64 Linux with all languages.
> >>>>>>>>
> >>>>>>>> OK?
> >>>>>>>
> >>>>>>> A couple of nits I spotted:
> >>>>>>>
> >>>>>>> diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
> >>>>>>> index f20730a85ba..228f20b5203 100644
> >>>>>>> --- a/gcc/tree-vrp.c
> >>>>>>> +++ b/gcc/tree-vrp.c
> >>>>>>> @@ -1275,6 +1275,32 @@ set_value_range_with_overflow (value_range &vr,
> >>>>>>>          }
> >>>>>>>      }
> >>>>>>>
> >>>>>>> +/* Value range wrapper for wide_int_range_pointer.  */
> >>>>>>> +
> >>>>>>> +static void
> >>>>>>> +vrp_range_pointer (value_range *vr,
> >>>>>>> +                enum tree_code code, tree type,
> >>>>>>> +                value_range *vr0, value_range *vr1)
> >>>>>>>
> >>>>>>> Looking at the signature of the function, I wondered what the source
> >>>>>>> and destination of the information is...
> >>>>>>
> >>>>>> vr being the destination and vr0/vr1 being the sources are standard
> >>>>>> operating procedure within tree-vrp.c.  All the functions are basically
> >>>>>> that, that's why I haven't bothered.
> >>>>>>
> >>>>>>>
> >>>>>>> Could vr0 and vr1 be const?
> >>>>>>>
> >>>>>>> ...which would require extract_range_into_wide_ints to take a const
> >>>>>>> value_range *
> >>>>>>
> >>>>>> Yes, but that would require changing all of tree-vrp.c to take const
> >>>>>> value_range's.  For instance, range_int_cst_p and a slew of other
> >>>>>> functions throughout.
> >>>>>>
> >>>>>>>
> >>>>>>>       ... which would require range_int_cst_p to take a const 
> >>>>>>> value_range *
> >>>>>>>
> >>>>>>> (I *think* that's where the yak-shaving would end)
> >>>>>>>
> >>>>>>> +{
> >>>>>>> +  signop sign = TYPE_SIGN (type);
> >>>>>>> +  unsigned prec = TYPE_PRECISION (type);
> >>>>>>> +  wide_int vr0_min, vr0_max;
> >>>>>>> +  wide_int vr1_min, vr1_max;
> >>>>>>> +
> >>>>>>> +  extract_range_into_wide_ints (vr0, sign, prec, vr0_min, vr0_max);
> >>>>>>> +  extract_range_into_wide_ints (vr1, sign, prec, vr1_min, vr1_max);
> >>>>>>> +  wide_int_range_nullness n;
> >>>>>>> +  n = wide_int_range_pointer (code, sign, vr0_min, vr0_max, vr1_min,
> >>>>>>> vr1_max);
> >>>>>>> +  if (n == WIDE_INT_RANGE_UNKNOWN)
> >>>>>>> +    set_value_range_to_varying (vr);
> >>>>>>> +  else if (n == WIDE_INT_RANGE_NULL)
> >>>>>>> +    set_value_range_to_null (vr, type);
> >>>>>>> +  else if (n == WIDE_INT_RANGE_NONNULL)
> >>>>>>> +    set_value_range_to_nonnull (vr, type);
> >>>>>>> +  else
> >>>>>>> +    gcc_unreachable ();
> >>>>>>> +}
> >>>>>>> +
> >>>>>>>
> >>>>>>> Would it be better to use a "switch (n)" here, rather than a series of
> >>>>>>> "if"/"else if" for each enum value?
> >>>>>>
> >>>>>> I prefer ifs for a small amount of options, but having the compiler 
> >>>>>> warn
> >>>>>> on missing enum alternatives is nice, so I've changed it.  Notice
> >>>>>> there's more code now though :-(.
> >>>>>
> >>>>> I don't like the names *_range_pointer, please change them to sth more
> >>>>> specific like *_range_pointer_binary_op.
> >>>>
> >>>> Sure.
> >>>>
> >>>>>
> >>>>> What's the advantage of "hiding" the resulting ranges behind the
> >>>>> wide_int_range_nullness enum rather than having regular range output?
> >>>>
> >>>> Our upcoming work has another representation for non-nulls in particular
> >>>> ([-MIN,-1][1,+MAX]), since we don't have anti ranges.  I want to share
> >>>> whatever VRP is currently doing for pointers, without having to depend
> >>>> on the internals of vrp (value_range *).
> >>>>
> >>>>> What's the value in separating pointer operations at all in the
> >>>>> wide-int interfaces?  IIRC the difference is that whenever unioning
> >>>>> is required that when it's a pointer result we should possibly
> >>>>> preserve non-nullness.  It's of course also doing less work overall.
> >>>>
> >>>> I don't follow.  What are you suggesting?
> >>>
> >>> I'm thinking out loud.  Here adding sort-of a "preferencing" to the
> >>> more general handling of the ops would do the same trick, without
> >>> restricting that to "pointers".  For example if a pass would be interested
> >>> in knowing whether a divisor is zero it would also rather preserve
> >>> non-nullness and trade that for precision in other parts of the range,
> >>> say, if you had [-1, -1] [1, +INF] then the smallest unioning result
> >>> is [-1, +INF] but ~[0, 0] is also a valid result which preserves 
> >>> non-zeroness.
> >>>
> >>> So for wide-int workers I don't believe in tagging sth as pointers.  
> >>> Rather
> >>> than that ops might get one of
> >>>
> >>>    enum vr_preference { VR_PREF_SMALL, VR_PREF_NONNULL, 
> >>> VR_PREF_NONNEGATIVE, ... }
> >>>
> >>> ?
> >>
> >> Neat.  I think this is worth exploring, but perhaps something to be
> >> looked at as a further enhancement?
> >>
> >>>
> >>>>>
> >>>>> So - in the end I'm not convinced that adding this kind of interface
> >>>>> to the wide_int_ variants is worth it and I'd rather keep the existing
> >>>>> VRP code?
> >>>>
> >>>> Again, I don't want to depend on vr_values or VRP in general.
> >>>
> >>> Sure.  But the general handling of the ops (just treat POINTER_PLUS like 
> >>> PLUS)
> >>> should do range operations just fine.  It's only the preferencing you'd 
> >>> lose
> >>> and that preferencing looks like a more general feature than "lets have 
> >>> this
> >>> function dealing with a small subset of binary ops on pointers"?
> >>
> >> Something like MIN/MAX, that is specially handled for binary ops, can't
> >> be treated with the general min/max range operations.  Take for instance
> >> MIN(NULL, NON-NULL) which is basically MIN([0], [1..MAX]).  Generic
> >> range ops would yield 0/NULL, whereas current VRP returns VARYING.
> >>
> >> Similarly for BIT_AND_EXPR.  Imagine [1,5] & [10,20] for pointers.
> >> Handling this generically would yield [0] (NULL), whereas the correct
> >> answer is NON-NULL.  And yes, [1,5] and [10,20] can actually happen, as
> >> I've mentioned in another thread.  I think it's libgcc that has code
> >> that does:
> >>
> >> if (some_pointer == (pointer_type *) 1)
> >> else if (some_pointer == (pointer_type *) 2)
> >> etc etc.
> >>
> >> Again, I think we could address your preference idea as an enhancement
> >> if you feel strongly about it.
> >
> > Ah, OK.  It basically boils down to pointer operations having special 
> > semantics
> > (similar to overflow definedness).
>
> Yes.
>
> >
> >> We could make wide_int_range_pointer an inline function, and the penalty
> >> for VRP would only be the conversion to wide ints in vrp_range_pointer
> >> (extract_range_into_wide_ints actually).
> >>
> >>>
> >>> The preferencing above would get passed down to the range unioning code.
> >>>
> >>> Btw, since your wide-int-range code doesn't even have ANTI_RANGE, how
> >>> do you represent non-zero in the API?
> >>
> >> The way god intended of course, with the truth!  As I said earlier:
> >>
> >>   >> Our upcoming work has another representation for non-nulls in 
> >> particular
> >>   >> ([-MIN,-1][1,+MAX]), since we don't have anti ranges.
> >>
> >> :-)
> >>
> >>>
> >>> As said, splitting this out in the way of your patch looks "premature",
> >>> there's not enough of the big picture visible for me to say it makes 
> >>> sense.
> >>
> >> You could always look at svn/ssa-range :-P.  It's been merged with
> >> mainline as of early last week.
> >
> > Eh.
> >
> >> Splitting this out makes my life a lot easier, with virtually no penalty
> >> to VRP.  And we could always revisit it later.  But if you feel strongly
> >> about it, I could inline the pointer handling into our code, and revisit
> >> this later with you.
> >
> > Yeah, please do so - I'm leaving for the Cauldron soon.  Looking at
> > the current wide-int-range.h header doesn't reveal a consistent API :/
>
> Suggestions welcome :).
>
> Just to make sure, was that OK and approval, provided I make the
> function an inline?

It was to "inline the pointer handling into our code"

>
> Thanks, and see you at Cauldron (albeit a few days late).
> Aldy

Reply via email to