On Mon, Aug 4, 2014 at 12:16 AM, Prathamesh Kulkarni
<bilbotheelffri...@gmail.com> wrote:
> On Thu, Jul 31, 2014 at 2:49 PM, Prathamesh Kulkarni
> <bilbotheelffri...@gmail.com> wrote:
>> On Thu, Jul 31, 2014 at 2:44 PM, Richard Biener
>> <richard.guent...@gmail.com> wrote:
>>> On Thu, Jul 31, 2014 at 11:09 AM, Prathamesh Kulkarni
>>> <bilbotheelffri...@gmail.com> wrote:
>>>> On Thu, Jul 31, 2014 at 2:15 PM, Richard Biener
>>>> <richard.guent...@gmail.com> wrote:
>>>>> On Thu, Jul 31, 2014 at 7:41 AM, Prathamesh Kulkarni
>>>>> <bilbotheelffri...@gmail.com> wrote:
>>>>>> On Wed, Jul 30, 2014 at 11:49 PM, Prathamesh Kulkarni
>>>>>> <bilbotheelffri...@gmail.com> wrote:
>>>>>>> On Wed, Jul 30, 2014 at 4:49 PM, Richard Biener
>>>>>>> <richard.guent...@gmail.com> wrote:
>>>>>>>> On Wed, Jul 30, 2014 at 1:11 PM, Richard Biener
>>>>>>>> <richard.guent...@gmail.com> wrote:
>>>>>>>>> On Wed, Jul 30, 2014 at 12:49 PM, Prathamesh Kulkarni
>>>>>>>>> <bilbotheelffri...@gmail.com> wrote:
>>>>>>>>>> Hi,
>>>>>>>>>>    Sorry to ask a stupid question, but I am having issues writing 
>>>>>>>>>> patterns
>>>>>>>>>> involving casts. I am trying to write patterns from simplify_rotate.
>>>>>>>>>>
>>>>>>>>>> Could you show me how to write a patterns that involve
>>>>>>>>>> casts ?
>>>>>>>>>> for eg:
>>>>>>>>>> ((T) ((T2) X << CNT1)) + ((T) ((T2) X >> CNT2))     iff CNT1 + CNT2 
>>>>>>>>>> == B
>>>>>>>>>> T -> some unsigned type with bitsize B, and some type T2 wider than 
>>>>>>>>>> T.
>>>>>>>>>> How to express this in the pattern ?
>>>>>>>>>
>>>>>>>>> [copying gcc@ because of the syntax stuff]
>>>>>>>>>
>>>>>>>>> for example with (leaving captures as the appear in the pattern above)
>>>>>>>>>
>>>>>>>>> (match_and_simplify
>>>>>>>>>    (plus (convert@2 (lshift (convert@0 X) CNT1))
>>>>>>>>>            (convert (rshift (convert@1 X) CNT2)))
>>>>>>>>>     /* Types T2 have to match */
>>>>>>>>>    (if (types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1))
>>>>>>>>>         /* Type T should be unsigned.  */
>>>>>>>>>        && TYPE_UNSIGNED (TREE_TYPE (@2))
>>>>>>>>>        /* T2 should be wider than T.  */
>>>>>>>>>        && TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE 
>>>>>>>>> (@2))
>>>>>>>>>        /* CNT1 + CNT2 == B */
>>>>>>>>>        && wi::eq_p (TYPE_PRECISION (TREE_TYPE (@2)),
>>>>>>>>>                            wi::add (CNT1, CNT2))))
>>>>>>>>>    (lrotate CNT1))
>>>>>>>>
>>>>>>>> Note that this will _explicitely_ require a conversion.  That is, if T 
>>>>>>>> == T2
>>>>>>>> it won't match because the conversion to T will not be there, nor if X
>>>>>>>> is already of type T2.
>>>>>>>>
>>>>>>>> Which means that we want to match multiple variants of this
>>>>>>>> (with conversions in place or not).  Hmm.  Maybe with extending 'for' 
>>>>>>>> like
>>>>>>>>
>>>>>>>> (for cvt1 in convert *
>>>>>>>>   (fot cvt2 in convert *
>>>>>>>>     (plus@2 (cvt1 (lshift@0 (cvt2 X) CNT1))
>>>>>>>>                  (cvt1 (rshift@1 (cvt2 X) CNT2)))
>>>>>>>> ...
>>>>>>>>
>>>>>>>> adding an "empty" operator to the list of operators to substitute for 
>>>>>>>> cvt1
>>>>>>>> and allowing nested for.  The "empty" operator would necessarily be
>>>>>>>> unary and be just un-wrapped.
>>>>>>> Would it be better to have syntax (say using ?) for denoting that an
>>>>>>> operator is optional ?
>>>>>>> operator should be unary, and it's operand must be an expression.
>>>>>>>
>>>>>>> so the pattern becomes sth like:
>>>>>>> (plus@2 (convert? (lshift@0 (convert? X) CNT1))
>>>>>>>              (convert? (rshift@1 (convert? X) CNT2)))
>>>>>>>
>>>>>> Let me rephrase it.
>>>>>> An operator can be marked optional, if
>>>>>> a) it's unary
>>>>>> b) if in outermost-expr, the operand must be an expression
>>>>>>
>>>>>> I want to reject case like:
>>>>>> (negate? @0)
>>>>>>
>>>>>> (op? operand)
>>>>>> generates code :
>>>>>> match (op)
>>>>>>    match (operand)
>>>>>>
>>>>>> and once without op
>>>>>> match (operand)
>>>>>>
>>>>>> Implementation-wise I think, we could duplicate the AST, like we do
>>>>>> for "for pattern".
>>>>>> Would that be okay ?
>>>>>
>>>>> I thought of something similar but how exactly would you do the
>>>>> duplication in the above example?  The point is that we know
>>>>> that the conversions will exist in pairs, that is, either
>>>>> the two outer and no inner or no outer and both inner or
>>>>> both outer and both inner.  You can express that with the
>>>>> nested for - with just a '?' you can't do that.  Of course you could
>>>>> do sth like
>>>>>
>>>>> (plus@2 (convert?1 (lshift@0 (convert?2 X) CNT1))
>>>>>              (convert?1 (rshift@1 (convert?2 X) CNT2)))
>>>>>
>>>>> that is, add an index to ?s and tie them together.  We want to
>>>>> avoid generating useless patterns - in this case 4 are sufficient
>>>>> but if we generate all possible combinations we'd have an additional
>>>>> 12 useless patterns.
>>>> Ah yes, didn't realize that, thanks.
>>>>>
>>>>> But using '?' indeed looks better than (ab)using 'for'.  Note that
>>>>> it is _only_ 'convert' that I can see this useful for (or can you
>>>>> think of other cases?).  So maybe we instead want to make
>>>>> it a special operator like
>>>>>
>>>>> (plus@2 (opt_convert 1 (lshift@0 (opt_convert 2 X) CNT1))
>>>>>              (opt_convert 1 (rshift@1 (opt_convert 2 X) CONT2)))
>>>>>
>>>>> with an additional operand specifying the group (or simply
>>>>> have opt_convert1 and opt_convert2 operands - hoping for
>>>>> more "groups" to never happen ;)).
>>>>>
>>>>> Actually I like opt_convert[123] most.
>>>> I like opt_convert[123] too.
>>>> Implementation-wise I don't think it would be more difficult to
>>>> generalize it for other operators ...
>>>
>>> Of course, but I don't see the need for that.  Conversions are really
>>> special in this regard.
>>>
>>>> I was thinking about this ... Instead of grouping by indexes,
>>>> how about defining operator aliases ?
>>>> sth like:
>>>> (define_op cvt1 convert)
>>>> (define_op cvt2 convert)
>>>>
>>>> and then the pattern becomes:
>>>>
>>>> (plus@2 (cvt1? (lshift@0 (cvt2? X) CNT1))
>>>>              (cvt1? (rshift@1 (cvt2? X) CNT2)))
>>>>
>>>> that would avoid generating useless patterns (since cvt1, cvt2 are
>>>> "different"), however during code-gen
>>>> both shall map to CONVERT_EXPR (and once without it since its optional).
>>>
>>> Yeah, that would work if we'd implement it that way.  Still I don't like
>>> a general '?' facility unless we come up with really good uses apart from
>>> conversions.
>> Agreed. I will start with implementing opt_convert.
> I have attached patch, that implements opt_convert.
> The implementation is not very efficient (i hope we can combine
> replace_opt_convert and lower_opt_convert).
>
> Some issues with implementation:
> a) since OPT_CONVERT is not defined in tree.def, i added it after
> #include tree.def in enum tree_code.
> So our enum tree_code becomes different from the usual enum tree_code.
>
> b) checks if there's any opt_convert remaining before lowering it to CONVERT
> and once removing it (this leads to walking AST thrice per each group).
> We can probably combine lower_opt_convert, remove_opt_convert and
> has_opt_convert into one function.
>
> c) opt_convert cannot be captured, for instance doesn't make sense
> when it's operand is not an expression
> eg - (opt_convert 1 @0)
> Or maybe allow capturing if the operand is expression ?

