On 07/26/2017 05:20 AM, Richard Biener wrote:
> On Tue, Jul 25, 2017 at 4:50 PM, Andrew MacLeod <amacl...@redhat.com> wrote:
>> On 07/25/2017 03:12 AM, Richard Biener wrote:
>>>
>>> On Fri, Jul 21, 2017 at 9:30 PM, Aldy Hernandez <al...@redhat.com> wrote:
>>>>
>>>> On Mon, Jul 17, 2017 at 6:23 AM, Richard Biener
>>>> <richard.guent...@gmail.com> wrote:
>>>>>
>>>>> On Mon, Jul 17, 2017 at 8:51 AM, Aldy Hernandez <al...@redhat.com>
>>>>> wrote:
>>>>>>
>>>>>> How does this look?
>>>>>
>>>>> It's a change that on its own doesn't look worthwhile to me.
>>>>>
>>>>> So please post the changes that will build ontop of this.  Like removing
>>>>> anti-ranges from VRP or your on-demand value-range stuff.
>>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>
>>>>  From the looks of it, we can have a variety of VRP ranges that are not
>>>> representable at all with the an integer range class.  For instance, I
>>>> see the following ranges built in set_value_range():
>>>>
>>>> [INT, (nop_expr SSA)]
>>>>
>>>> [INT, (plus_expr SSA INT)]
>>>>
>>>> [(negate_expr SSA), (negate_expr SSA)]
>>>>
>>>> [(plus_expr (negate_expr SSA INT)),
>>>>   (plus_expr (negate_expr SSA) INT)]
>>>>
>>>> [SSA, SSA]
>>>>
>>>> So...I guess the first suggestion is out of the question ;-).
>>>
>>> Well.  We do not want range operations implemented twice (really!)
>>> so range operations need to work on both representations.  So we
>>> should think of a way to get rid of anti-ranges in VRP which, frankly,
>>> means that for the sake symbolic ranges we have to trade them
>>> with handling open/closed ranges which I'm not sure will be less of
>>> a hassle to handle?
>>
>>
>> I originally looked at ranges with symbolic expressions, but as soon as
>> there are ranges comprised of more than 1 range, symbolics became a
>> nightmare.  At best you can do endpoints, and even then you have to start
>> adding complexity..  [0, 100] Union  [5, x_4]  now has to become  [0,
>> max(100, x_4)] , and chained operations were making the expressions more and
>> more complicated.  Trying to maintain these expression across optimizations
>> was also very problematic as the IL changes and these expressions are not in
>> the IL and don't suffer updates easily.
>>
>> At which point one asks themselves whether it actually makes sense to
>> integrate that into the range representation, or try a different tactic.
>>
>> Seems to me its cleaner to have an integral range, and when appropriate
>> track symbols separately to determine if their values can be refined.    If
>> at some point you can resolve those symbols to an integral value,  then you
>> simply update the integral range with the new range you've determined.
>>
>> VRP chooses to do this by creating a completely different structure for
>> ranges, and representing endpoints as expression trees. It then updates the
>> integral ranges at the end of the pass. It uses anti-ranges as a shorthand
>> to handle a special case of a range comprised of 2 ranges.  As it stands
>> right now, VRP's version of union and intersection can never have much in
>> common with a general integral range implementation. They are 2 very
>> different beasts.
>>
>> So we cant do much about VRP internally yet without some significant
>> surgery.
>>
>> This issue seems orthogonal to me though.  irange is not intended to ever do
>> anything with symbols, thus can never replace VRPs internal value_range
>> class.    We're simply replacing "struct range_info_def" with a new range
>> structure and API which can support more precise ranges than a pair of
>> integral endpoints.  We'll then build on that by providing routines which
>> can generate more precise range information as well.
>>
>> For the moment we provide an implementation with the same precision to
>>   a) ensure code generation remains the same
>>   b) allow the compiler to use it for a while to make sure no bugs have been
>> introduced
>>   c) and there is nothing that would utilize the additional precision yet
>> anyway.
>>
>> I just think its important to get it in the code base so its being used and
>> we can be sure its correct.
> 
> But nothing uses all the methods.
> 
> And we're ending up with two variants of range + range, etc.
But I think this is inevitable.  Consider for example floating point
ranges.  There's a belief that a limited form of VRP would be useful
(essentially tracking if the FP value could have the value 0 and perhaps
tracking NaNs as well).  We're not likely to be tracking actual values,
but boolean states about what values an object may or may not have.

I could also well see building another set of evaluation routines which
track zero, nonzero and unknown bits for integer values on top of the
basic framework Andrew is working on.

To some degree symbolics feel the same in that I suspect that we most
often are going to want to work with them as expressions.

Which leads me to wonder if we really need to templateize all the new
code so that we can have a different storage for the ranges and
different ways to extract ranges from operations we see.

Additionally, Andrew claims that handling symbolics really isn't needed
-- I'm still wrapping my head around all the implications of the
terminal names and how we can utilize them.


The more I think about the general desire to eliminate the range
extraction and propagation step from VRP and instead build on top of
this framework is going to require doing something with symbolics, plain
and simple.  We're not going to be able to remove those hunks of VRP if
we don't do *something* for symbolics.

So I come back to the do we template-ize irange so that we get frange,
srange and possibly others, do we change the underlying storage to
trees, or do  we have a polymorphic data structure that adjusts to the
integer, floating and symbolic handling?


> 
> irange is a nearly subset of what VRP can handle so it should be able to 
> re-use
> VRP workers.  The 'nearly' part is that VRP currently doesn't handle multiple
> ranges.  For an unknown reason you didn't start with teaching VRP that bit.
Perhaps, but the general belief is that VRP as we know it today wouldn't
exist in this new world.  Computation of range information would be
separate from utilizing range information for optimization/analysis
purposes.


One approach would be to take the existing bits from VRP and try to pull
them out into its own little module, then extending it to allow the
kinds of queries we need to do.  We felt it was actually going to be
better to start over, building a system to answer the queries we want
from the ground up.

The belief is that what we're going to end up would replace huge amounts
of VRP (eliminating ASSERT_EXPRs and anti-ranges along the way).

> 
> Yes, symbolic ranges complicate that conversion a bit (getting rid of
> anti-ranges
> in VRP) but you could have either kept anti-ranges for symbolic ranges only
> or have open/closed ranges.  The issue with symbolic ranges here is that
> from
> 
>   if (a != b)
> 
> we derive a symbolic range for a that is ~[b, b].  If you want to make that
> a union of two ranges you have [MIN, b - 1] U [b + 1, MAX] _but_ both
> b - 1 or b + 1 might actually overflow!  So you need to use [MIN, b[ U ]b, 
> MAX]
> here (which means both can be empty if b == MIN or b == MAX).
But how often is this useful in practice and how much are we willing to
pay to get this level of generality?  I wonder if just the ability to
record simple symbolics and very simple manipulations is sufficient to
do what we need in practice.


Jeff

Reply via email to