2011/7/8 Richard Guenther <richard.guent...@gmail.com>:
> On Fri, Jul 8, 2011 at 4:35 PM, Kai Tietz <ktiet...@googlemail.com> wrote:
>> 2011/7/8 Richard Guenther <richard.guent...@gmail.com>:
>>> On Thu, Jul 7, 2011 at 6:28 PM, Kai Tietz <ktiet...@googlemail.com> wrote:
>>>> 2011/7/7 Paolo Bonzini <bonz...@gnu.org>:
>>>>> On 07/07/2011 06:07 PM, Kai Tietz wrote:
>>>>>>
>>>>>> +  /* We redo folding here one time for allowing to inspect more
>>>>>> +     complex reductions.  */
>>>>>> +  substitute_and_fold (op_with_constant_singleton_value_range,
>>>>>> +                      vrp_fold_stmt, false);
>>>>>> +  /* We need to mark this second pass to avoid re-entering of same
>>>>>> +     edges for switch statments.  */
>>>>>> +  in_second_pass = true;
>>>>>>    substitute_and_fold (op_with_constant_singleton_value_range,
>>>>>>                       vrp_fold_stmt, false);
>>>>>> +  in_second_pass = false;
>>>>>
>>>>> This needs a much better explanation.
>>>>>
>>>>> Paolo
>>>>
>>>> Well, I can work on a better comment.  The complex reduction I mean
>>>> here are cases like
>>>>
>>>> int x;
>>>> int y;
>>>> _Bool D1;
>>>> _Bool D2;
>>>> _Bool D3;
>>>> int R;
>>>>
>>>> D1 = x[0..1] != 0;
>>>> D2 = y[0..1] != 0;
>>>> D3 = D1 & D2
>>>> R = (int) D3
>>>>
>>>> (testcase is already present. See tree-ssa/vrp47.c).
>>>>
>>>> As VRP in first pass produces (and replaces) to:
>>>>
>>>> D1 = (_Bool) x[0..1];
>>>> D2 = (_Bool) y[0..1];
>>>> D3 = D1 & D2
>>>> R = (int) D3
>>>>
>>>> Just in the second pass the reduction
>>>>
>>>> R = x[0..1] & y[0..1]
>>>
>>> So why wouldn't that happen during the first pass?  The first
>>> pass could change the IL to
>>>
>>>  D1 = x[0..1] != 0;
>>>  D2 = y[0..1] != 0;
>>>  D3 = D1 & D2;
>>>  R = x & y;
>>>
>>> if D3 only has a single use.
>> No, as D3 would need a type change, and this isn't possible.  If it
>> wasn't absolutely clear, this patch to VRP is necessary after patch 2,
>> as here D1, D2, and D3 have bool-type, and just R is of type int.
>
> In your example x,y and R are int, so it works with re-using R.
Well, if we add pattern match with prefixed cast, it works. This
actual my patch does, as it finds out that D1's and D2's operand is of
kind int, and matches R's type. So it uses R to simplify.  This
pattern is better then nothing, but more complex operations can't be
handled without introducing new statements.

Eg:

int foo (int a, int b, int c)
{
  if (a < 0 || a > 1 || b < 0 || b > 1 || c < 0 || c > 1)
    return -1;
  return (a != 0 | b != 0) | c != 0;
}

Here we get:

int a; int b; int c;
_Bool D1, D2, D3, D4;
int R;

...

D1 = (bool) a;
D2 = (bool) b;
D3 = (bool) c;
D4 = D1 | D2;
D5 = D4 | D3
R = (int) D5;

This can't be simplified by VRP without inserting new statement.

>>>> can happen.  In general it is sad that VRP can't insert during pass
>>>> new statements right now.  This would cause issues in range-tables,
>>>> which aren't designed for insertations.  As otherwise, we could do
>>>> also simplify things like
>>>>
>>>> D1 = x[0..1] != 0;
>>>> D2 = y[0..1] == 0;
>>>> D3 = D1 & D2
>>>> R = (int) D3
>>>>
>>>> to
>>>> R = x[0..1] & (y[0..1] ^ 1)
>>>
>>> Why that ^ 1?  And why does that confuse the range tables
>>> if you re-use R?
>> Because we would need to insert a new statement and this isn't allowed
>> in VRP. See the comments in VRP and substitute_and_fold.  VRP
>> disallows to remove statements or to insert new ones.
>
> That's not a hard limitation.

Hmm, ok. I played by it for a while to add this, but some later passes
like switch-range analyzis and jump-threading (IIRC) getting confused
by this.  AFAIU are the major culprits here the inserted ASSERTs, but
maybe I am wrong about this.

Kai

Reply via email to