Hmm.  Capturing the convert may be necessary though as we usually
have to constrain allowed conversions.  Like

 (convert?@0 @1)
 if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@1))

to allow an optional widening convertsion.  But yes, we can't
possibly evaluate that if-expression if the convert is not there.

Bummer.

That rules out this way of doing a conditional conversion.

OTOH we can simply make the capturing of the conversion
capture its operand if it is not there?

> d) Use of opt_convert inside for operator-list is rejected.
> eg - (for op in convert opt_convert bit_not)
>
> * Changing syntax:
> I was wondering if instead of having new operator like opt_convert, we
> could reuse convert ?
> convert becomes optional if it's followed with '?'
> eg:
> (convert? 1 @0) is "optional convert".
> or maybe use colon ?
> (convert:1 @0) ?
> (IMHO '?' is slightly better since it's typically used to denote
> "optional" in regexp, but
> '? number' looks somewhat out of place in the pattern, ': number' looks 
> better).

Hmm, then if we resort to predicate/flag syntax why not do
convert:?1 or convert:? convert:?? convert:??? with the number
of ?s also providing the match-number.  Of course that makes
it look like a generic flag when we should only accept it on converts.

Or do convert1?  I don't like the binary form or the number following
the ? (looks too much like a capture).  Note that convert1? lexes
as one identifier followed by a ? though.

