On Thu, Jun 12, 2014 at 4:26 PM, Richard Biener
<[email protected]> wrote:
> On Wed, Jun 11, 2014 at 4:09 PM, Prathamesh Kulkarni
> <[email protected]> wrote:
>> On 6/11/14, Richard Biener <[email protected]> wrote:
>>> On Wed, Jun 11, 2014 at 12:53 PM, Richard Biener
>>> <[email protected]> wrote:
>>>> On Wed, Jun 11, 2014 at 10:51 AM, Richard Biener
>>>> <[email protected]> wrote:
>>>>> On Tue, Jun 10, 2014 at 1:57 PM, Richard Biener
>>>>> <[email protected]> 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
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
>>>