On Mon, Aug 11, 2014 at 2:53 AM, Prathamesh Kulkarni <bilbotheelffri...@gmail.com> wrote: > On Tue, Aug 5, 2014 at 3:15 PM, Richard Biener > <richard.guent...@gmail.com> wrote: >> On Mon, Aug 4, 2014 at 4:44 PM, Prathamesh Kulkarni >> <bilbotheelffri...@gmail.com> wrote: >>> On Mon, Aug 4, 2014 at 2:59 PM, Richard Biener >>> <richard.guent...@gmail.com> wrote: >>>> 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? >>> I am not sure if I understood this. >>> eg: (foo (convert?@0 @1)) where foo's any operator. >>> gets lowered to: >>> a) (foo (convert@0 @1)) >>> b) (foo @1) >> >> b) (foo @0@1) >> >> that is, both captures capture the same >> >>> in case a), @0 captures (convert @1). >>> in case b), when there's no convert, what should @0 capture ? >>> It cannot capture foo, (foo@0 @1) since foo's in outermost-expr, >>> so should @0 be same as @1 for this case ? >> >> Yes. >> >>>> >>>>> 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. >>> Thanks, I would do that. >>> I was wondering whether it would be okay to change tree.def for this >>> purpose though ? >>> since convert1, convert2 would be having no other use. >> >> No, not changing tree.def but its use as you did in your first proposed >> patch. > I have got it done except for capturing optional converts. > for instance (negate (convert1@0 @1)) does not work. > This is because of insertion in decision tree (insert::operand). > Since captures were always predicate or expressions, > ie, the corresponding dt-node->type was dt_node::DT_OPERAND, > i could hard-code for a search on dt_node::DT_OPERAND. > This changes when capture itself can be captured (dt_node::DT_TRUE/DT_MATCH), > and there's no easy way right now to obtain corresponding > dt-node from a given operand node. > > Should we keep a mapping (hash_map/std::map) from operand * to dt_node * ? > That will also get rid of dt_node::parent (but we need to then > introduce parent in AST). > > Other cases where convert1, convert2 are not captured work > fine. > (bit_not (convert1 @0) (convert2 @1)) > I have attached patch for reference (don't intend to get it committed). I have fixed it in a hackish way in the current patch, so capturing optional convert works.. Since we don't know type corresponding to capture in decision tree :DT_TRUE/DT_MATCH (unless we get hold of dt-node corresponding to the capture), I tried both the possibilities.
* genmatch.c (enum tree_code): Add new values CONVERT1, CONVERT2. (lower_opt_convert): New function. (lower_opt_convert): New function overloaded. (lower_opt_convert): Likewise. (lower_opt_convert): Likewise. (remove_opt_convert): New function. (has_opt_convert): Likewise. (decision_tree::insert_operand): Adjust for capturing a capture. (parse_for): Reject CONVERT1, CONVERT2. (main): call add_operator. call lower_opt_convert. Thanks, Prathamesh > > Thanks, > Prathamesh >> >> Richard. >> >>> Thanks, >>> Prathamesh >>>> >>>> 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
Index: genmatch.c =================================================================== --- genmatch.c (revision 213756) +++ genmatch.c (working copy) @@ -101,6 +101,8 @@ output_line_directive (FILE *f, source_l #define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM, enum tree_code { #include "tree.def" +CONVERT1, +CONVERT2, MAX_TREE_CODES }; #undef DEFTREECODE @@ -600,6 +602,134 @@ lower_commutative (simplify *s, vec<simp } } +operand * +lower_opt_convert (operand *o, const char *oper) +{ + if (capture *c = dyn_cast<capture *> (o)) + { + if (c->what) + return new capture (c->where, lower_opt_convert (c->what, oper)); + else + return c; + } + + if (!is_a<expr *> (o)) + return o; + + expr *e = as_a<expr *> (o); + if (strcmp (e->operation->op->id, oper) == 0) + { + expr *ne = new expr (new e_operation ("CONVERT_EXPR")); + ne->append_op (lower_opt_convert (e->ops[0], oper)); + return ne; + } + + expr *ne = new expr (e->operation); + for (unsigned i = 0; i < e->ops.length (); ++i) + ne->append_op (lower_opt_convert (e->ops[i], oper)); + + return ne; +} + +operand * +remove_opt_convert (operand *o, const char *oper) +{ + if (capture *c = dyn_cast<capture *> (o)) + { + if (c->what) + return new capture (c->where, remove_opt_convert (c->what, oper)); + else + return c; + } + + if (!is_a<expr *> (o)) + return o; + + expr *e = as_a<expr *> (o); + if (strcmp (e->operation->op->id, oper) == 0) + return remove_opt_convert (e->ops[0], oper); + + expr *ne = new expr (e->operation); + for (unsigned i = 0; i < e->ops.length (); ++i) + ne->append_op (remove_opt_convert (e->ops[i], oper)); + + return ne; +} + +bool +has_opt_convert (operand *o, const char *oper) +{ + if (capture *c = dyn_cast<capture *> (o)) + { + if (c->what) + return has_opt_convert (c->what, oper); + else + return false; + } + + if (!is_a<expr *> (o)) + return false; + + expr *e = as_a<expr *> (o); + + if (strcmp (e->operation->op->id, oper) == 0) + return true; + + for (unsigned i = 0; i < e->ops.length (); ++i) + if (has_opt_convert (e->ops[i], oper)) + return true; + + return false; +} + +void +lower_opt_convert (vec<operand *>& v, operand *o, const char *oper) +{ + if (has_opt_convert (o, oper)) + { + v.safe_push (lower_opt_convert (o, oper)); + v.safe_push (remove_opt_convert (o, oper)); + } +} + +vec<operand *> +lower_opt_convert (operand *o) +{ + vec<operand *> v1 = vNULL, v2; + + v1.safe_push (o); + + const char *opers[] = { "CONVERT1", "CONVERT2", 0 }; + + for (unsigned i = 0; opers[i]; ++i) + { + v2 = vNULL; + for (unsigned j = 0; j < v1.length (); ++j) + lower_opt_convert (v2, v1[j], opers[i]); + + if (v2 != vNULL) + { + v1 = vNULL; + for (unsigned j = 0; j < v2.length (); ++j) + v1.safe_push (v2[j]); + } + } + + return v1; +} + +void +lower_opt_convert (simplify *s, vec<simplify *>& simplifiers) +{ + vec<operand *> matchers = lower_opt_convert (s->match); + for (unsigned i = 0; i < matchers.length (); ++i) + { + simplify *ns = new simplify (s->name, matchers[i], s->match_location, + s->result, s->result_location, s->ifexpr_vec); + simplifiers.safe_push (ns); + } +} + void check_operator (id_base *op, unsigned n_ops, const cpp_token *token = 0) { @@ -816,6 +946,7 @@ decision_tree::cmp_node (dt_node *n1, dt if (!n1 || !n2 || n1->type != n2->type) return false; + if (n1 == n2 || n1->type == dt_node::DT_TRUE) return true; @@ -924,8 +1055,28 @@ decision_tree::insert_operand (dt_node * if (c->what) { q = insert_operand (p, c->what, indexes, pos, parent); - dt_operand temp (dt_node::DT_OPERAND, c->what, 0); - elm = decision_tree::find_node (p->kids, &temp); + + if (capture *cc = dyn_cast<capture *> (c->what)) + { + unsigned cc_index = atoi (cc->where); + dt_operand *match_op = indexes[cc_index]; + + dt_operand temp (dt_node::DT_TRUE, 0, 0); + elm = decision_tree::find_node (p->kids, &temp); + + if (elm == 0) + { + dt_operand temp (dt_node::DT_MATCH, 0, match_op); + elm = decision_tree::find_node (p->kids, &temp); + } + } + else + { + dt_operand temp (dt_node::DT_OPERAND, c->what, 0); + elm = decision_tree::find_node (p->kids, &temp); + } + + gcc_assert (elm); } else q = elm = p->append_true_op (parent, pos); @@ -2125,7 +2276,11 @@ parse_for (cpp_reader *r, source_locatio token = peek (r); if (token->type != CPP_NAME) break; - opers.safe_push (get_ident (r)); + const char *id = get_ident (r); + id_base *idb = get_operator (id); + if (strcmp (idb->id, "CONVERT1") == 0 || strcmp (idb->id, "CONVERT2") == 0) + fatal_at (token, "CONVERT1, CONVERT2 cannot be used inside for"); + opers.safe_push (id); } if (token->type == CPP_CLOSE_PAREN) @@ -2254,6 +2409,8 @@ main(int argc, char **argv) add_operator (SYM, # SYM, # TYPE, NARGS); #define END_OF_BASE_TREE_CODES #include "tree.def" +add_operator (CONVERT1, "CONVERT1", "tcc_unary", 1); +add_operator (CONVERT2, "CONVERT2", "tcc_unary", 1); #undef END_OF_BASE_TREE_CODES #undef DEFTREECODE @@ -2273,9 +2430,13 @@ main(int argc, char **argv) for (unsigned i = 0; i < simplifiers.length (); ++i) check_no_user_id (simplifiers[i]); - vec<simplify *> out_simplifiers = vNULL; + vec<simplify *> out_simplifiers0 = vNULL; for (unsigned i = 0; i < simplifiers.length (); ++i) - lower_commutative (simplifiers[i], out_simplifiers); + lower_opt_convert (simplifiers[i], out_simplifiers0); + + vec<simplify *> out_simplifiers = vNULL; + for (unsigned i = 0; i < out_simplifiers0.length (); ++i) + lower_commutative (out_simplifiers0[i], out_simplifiers); if (verbose) for (unsigned i = 0; i < out_simplifiers.length (); ++i)