> the above pattern becomes:
> (plus@2 (convert? 1 (lshift@0 (convert? 2 X) CNT1))
>              (convert? 1 (rshift@1 (convert? 2 X) CNT2)))
>
> "optional" converts won't be allowed to get captured (non-optional convert 
> yes).

See above - we should capture its operand if it is not there.

So I think let's go with convert1? and allow capturing.  Doing that
with appending CONVERT1, CONVERT2, ... to tree.def works for me.

Richard.

>
> * genmatch.c (enum tree_code): New value OPT_CONVERT.
>       (e_operation): New member unsigned group_index.
>       (e_operation::e_operation): Add new default argument.
>                                               Adjust to changes in 
> e_operation.
>       (remove_opt_convert): New function.
>       (has_opt_convert): Likewise.
>       (lower_opt_convert): Likewise.
>       (lower_opt_convert): New overloaded function.
>       (lower_opt_convert): Likewise.
>       (parse_expr): Adjust to parse opt_convert.
>       (parse_for): Reject opt_convert in opers.
>       (main): Call lower_opt_convert.
>
> Thanks,
> Prathamesh
>>
>> Thanks,
>> Prathamesh.
>>>
>>> Richard.
>>>
>>>> Thanks,
>>>> Prathamesh
>>>>
>>>>>
>>>>> Richard.
>>>>>
>>>>>> Thanks,
>>>>>> Prathamesh
>>>>>>
>>>>>>
>>>>>>> Thanks,
>>>>>>> Prathamesh
>>>>>>>
>>>>>>>>
>>>>>>>> Extending for in this way avoids treating conversions specially
>>>>>>>> (I don't see an easy way to do very good at that automagically).  We
>>>>>>>> need multiple patterns in the decision tree here anyway.
>>>>>>>>
>>>>>>>> Now guess sth fancy in place of '*' ...
>>>>>>>>
>>>>>>>> Lisp style would be less free-form like
>>>>>>>>
>>>>>>>> (for cvt (convert ())
>>>>>>>>
>>>>>>>> where we could use an empty list for the "empty" operator.
>>>>>>>>
>>>>>>>> Is nested for support already implemented?
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Richard.
>>>>>>>>
>>>>>>>>> which suggests that we may want to add some type capturing / matching
>>>>>>>>> so we can maybe write
>>>>>>>>>
>>>>>>>>>   (plus (convert@T (lshift (convert@T2 X) CNT1))
>>>>>>>>>           (convert (rshift (convert@T2 X) CNT2)))
>>>>>>>>>   (if (/* T2s will be matched automagically */
>>>>>>>>>        && TYPE_UNSIGNED (@T)
>>>>>>>>>        && TYPE_PRECISION (@T2) > TYPE_PRECISION (@T)
>>>>>>>>>        && wi::eq_p (TYPE_PRECISION (@T), wi::add (CNT1, CNT2))))
>>>>>>>>>
>>>>>>>>> which is less to type and supports requiring matching types.  Maybe
>>>>>>>>> require @T[0-9]+ here thus use @T0 and disallow plain @T.  We could
>>>>>>>>> then also use @T for the implicitely "captured" outermost type we
>>>>>>>>> refer to as plain 'type' right now.
>>>>>>>>>
>>>>>>>>> I suggest to go ahead without a new syntax for now and see if it
>>>>>>>>> gets unwieldingly ugly without first.
>>>>>>>>>
>>>>>>>>>> For this week, I have planned:
>>>>>>>>>> a) writing patterns from simplify_rotate
>>>>>>>>>> b) replacing op in c_expr
>>>>>>>>>> c) writing more test-cases.
>>>>>>>>>>
>>>>>>>>>> If there's anything else you would like me to do, I would be happy
>>>>>>>>>> to know.
>>>>>>>>>
>>>>>>>>> Just keep an eye open for things like above - easy ways to reduce
>>>>>>>>> typing for patterns.
>>>>>>>>>
>>>>>>>>> Btw, I suggest to split up match.pd by code you converted from.  Thus
>>>>>>>>> for simplify_rotate add
>>>>>>>>>
>>>>>>>>>   match-simplify-rotate.pd
>>>>>>>>>
>>>>>>>>> with the patterns and do a #include "match-simplify-rotate.pd"
>>>>>>>>> in match.pd.  That will make it easier to match the two later.
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Richard.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> Thanks,
>>>>>>>>>> Prathamesh

Reply via email to