On Tue, Jun 17, 2014 at 12:21 AM, Prathamesh Kulkarni
<bilbotheelffri...@gmail.com> wrote:
> On Mon, Jun 16, 2014 at 4:45 PM, Richard Biener
> <richard.guent...@gmail.com> wrote:
>>
>> > * Patterns requiring GENERIC support like cond_expr
>> > I am not sure about how to handle these patterns. I was thinking about
>> > handling them after we have
>> > GENERIC code generation in place.
>>
>> Yeah, though handling GENERIC for matching is as simple as
>> emitting the code check twice, the 2nd check off the an else
>> from the if (TREE_CODE (op) == SSA_NAME).  That is,
>> arrange for expr::gen_gimple_match_dt to emit
>>
>>    if (TREE_CODE (...) == SSA_NAME)
>>      {
>>         gimple def_stmt = SSA_NAME_DEF_STMT (...);
>>         if (is_gimple_assign (def_stmt) && gimple_assign_rhs_code
>> (def_stmt) == <code>)
>>           {
>>   ....
>>      }
>>    else (TREE_CODE (...) == <code>)
>>      {
>>   ....
>>      }
>>
>> which would require some refactoring in the generator.  As for refactoring
>> it I'd not hook the gen_gimple_match_dt off the AST operands but
>> inline it in the decision tree traversal routine - that also makes the
>> commoning above easier.
> Thanks, I shall get started on this.

Good.  You also miss the special-casing of REALPART_EXPR,
IMAGPART_EXPR, VIEW_CONVERT_EXPR and BIT_FIELD_REF
operand extraction as you say below.

>>
>> Btw, I checked what we generate for (bogus)
>>
>> (match_and_simplify
>>   (MINUS_EXPR (PLUS_EXPR@2 @0 @1) @2)
>>   @1)
>>
>> and the DT looks like
>>
>> root, 1
>> |--operand: MINUS_EXPR, 1
>> |----operand: true, 1
>> |------operand: PLUS_EXPR, 1
>> |--------operand: true, 1
>> |----------operand: true, 1
>> |------------operand: match(1), 1
>> |--------------simplify_0, 0
>>
>> though I expected
>>
>> root, 1
>> |--operand: MINUS_EXPR, 1
>> |----operand: PLUS_EXPR, 1
>> |------operand: true, 1
>> |--------operand: true, 1
>> |----------operand: match(1), 1
>> |------------simplify_0, 0
>>
>> that is, I wonder where the extra "true" comes from.
> Thanks, fixed it in the current patch.

Thanks.

>>
>>
>> For
>>
>> (match_and_simplify
>>   (MINUS_EXPR @2 (PLUS_EXPR@2 @0 @1))
>>   @1)
>>
>> I get
>>
>> root, 1
>> |--operand: MINUS_EXPR, 1
>> |----operand: true, 1
>> |------operand: match(1), 1
>> |--------operand: PLUS_EXPR, 1
>> |----------operand: true, 1
>> |------------operand: true, 1
>> |--------------simplify_0, 0
>>
>> which looks good to me.
>>
>> There is still a fallthru for all match failures but the DT should ensure
>> that once any of the checks is false we can terminate - that is,
>> we never have to backtrack.  Sth simple like
>>
>> --- genmatch.c.orig     2014-06-16 12:57:38.401890454 +0200
>> +++ genmatch.c  2014-06-16 12:58:03.451888730 +0200
>> @@ -816,6 +816,7 @@
>>    unsigned i;
>>    for (i = 0; i < kids.length (); ++i)
>>      kids[i]->gen_gimple (f);
>> +  fprintf (f, "return false;\n");
>>
>>
>>    for (i = 0; i < n_braces; ++i)
>>      fprintf (f, "}\n");
>>
>> So overall I think we are ok sofar and don't need major changes in
>> the algorithm.
>>
>> I'd say add the missing call support and we're good to go ripping out
>> the non-decision tree path.
>>
>> I'm happy to do some of the refactoring that I'd like to see myself
>> so you can concentrate on pattern implementing for phase 2.  But
>> feel free to do some of it yourself.
>>
>> > Small point: I was wondering if it's a good idea to slightly change
>> > the syntax of pattern to sth like:
>> > match-expression -> transform  ?
>> > eg:
>> > (minus (plus @0 @1) @1) -> @0
>> > Looks smaller -:)
>>
>> Well, I suppose we stay with what we have here.
> The attached patch, adds support for built-in functions, and fixes
> insertion bug in decision tree.
> The insertion in decision tree is carried out during preorder traversal
> of AST (insert_operand), so it avoids generating preorder traversal in
> vector (removed walk_operand_preorder and
> lower_capture). For now have put (parent, pos, preorder_level) in
> separate struct operand_info, and added instance
> of this struct to operand (struct operand_info opinfo). operand_info
> is computed during preorder traversal
> (insert_operand), so parsing routines are not concerned with it.
> Eventually we should probably move
> matching code on decision tree nodes. For convenience of tracking
> patterns, I have numbered them in match.pd.

Ok.

> * Testing
> Total patterns in match.pd - 58
> Total test cases: 4 (match-1.c), 32 (match-decision-tree.c), match-2.c
> is screwed.

How is it screwed?  I see it all pass ...

> Out of 22 remaining patterns:
> Not supported yet (require GENERIC support or special handling): 31
> (convert), 33, 34, 35 (realpart/imagpart), 37 (cond)
> Not able to write test-cases: 2, 16, 31, 38

Sth like

char *foo (char *p)
{
  int i = 0;
  return p + i;
}

for 2) and using -fdump-tree-ccp1-details and scanning the
ccp1 dump for "Match-and-simplified definition of _4 to p_3(D)"
(ok, that's a quite non-informative dump message and we should
improve it ... ok, changed now to "Match-and-simplified p_3(D) + _2 to p_3(D)")

16) is expected (it would be possible to write a testcase but I'm not sure
we want to retain that pattern).  31) has a testcases in gcc.dg/pr58742-[123].c
At some point (well, maybe now ...) we want to remove those patterns
we implemented in match.pd from the manual code in tree-ssa-forwprop.c
so we don't see "false" passing of testcases written for them.
For 38) I have no idea how to get a FMA_EXPR with integer types ... probably
the pattern (and the corresponding code in fold-const.c) is "dead".

Thanks,
Richard.

> I will add test-cases for remaining patterns shortly.
>
> Thanks and Regards,
> Prathamesh
>>
>> Thanks,
>> Richard.
>>
>> > Thanks and Regards
>> > Prathamesh
>> >>
>> >> 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