On June 13, 2014 11:48:13 PM CEST, Prathamesh Kulkarni 
<bilbotheelffri...@gmail.com> wrote:
>On Thu, Jun 12, 2014 at 4:26 PM, Richard Biener
><richard.guent...@gmail.com> wrote:
>> On Wed, Jun 11, 2014 at 4:09 PM, Prathamesh Kulkarni
>> <bilbotheelffri...@gmail.com> wrote:
>>> On 6/11/14, Richard Biener <richard.guent...@gmail.com> wrote:
>>>> On Wed, Jun 11, 2014 at 12:53 PM, Richard Biener
>>>> <richard.guent...@gmail.com> wrote:
>>>>> On Wed, Jun 11, 2014 at 10:51 AM, Richard Biener
>>>>> <richard.guent...@gmail.com> wrote:
>>>>>> On Tue, Jun 10, 2014 at 1:57 PM, Richard Biener
>>>>>> <richard.guent...@gmail.com> wrote:
>> [...snip...]
>>>>>>> But then why not generate
>>>>>>>
>>>>>>>   if (!captures[0]
>>>>>>>       || captures[0] == op0)
>>>>>>>     {
>>>>>>>       captures[0] = op0;
>>>>>>>       // simplification code S1
>>>>>>>       return true;
>>>>>>>     }
>>>>>>>
>>>>>>> and go without label and goto?  Or did I miss something?
>>>>>>>
>>>>>>>> c) Shared captures between all patterns:
>>>>>>>> In the patch all patterns share the capture array tree
>captures[4] =
>>>>>>>> {}
>>>>>>>> (since all match patterns get interleaved in generated code off
>>>>>>>> decision tree).
>>>>>>>> This requires extra code to be generated to make sure captures
>are
>>>>>>>> correctly restored for another pattern.
>>>>>>
>>>>>> Btw, I see that you back-track the decision tree.  That is, for
>>>>>>
>>>>>> root
>>>>>> |--operand: MINUS_EXPR
>>>>>> |----operand: PLUS_EXPR
>>>>>> |------operand: @0
>>>>>> |--------operand: @1
>>>>>> |----------operand: @0
>>>>>> |------------simplify
>>>>>> |----------operand: @1
>>>>>> |------------simplify
>>>>>>
>>>>>> you do
>>>>>>
>>>>>>   if (code == MINUS_EXPR)
>>>>>>     {
>>>>>>       tree captures[4] = {};
>>>>>>       if (TREE_CODE (op0) == SSA_NAME)
>>>>>>         {
>>>>>>           gimple def_stmt = SSA_NAME_DEF_STMT (op0);
>>>>>>           if (is_gimple_assign (def_stmt) &&
>gimple_assign_rhs_code
>>>>>> (def_stmt) == PLUS_EXPR)
>>>>>>             {
>>>>>>               tree op01 = gimple_assign_rhs1 (def_stmt);
>>>>>>               if (valueize && TREE_CODE (op01) == SSA_NAME)
>>>>>>                 op01 = valueize (op01);
>>>>>>               else
>>>>>>                 goto L0;
>>>>>>               if (op01)
>>>>>>                 {
>>>>>> L0:
>>>>>>                   tree op11 = gimple_assign_rhs2 (def_stmt);
>>>>>>                   if (valueize && TREE_CODE (op11) == SSA_NAME)
>>>>>>                     op11 = valueize (op11);
>>>>>>                   else
>>>>>>                     goto L1;
>>>>>>                   if (op11)
>>>>>>                     {
>>>>>> L1:
>>>>>>                       tree captures_0 = captures[0];
>>>>>>                       if (!captures[0])
>>>>>>                         {
>>>>>>                           captures[0] = op01;
>>>>>>                           goto L2;
>>>>>>                         }
>>>>>>                       else if (captures[0] == op01)
>>>>>>                         {
>>>>>> L2:
>>>>>>                           tree captures_1 = captures[1];
>>>>>>                           if (!captures[1])
>>>>>>                             {
>>>>>>                               captures[1] = op11;
>>>>>>                               goto L3;
>>>>>>                             }
>>>>>>                           else if (captures[1] == op11)
>>>>>>                             {
>>>>>> L3:
>>>>>>                               tree captures_2 = captures[0];
>>>>>>                               if (!captures[0])
>>>>>>                                 {
>>>>>>                                   captures[0] = op1;
>>>>>>                                   goto L4;
>>>>>>                                 }
>>>>>>                               else if (captures[0] == op1)
>>>>>>                                 {
>>>>>> L4:
>>>>>>                                   res_ops[0] = captures[1];
>>>>>>                                   *res_code = TREE_CODE
>(res_ops[0]);
>>>>>>                                   return true;
>>>>>>                                 }
>>>>>>                               captures [0] = captures_2;
>>>>>>                               tree captures_3 = captures[1];
>>>>>>                               if (!captures[1])
>>>>>>                                 {
>>>>>>                                   captures[1] = op1;
>>>>>>                                   goto L5;
>>>>>>                                 }
>>>>>>                               else if (captures[1] == op1)
>>>>>>                                 {
>>>>>> L5:
>>>>>>                                   res_ops[0] = captures[0];
>>>>>>                                   *res_code = TREE_CODE
>(res_ops[0]);
>>>>>>                                   return true;
>>>>>>                                 }
>>>>>>                               captures [1] = captures_3;
>>>>>>                             }
>>>>>>                           captures [1] = captures_1;
>>>>>>                         }
>>>>>>                       captures [0] = captures_0;
>>>>>>                     }
>>>>>>                 }
>>>>>>             }
>>>>>>         }
>>>>>>
>>>>>> but if you processed all children of a decision tree node and
>didn't
>>>>>> hit one of the simplifies (which return true) then you know
>nothing
>>>>>> else will match and you can just return false.  That early out
>seems
>>>>>> to be missing completely and we fall through processing all
>siblings
>>>>>> of the parents.
>>>>>>
>>>>>> But maybe I am missing something?  I see that if I make capture
>>>>>> IDs not matching that we'd miss to detect things then (as a
>>>>>> "first" capture always "matches").
>>>>>>
>>>>>> root
>>>>>> |--operand: MINUS_EXPR
>>>>>> |----operand: PLUS_EXPR
>>>>>> |------operand: @0
>>>>>> |--------operand: @1
>>>>>> |----------operand: @0
>>>>>> |------------simplify
>>>>>> |------operand: @1
>>>>>> |--------operand: @0
>>>>>> |----------operand: @0
>>>>>> |------------simplify
>>>>>>
>>>>>> So I suppose we really have to distinguish "first" captures from
>>>>>> "matching" captures, basically not treating the "first" ones as
>>>>>> nodes of the decision tree and only populating the capture
>>>>>> array once we hit the code generation part of a pattern (well,
>>>>>> or the if-expr).
>>>>>
>>>>> It's probably a good idea to pre-parse the AST to classify
>>>>> captures and matches differently.  Given for example
>>>>>
>>>>> (plus @0 (minus@0 @1 @2))
>>>>>
>>>>> this would say (well, if we support this), that the plus has two
>>>>> "same" operands (on GIMPLE the "same" valueized SSA name)
>>>>> and that this operand is defined by a (minus @1 @2).  But with
>>>>> the current operator ordering in the decision tree we'd meet
>>>>> the no-op capture first and the match in an odd position.
>>>>>
>>>>> In the RTL machine description the matches are more explicit
>>>>> like
>>>>>
>>>>> (plus (match @0) (minus@0 @1 @2))
>>>>>
>>>>> so maybe we want to auto-detect those and rewrite the AST.
>>>>> Just distinguish between capture-def and capture-ref, where
>>>>> expression captures are always -def but leafs may be -refs as
>well.
>>>>>
>>>>> In the decision tree builder we'd "ignore" -defs and only make
>>>>> -refs explicit (and the -refs would need to "materialize" the
>-defs
>>>>> just like the ifexpr or transform stage).
>>>>>
>>>>> So I'd say add a flag to struct capture telling whether it's a ref
>>>>> and compute that via an AST traversal (that should then error
>>>>> for invalid refs).
>>>>>
>>>>> In the decision tree I'd keep a vector of operand * and record
>>>>> a name of a temporary the operand can be accessed via
>>>>> (in case any of the AST operands represented by the decision tree
>>>>> node has a capture associated).
>>>>>
>>>>> You'd still have "empty" leaf captures that would then only record
>>>>> the value into a temporary.
>>>>>
>>>>> Eventually you need a back-ref to the decision tree node for
>>>>> each capture when you insert a new AST traversal so you
>>>>> can decide whether a match (a capture-ref) refers to the same
>>>>> decision tree node or not.
>>>>>
>>>>> Richard.
>>>>
>>>> Ok, let me re-phrase after some more thinking and talking with
>>>> a collegue.
>>>>
>>>> When you do the AST traversal computing the array of AST operands *
>>>> you'd initialize book-keeping like the following
>>>>
>>>>  for operand in AST do
>>>>    if (operand is a capture)
>>>>     {
>>>>       if (this capture index was not yet seen)
>>>>         {
>>>>           record for this pattern (in its simplify node created at
>the
>>>>           decision tree leaf) that the capture index refers to the
>>>>           operand with the current index
>>>>           if (capture has a sub-expression)
>>>>             recurse
>>>>           else
>>>>             insert "true" op (matches everything)
>>>>         }
>>>>       else
>>>>         {
>>>>           generate a decision tree node that matches the decision
>>>>           tree index of the capture
>>>>           recurse
>>>>         }
>>>>     }
>>>>   else
>>>>     record op and recurse
>>>>
>>>> So when you generate code you implicitely capture all operands
>>>> in automatic variables named like 'captureN' with 'N' being the
>>>> current level of the decision tree (the index of the operand array
>>>> from the AST walk).  Once you hit a 'match-X' node you
>>>> simply match against the operand from the refered to decision
>>>> tree index.
>>>>
>>>> Once you reach the ifexpr point you populate the operands[] array
>>>> from the side-information you initialized in the AST traversal and
>>>> the automatic variables initialized from the decision tree walk.
>>>>
>>>> So
>>>>
>>>> (plus (minus@2 @1 @3) @2)
>>>>
>>>> would have the decision tree
>>>>
>>>> plus - minus - 'true' - 'true' - match(1) - simplify
>>>>
>>>> and the generated code would look like (simplified)
>>>>
>>>>   [can't capture outermost expr]
>>>>   if (code == plus)
>>>>     {
>>>>       op1 = gimple_assign_rhs1 (plus-stmt);
>>>>       if (TREE_CODE (op1) == minus)
>>>>         {
>>>>           op2 = gimple_assign_rhs1 (minus-stmt);
>>>>           if (true)
>>>>             {
>>>>               op3 = gimple_assign_rhs2 (minus-stmt);
>>>>               if (true)
>>>>                 {
>>>>                    op4 = gimple_assign_rhs2 (plus-stmt);
>>>>                    if (op4 == op1)
>>>>                      {
>>>>                         operands[0] = op2;
>>>>                         operands[1] = op1;
>>>>                         operands[2] = op3;
>>> Did you mean captures ?
>>> captures[0] = op2;
>>> captures[1] = op1;
>>> captures[2] = op3
>>
>> Yes, of course.
>>
>>>>                         <simplify>
>>>>
>>>> where the 'true' cases would be matched last (as "else") in case
>there
>>>> are multiplie choices here if you'd have also
>>>>
>>>> (plus @1 (minus @2 @3))
>>>>
>>>> the decision tree would become
>>>>
>>>> plus - minus - 'true' - 'true' - match(1) - simplify
>>>>         \
>>>>           'true' - minus - 'true' - 'true' - simplify
>>>>
>>> Thanks, I will get started on this. Today I added a patch that
>handles
>>> "matching-captures" but does not commonize, I am not not posting
>since
>>> it's of no
>>> use now. The above algorithm will also get rid of generating
>temporary
>>> as op<pos><level>.
>>
>> Indeed.  Note that it probably makes sense to do all the bookkeeping
>> setup in the decision tree insertion - splitting parts to the AST
>traversal
>> that builds the linear operand vector probably just complicates
>things.
>>
>>> suppose these are patterns:
>>> (plus @0 @1) S1
>>> (plus @1 @0) S2
>>>
>>> then how would be decision tree represented as ?
>>>
>>> plus - true - true - S1
>>>                         \
>>>                           S2
>>
>> Yes.
>>
>>> I suppose pattern-1 would always match (even with earlier code gen.
>>
>> Yes.  We might emit a warning if we detect such a case.
>>
>> Note that if we have
>>
>>   plus - true - S1
>>           \
>>             minus.... - S2
>>           \
>>             mult...  - S3
>>
>> then the code for the children of the plus node looks like
>>
>>     if (sub-code == minus)
>>     else if (sub-code == mult)
>>     else /*  if (true)  */
>>        S1;
>>
>> so a 'true' case has to be always processed last.
>For the pattern (made-up):
>(plus @0 (negate@0 @1)) S
>
>the decision-tree would look like the following: ?
>plus - true - negate - true - match (1) - simplify
>match (1) matches @0

You could also do

Plus - true - match(1) - negate - true

To avoid doing two things in one node.

Richard.

>and for the commutative variant:
>(plus (negate@0 @1) @0) S
>
>the decision tree would be the following: ?
>plus - negate - true - true - match (3) - simplify
>
>Thanks and Regards,
>Prathamesh
>>
>> Richard.
>>
>>>> Richard.
>>>>
>>>>>> There are also opportunities to optimize the generated code, but
>>>>>> basic correctness first I guess.
>>>>>>
>>>>>> I suppose we have to work a bit on the capture stuff.
>>>>>>
>>>>>> Btw, you can easily play with the code generator by doing inside
>>>>>> the gcc build directory
>>>>>>
>>>>>> obj/gcc> build/genmatch test.pd > test.c
>>>>>>
>>>>>> with a small test.pd. I used the following for the above
>examples:
>>>>>>
>>>>>> (match_and_simplify
>>>>>>   (MINUS_EXPR (PLUS_EXPR @0 @1) @0)
>>>>>>   @1)
>>>>>> (match_and_simplify
>>>>>>   (MINUS_EXPR (PLUS_EXPR @1 @0) @0)
>>>>>>   @1)
>>>>
>>>>>> Richard.
>>>>>>
>>>>>>>> I will change this to have capture per pattern
>>>>>>>> tree captures1[4] = {};  // for pattern-1
>>>>>>>> tree captures2[4] = {};
>>>>>>>
>>>>>>> Hmm, is this the matching captures issue I mentioned?  Btw, I
>see
>>>>>>> you do
>>>>>>>
>>>>>>> +void
>>>>>>> +walk_operand_preorder(vec<operand *>& operands, operand *op)
>>>>>>> +{
>>>>>>> +  if (op->type == operand::OP_CAPTURE || op->type ==
>>>>>>> operand::OP_PREDICATE || op->type == operand::OP_C_EXPR)
>>>>>>> +    {
>>>>>>> +      operands.safe_push (op);
>>>>>>> +      return;
>>>>>>> +    }
>>>>>>>
>>>>>>> but that leaves captured expressions as a single operand?
>>>>>>>
>>>>>>> (plus (minus@1 @2 @3) @2)
>>>>>>>
>>>>>>> would have a decision tree
>>>>>>>
>>>>>>>  plus -> minus -> @2
>>>>>>>
>>>>>>> correct?
>>>>>>>
>>>>>>>> d) Matching multiple patterns.
>>>>>>>> Code for patterns with same match, but different transforms is
>>>>>>>> generated as follows:
>>>>>>>> code for match operand.
>>>>>>>> if (if-expr of pattern-1)
>>>>>>>> {
>>>>>>>>   code for result of pattern-1
>>>>>>>>   return true;
>>>>>>>> }
>>>>>>>> if (if-expr of pattern-2)
>>>>>>>> {
>>>>>>>>   code for result of pattern-2
>>>>>>>>   return true;
>>>>>>>> }
>>>>>>>
>>>>>>> good.
>>>>>>>
>>>>>>>> ...
>>>>>>>> Should we emit a warning for patterns that have same match
>operand but
>>>>>>>> no if-expr and no manual transform ?
>>>>>>>>
>>>>>>>> for eg:
>>>>>>>> (match_and_simplify
>>>>>>>>   (plus (minus @0 @1) @1)
>>>>>>>>   @0
>>>>>>>>
>>>>>>>> (match_and_simplify
>>>>>>>>   (plus (minus @0 @1) @1)
>>>>>>>>   @1  // just for illustration
>>>>>>>>
>>>>>>>> Since the matching is ambiguous (same match, no if-expr, no
>manual
>>>>>>>> transform).
>>>>>>>
>>>>>>> Yeah, I suppose we should.
>>>>>>>
>>>>>>>> we are left to choose between result of pattern-1 and result of
>>>>>>>> pattern-2.
>>>>>>>> We can emit warning and choose result of pattern-1 (first-match
>rule
>>>>>>>> as in flex).
>>>>>>>>
>>>>>>>> e) Non-matching captures:
>>>>>>>> Haven't thought about this yet.
>>>>>>>>
>>>>>>>> * Should we add "negative" predicates that match only if the
>predicate
>>>>>>>> fails ?
>>>>>>>> for eg:
>>>>>>>> (match_and_simplify
>>>>>>>>   trunc_mod integer_zerop@0 !integer_zerop)
>>>>>>>>   @0)
>>>>>>>
>>>>>>> well, there could simply be a integer_not_zerop predicate.
>>>>>>>
>>>>>>>> * Testing
>>>>>>>> Sorry to bring this up again, but I am still not clear what
>regex to
>>>>>>>> write in scan-tree-dump.
>>>>>>>>
>>>>>>>> Suppose we have these two patterns in match.pd:
>>>>>>>> /* (x + y) - y -> x */
>>>>>>>> (match_and_simplify
>>>>>>>>   (minus (plus @0 @1) @1)
>>>>>>>>   @0)
>>>>>>>>
>>>>>>>> /* (x - y) + y -> x */
>>>>>>>> (match_and_simplify
>>>>>>>>   (plus (minus @0 @1) @1)
>>>>>>>>   @0)
>>>>>>>> scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*=
>>>>>>>> x_\\d\+\\(D\\)"
>>>>>>>>
>>>>>>>> I have following test-cases:
>>>>>>>> int f1(int x, int y)
>>>>>>>> {
>>>>>>>>   int t1 = x + y;
>>>>>>>>   return t1 - y;
>>>>>>>> }
>>>>>>>> scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*=
>>>>>>>> x_\\d\+\\(D\\)"
>>>>>>>>
>>>>>>>> int f2(int x, int y)
>>>>>>>> {
>>>>>>>>   int t1 = x - y;
>>>>>>>>   return t1 + y;
>>>>>>>> }
>>>>>>>> scan-tree-dump "gimple_match_and_simplified to \[^\n\r\]*=
>>>>>>>> x_\\d\+\\(D\\)"
>>>>>>>>
>>>>>>>> both the test-cases have same regex.
>>>>>>>> Tested in isolation f1 passes (first pattern if fired) and f2
>fails
>>>>>>>> (second pattern doesn't fire, it does after
>>>>>>>> adding it's commutative variant, but that's irrelevant for this
>case).
>>>>>>>>
>>>>>>>> However when both test-cases are put in one file both the test
>cases
>>>>>>>> PASS.
>>>>>>>> I think that's because both of them have same regex:
>\[^\n\r\]*=
>>>>>>>> x_\\d\+\\(D\\)
>>>>>>>> so in f1 and f2's regex both match the dump for f1 function in
>>>>>>>> forwprop dump file:
>>>>>>>> "gimple_match_and_simplified to \[^\n\r\]*= x_\\d\+\\(D\\)
>>>>>>>>
>>>>>>>> As a quick hack i rewrote f1 and f2 as:
>>>>>>>> int f1(int x, int y)
>>>>>>>> {
>>>>>>>>   int t1 = x + y;
>>>>>>>>   int f1_val = t1 - y;
>>>>>>>>   return f1_val;
>>>>>>>> }
>>>>>>>> scan-tree-dump "gimple_match_and_simplified to f1_val_\\d\+ =
>>>>>>>> x_\\d\+\\(D\\)"
>>>>>>>>
>>>>>>>> int f2(int x, int y)
>>>>>>>> {
>>>>>>>>   int t1 = x - y;
>>>>>>>>   int f2_val = t1 + y;
>>>>>>>>   return f2_val;
>>>>>>>> }
>>>>>>>> scan-tree-dump "gimple_match_and_simplified to f2_val_\\d\+ =
>>>>>>>> x_\\d\+\\(D\\)"
>>>>>>>> so both f1 and f2's scan-tree-dump have different regexes.
>>>>>>>> and f2's regex does not match dump of f1's function.
>>>>>>>> This matches all patterns in match-decision-tree.c however this
>is not
>>>>>>>> ideal,
>>>>>>>> since it does not check for matching dump across newlines.
>>>>>>>> Could you suggest a better way ?
>>>>>>>
>>>>>>> There isn't a good better way (the others explicitely do _not_
>match
>>>>>>> against
>>>>>>> a newline - see the ^ in the \[\] group).  Well, apart from
>splitting
>>>>>>> the testcase
>>>>>>> into multiple files of course.
>>>>>>>
>>>>>>> Richard.
>>>>>>>
>>>>>>>> Thanks and Regards,
>>>>>>>> Prathamesh
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>> Richard.
>>>>>>>>>
>>>>>>>>>>> Thanks and Regards,
>>>>>>>>>>> Prathamesh
>>>>>>>>>>>>
>>>>>>>>>>>> Richard.
>>>>>>>>>>>>
>>>>>>>>>>>>> * Code generation.
>>>>>>>>>>>>> Code shall be generated by walking the decision tree.
>>>>>>>>>>>>> The way it's constructed, there's no difference between
>code
>>>>>>>>>>>>> generation
>>>>>>>>>>>>> for "matching" and code generation for "transform". For
>>>>>>>>>>>>> non-simplificaton
>>>>>>>>>>>>> operands, "matching" code is generated, and for
>"simplification"
>>>>>>>>>>>>> operands,
>>>>>>>>>>>>> "transform" code is generated. The tree shall be walked
>twice,
>>>>>>>>>>>>> once to generate GIMPLE code and second time for GENERIC.
>>>>>>>>>>>>> For simplicity, I currently return false whenever there's
>a fail
>>>>>>>>>>>>> in match,
>>>>>>>>>>>>> instead of trying to match the next pattern.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Code-gen for capture - same as capture::gen_gimple_match.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Code-gen for predicate -  I haven't added support for
>predicate
>>>>>>>>>>>>> in
>>>>>>>>>>>>> decision tree yet, but I guess that would be the same as
>>>>>>>>>>>>> predicate::gen_gimple_match
>>>>>>>>>>>>>
>>>>>>>>>>>>> Code-gen for expr.
>>>>>>>>>>>>> There are two types of code-gen for expr.
>>>>>>>>>>>>> The patch generates following code:
>>>>>>>>>>>>> Type 1 - expr is child of root node.
>>>>>>>>>>>>> the only code that gets generated is (in
>>>>>>>>>>>>> decision_tree::gen_gimple):
>>>>>>>>>>>>> if (code == <expr code>)
>>>>>>>>>>>>> {
>>>>>>>>>>>>> tree captures[4] = {}
>>>>>>>>>>>>> <generated code for children>
>>>>>>>>>>>>> }
>>>>>>>>>>>>> This is similar to generating matching code in
>>>>>>>>>>>>> write_nary_simplifiers.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Type 2 - expr_1 is a child of another expr_0 node.
>>>>>>>>>>>>> The code gets generated as follows (dt_expr::gen_gimple):
>>>>>>>>>>>>> {
>>>>>>>>>>>>> gimple def_stmt = SSA_NAME_DEF_STMT (op);
>>>>>>>>>>>>> if (is_gimple_assign (def_stmt)
>>>>>>>>>>>>>     && gimple_assign_rhs_code (def_stmt) == <expr_1-code>)
>>>>>>>>>>>>> {
>>>>>>>>>>>>> tree op = gimple_assign_rhs1 (def_stmt);
>>>>>>>>>>>>> if (valueize && TREE_CODE (op) == SSA_NAME)
>>>>>>>>>>>>> {
>>>>>>>>>>>>>   op = valueize (op);
>>>>>>>>>>>>>   if (!op) return false;
>>>>>>>>>>>>> }
>>>>>>>>>>>>> <code-gen for children of expr_1 node>
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> Example:
>>>>>>>>>>>>> (negate (negate @0))
>>>>>>>>>>>>> S1
>>>>>>>>>>>>>
>>>>>>>>>>>>> (negate (bit_not @0))
>>>>>>>>>>>>> S2
>>>>>>>>>>>>>
>>>>>>>>>>>>> decision tree:
>>>>>>>>>>>>>
>>>>>>>>>>>>>                 dummy/root
>>>>>>>>>>>>>                         |
>>>>>>>>>>>>>            NEGATE_EXPR
>>>>>>>>>>>>>              /                  \
>>>>>>>>>>>>>      BIT_NOT           NEGATE_EXPR
>>>>>>>>>>>>>            |                         |
>>>>>>>>>>>>>          @0                     @0
>>>>>>>>>>>>>            |                         |
>>>>>>>>>>>>>          S1                      S2
>>>>>>>>>>>>>
>>>>>>>>>>>>> // code-gen for NEGATE_EXPR (child of root):
>>>>>>>>>>>>> if (code == NEGATE_EXPR)
>>>>>>>>>>>>> {
>>>>>>>>>>>>> tree captures[4] = {};
>>>>>>>>>>>>> // code gen for BIT_NOT_EXPR
>>>>>>>>>>>>> {
>>>>>>>>>>>>> gimple def_stmt = SSA_NAME_DEF_STMT (op0);
>>>>>>>>>>>>> if (is_gimple_assign (def_stmt)
>>>>>>>>>>>>>     && gimple_assign_rhs_code (def_stmt) == BIT_NOT_EXPR)
>>>>>>>>>>>>> {
>>>>>>>>>>>>> tree op = gimple_assign_rhs1 (def_stmt);
>>>>>>>>>>>>> if (valueize && TREE_CODE (op) == SSA_NAME)
>>>>>>>>>>>>> {
>>>>>>>>>>>>>   op = valueize (op);
>>>>>>>>>>>>>   if (!op) return false;
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> // code-gen for @0, child of BIT_NOT_EXPR
>>>>>>>>>>>>> if (!captures[0])
>>>>>>>>>>>>>   captures[0] = op;
>>>>>>>>>>>>> else if (captures[0] != op)
>>>>>>>>>>>>>   return false;
>>>>>>>>>>>>>
>>>>>>>>>>>>> // code-gen for S1, child of @0
>>>>>>>>>>>>> < same as code generated by .gen_gimple_transform >
>>>>>>>>>>>>> return true;
>>>>>>>>>>>>> }
>>>>>>>>>>>>> // code gen for inner NEGATE_EXPR
>>>>>>>>>>>>> {
>>>>>>>>>>>>> gimple def_stmt = SSA_NAME_DEF_STMT (op0);
>>>>>>>>>>>>> if (is_gimple_assign (def_stmt)
>>>>>>>>>>>>>     && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR)
>>>>>>>>>>>>> <rest similar to the BIT_NOT case>
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> The following gets duplicated with the patch:
>>>>>>>>>>>>> {
>>>>>>>>>>>>> gimple_def_stmt = SSA_NAME_DEF_STMT (op0);
>>>>>>>>>>>>> if (TREE_CODE (op0) != SSA_NAME)
>>>>>>>>>>>>>   return false;
>>>>>>>>>>>>> if (is_gimple_assign (def_stmt)
>>>>>>>>>>>>>     && gimple_assign_rhs_code (def_stmt) == <expr-code>)
>>>>>>>>>>>>> ...
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> Improving code-gen for expr:
>>>>>>>>>>>>> "gimple def_stmt = ..." and "if (TREE_CODE (op0)" get
>duplicated,
>>>>>>>>>>>>> while they could be factored out, similar to this:
>>>>>>>>>>>>>
>>>>>>>>>>>>> {
>>>>>>>>>>>>> gimple def_stmt = SSA_NAME_DEF_STMT (op0);
>>>>>>>>>>>>> if (TREE_CODE (op0) != SSA_NAME)
>>>>>>>>>>>>>   return false;
>>>>>>>>>>>>> if (!is_gimple_assign (def_stmt))
>>>>>>>>>>>>>   return false;
>>>>>>>>>>>>> if (gimple_assign_rhs_code (def_stmt) == BIT_NOT_EXPR)
>>>>>>>>>>>>> {
>>>>>>>>>>>>>   // code-gen for BIT_NOT_EXPR subtree
>>>>>>>>>>>>> }
>>>>>>>>>>>>> else if (gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR)
>>>>>>>>>>>>> {
>>>>>>>>>>>>>   // code-gen for NEGATE_EXPR subtree
>>>>>>>>>>>>> }
>>>>>>>>>>>>>
>>>>>>>>>>>>> For factoring "gimple def_stmt ..." and "if (TREE_CODE
>(op0) !=
>>>>>>>>>>>>> SSA_NAME"
>>>>>>>>>>>>> we could have that generated at the parent of expr's node
>rather
>>>>>>>>>>>>> than
>>>>>>>>>>>>> at expr. However that would be incorrect for cases where
>not all
>>>>>>>>>>>>> children
>>>>>>>>>>>>> of a node are expressions:
>>>>>>>>>>>>>
>>>>>>>>>>>>> Example:
>>>>>>>>>>>>> // patterns only for illustration
>>>>>>>>>>>>> (negate (bit_not @0))
>>>>>>>>>>>>> (negate @0)
>>>>>>>>>>>>>
>>>>>>>>>>>>>                    root
>>>>>>>>>>>>>                      |
>>>>>>>>>>>>>                   negate
>>>>>>>>>>>>>                     /       \
>>>>>>>>>>>>>                 bit_not   @0
>>>>>>>>>>>>>                     |
>>>>>>>>>>>>>                   @0
>>>>>>>>>>>>>
>>>>>>>>>>>>> we cannot have the above code generated at negate,
>>>>>>>>>>>>> since it's not applicable negate's 2nd child (@0).
>>>>>>>>>>>>>
>>>>>>>>>>>>> This can be done by grouping together children that are
>>>>>>>>>>>>> expressions.
>>>>>>>>>>>>> However the patch does not do that.
>>>>>>>>>>>>>
>>>>>>>>>>>>> * Code-gen for simplification operand
>>>>>>>>>>>>> This involves code-gen for ifexpr and result of pattern.
>>>>>>>>>>>>> Calls gen_gimple_transform of ifexpr and result
>>>>>>>>>>>>> (dt_simplify::gen_gimple)
>>>>>>>>>>>>> So this is really code-gen off AST
>>>>>>>>>>>>
>>>>>>>>>>>> Right (modulo replacing captures with their replacements).
>>>>>>>>>>>>
>>>>>>>>>>>>> * Matching multiple patterns
>>>>>>>>>>>>> A pattern has following parts: match, ifexpr and result.
>>>>>>>>>>>>> If pattern fails in match operand, I guess we can safely
>return
>>>>>>>>>>>>> false ?
>>>>>>>>>>>>> We "club" together patterns that have same match operand,
>>>>>>>>>>>>> and use goto, if one of them fails in their
>(ifexpr/result) and
>>>>>>>>>>>>> then goto the
>>>>>>>>>>>>> (ifexpr/result) of the next operand.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Example:
>>>>>>>>>>>>> /* x & 0 -> 0 */
>>>>>>>>>>>>> (match_and_simplify
>>>>>>>>>>>>>   (bit_and @0 @1)
>>>>>>>>>>>>>   if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) && (@1 ==
>>>>>>>>>>>>> integer_zero_node))
>>>>>>>>>>>>>   { integer_zero_node; })
>>>>>>>>>>>>>
>>>>>>>>>>>>> /* x & -1 -> x */
>>>>>>>>>>>>> (match_and_simplify
>>>>>>>>>>>>>   (bit_and @0 @1)
>>>>>>>>>>>>>   if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
>>>>>>>>>>>>>      && (@1 == integer_minus_one_node)
>>>>>>>>>>>>>   @0)
>>>>>>>>>>>>>
>>>>>>>>>>>>> For both patterns match is same.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Decision Tree:
>>>>>>>>>>>>>                 bit_and
>>>>>>>>>>>>>                 /        \
>>>>>>>>>>>>>              @0      @1
>>>>>>>>>>>>>                            |
>>>>>>>>>>>>>                         S1,  S2
>>>>>>>>>>>>
>>>>>>>>>>>> I think it's worth adding a diagnostic to genmach whenever
>exactly
>>>>>>>>>>>> same matches appear.  But I'd say generally we'd support
>this
>>>>>>>>>>>> by testing the ifexpr of the next pattern.
>>>>>>>>>>>>
>>>>>>>>>>>>> S1 represents <ifexpr, result> of pattern-1, and S2
>represents
>>>>>>>>>>>>> <ifexpr, result>
>>>>>>>>>>>>> of pattern-2 respectively.
>>>>>>>>>>>>> S1, S2 would be stored as children of @1 (the last operand
>of
>>>>>>>>>>>>> n-ary operator),
>>>>>>>>>>>>> in dt_operand::kids vector.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The code would be generated as:
>>>>>>>>>>>>>
>>>>>>>>>>>>> matching code.
>>>>>>>>>>>>> if (! pattern-1 ifexpr condition)
>>>>>>>>>>>>>   goto simplify2;  // next pattern with the same "match"
>operand.
>>>>>>>>>>>>> transform code for pattern 1
>>>>>>>>>>>>>
>>>>>>>>>>>>> simplify2:
>>>>>>>>>>>>> if (! pattern-2 ifexpr condition)
>>>>>>>>>>>>>   return false;  // last pattern
>>>>>>>>>>>>> transform code for pattern 2.
>>>>>>>>>>>>>
>>>>>>>>>>>>> If matching itself fails, that is neither of the decisions
>get
>>>>>>>>>>>>> matched,
>>>>>>>>>>>>> I believe we can then return false as it cannot match any
>other
>>>>>>>>>>>>> pattern ?
>>>>>>>>>>>>>
>>>>>>>>>>>>> * patterns needing hacks like cond_expr or GENERIC support
>>>>>>>>>>>>> I haven't given thought to this yet. I suppose we can look
>to
>>>>>>>>>>>>> handle
>>>>>>>>>>>>> these after adding support for GENERIC. Instead of
>generating
>>>>>>>>>>>>> GENERIC
>>>>>>>>>>>>> matching in
>>>>>>>>>>>>> gimple_match_and_simplify, could we then call
>>>>>>>>>>>>> generic_match_and_simplify from
>>>>>>>>>>>>> within gimple_match_and_simplify ?
>>>>>>>>>>>>
>>>>>>>>>>>> Yes (that's what's currently done btw).
>>>>>>>>>>>>
>>>>>>>>>>>>> * Tests
>>>>>>>>>>>>> The patch transformed the following patterns:
>>>>>>>>>>>>>
>>>>>>>>>>>>> (match_and_simplify
>>>>>>>>>>>>>   (negate (bit_not @0))
>>>>>>>>>>>>>   if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
>>>>>>>>>>>>>   (plus @0 { build_int_cst (TREE_TYPE (@0)), 1); }))
>>>>>>>>>>>>>
>>>>>>>>>>>>> (match_and_simplify
>>>>>>>>>>>>>   (negate (negate @0))
>>>>>>>>>>>>>   @0)
>>>>>>>>>>>>>
>>>>>>>>>>>>> I have attached test-case I tried it with (negate.c)
>>>>>>>>>>>>>
>>>>>>>>>>>>> * Conclusion
>>>>>>>>>>>>> Does it sound reasonable ? I am going to be re-writing the
>>>>>>>>>>>>> decision tree from scratch, but is the basic idea fine ?
>Or should
>>>>>>>>>>>>> we
>>>>>>>>>>>>> take a different approach ?
>>>>>>>>>>>>>
>>>>>>>>>>>>> Thanks and Regards,
>>>>>>>>>>>>> Prathamesh
>>>>


Reply via email to