On Tue, Jul 15, 2014 at 6:29 PM, Prathamesh Kulkarni
<bilbotheelffri...@gmail.com> wrote:
> On Tue, Jul 15, 2014 at 6:05 PM, Richard Biener
> <richard.guent...@gmail.com> wrote:
>> On Mon, Jul 14, 2014 at 3:05 PM, Richard Biener
>> <richard.guent...@gmail.com> wrote:
>>> On Mon, Jul 14, 2014 at 12:07 PM, Prathamesh Kulkarni
>>> <bilbotheelffri...@gmail.com> wrote:
>>>> I was wondering if it was a good idea to implement
>>>> predicate on expressions ?
>>>>
>>>> Sth like:
>>>> (match_and_simplify
>>>> (op (op2:predicate @0))
>>>> transform)
>>>>
>>>> instead of:
>>>> (match_and_simplify
>>>> (op (op2@1 @0))
>>>> if (predicate (@1))
>>>> transform)
>>>>
>>>> When predicate is simple as just being a macro/function,
>>>> we could use this style and when the predicate is more complex
>>>> resort to using if-expr (or write the predicate as macro in
>>>> gimple-match-head.c
>>>> and use the macro in pattern instead ...)
>>>>
>>>> Example:
>>>> we could rewrite the pattern
>>>> (match_and_simplify
>>>> (plus:c @0 (negate @1))
>>>> if (!TYPE_SATURATING (type))
>>>> (minus @0 @1))
>>>>
>>>> to
>>>>
>>>> (match_and_simplify
>>>> (plus:c:NOT_TYPE_SATURATING_P @0 (negate @1))
>>>> (minus @0 @1))
>>>>
>>>> with NOT_TYPE_SATURATING_P predicate defined
>>>> appropriately in gimple-match-head.c
>>>>
>>>> However I am not entirely sure if adding predicates on expressions
>>>> would be very useful....
>>>
>>> Well. I think there are two aspects to this. First is pattern
>>> readability where I think that the if-expr form is more readable.
>>> Second is the ability to do less work in the code generated
>>> from the decision tree.
>>>
>>> For example most of the patterns from associate_plusminus
>>> still miss the !TYPE_SATURATING && !FLOAT_TYPE_P &&
>>> !FIXED_POINT_TYPE_P if-expr. That is, we'd have
>>>
>>> /* (A +- B) - A -> +-B. */
>>> (match_and_simplify
>>> (minus (plus @0 @1) @0)
>>> if (!TYPE_SATURATING (type)
>>> && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
>>> @1)
>>> (match_and_simplify
>>> (minus (minus @0 @1) @0)
>>> if (!TYPE_SATURATING (type)
>>> && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
>>> (negate @1))
>>> /* (A +- B) -+ B -> A. */
>>> (match_and_simplify
>>> (minus (plus @0 @1) @1)
>>> if (!TYPE_SATURATING (type)
>>> && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
>>> @0)
>>> (match_and_simplify
>>> (plus:c (minus @0 @1) @1)
>>> if (!TYPE_SATURATING (type)
>>> && !FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type))
>>> @0)
>>>
>>> with code-generation checking the if-expr after matching. And
>>> with using expression predicates we'd be able to check the
>>> predicate when matching the outermost 'minus' and "CSE"
>>> the predicate check for the first three patterns. Runtime-wise
>>> it depends on whether there is a point to back-track to.
>>
>> Actually now that I look at the current state of the testsuite on the
>> branch and notice
>>
>> FAIL: gcc.c-torture/execute/20081112-1.c execution, -O1
>>
>> which points at
>>
>> (match_and_simplify
>> (plus (plus @0 INTEGER_CST_P@1) INTEGER_CST_P@2)
>> (plus @0 (plus @1 @2))
>>
>> which we may not apply to (a - 1) + INT_MIN as -1 + INT_MIN
>> overflows and a + (-1 + INT_MIN) then introduces undefined
>> signed integer overflow. tree-ssa-forwprop.c checks TREE_OVERFLOW
>> on the result of (plus @1 @2) and disables the simplification
>> properly. We can do the same with re-writing the pattern to
>>
>> (match_and_simplify
>> (plus (plus @0 INTEGER_CST_P@1) INTEGER_CST_P@2)
>> /* If the constant operation overflows we cannot do the transform
>> as we would introduce undefined overflow, for example
>> with (a - 1) + INT_MIN. */
>> if (!TREE_OVERFLOW (@1 = int_const_binop (PLUS_EXPR, @1, @2)))
>> (plus @0 @1))
>>
>> also using something I'd like to more formally allow (re-using sth
>> computed in the if-expr in the replacement). But of course writing
>> it this way is ugly and the following would be nicer?
>>
>> (match_and_simplify
>> (plus (plus @0 INTEGER_CST_P@1) INTEGER_CST_P@2)
>> (plus @0 (plus:!TREE_OVERFLOW @1 @2)))
>>
>> ? That would be predicates on replacement expressions ...
>> (also negated predicates).
> Or maybe allow intermingling c-expr and expr ?
> (match_and_simplify
> (plus (plus @0 INTEGER_CST_P@1) INTEGER_CST_P@2)
> /* If the constant operation overflows we cannot do the transform
> as we would introduce undefined overflow, for example
> with (a - 1) + INT_MIN. */
> {
> tree sum;
> sum = int_const_binop (PLUS_EXPR, @1, @2);
> if (!TREE_OVERFLOW (sum))
> (plus @0 @1)
(plus @0 sum)
This is not good....
> else
> FAIL;
> })
>
> However the predicates version looks better, compared to others...
>
> Thanks and Regards,
> Prathamesh
>> Now it doesn't look all-that-pretty :/
>>
>> Another possibility is to always fail if TREE_OVERFLOW constants
>> leak into the replacement IL. (but I'd like to avoid those behind-the-backs
>> things at the moment)
>>
>> Richard.