This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: writing patterns


On Mon, Aug 11, 2014 at 2:53 AM, Prathamesh Kulkarni
<bilbotheelffriend@gmail.com> wrote:
> On Tue, Aug 5, 2014 at 3:15 PM, Richard Biener
> <richard.guenther@gmail.com> wrote:
>> On Mon, Aug 4, 2014 at 4:44 PM, Prathamesh Kulkarni
>> <bilbotheelffriend@gmail.com> wrote:
>>> On Mon, Aug 4, 2014 at 2:59 PM, Richard Biener
>>> <richard.guenther@gmail.com> wrote:
>>>> On Mon, Aug 4, 2014 at 12:16 AM, Prathamesh Kulkarni
>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>> On Thu, Jul 31, 2014 at 2:49 PM, Prathamesh Kulkarni
>>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>>> On Thu, Jul 31, 2014 at 2:44 PM, Richard Biener
>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>> On Thu, Jul 31, 2014 at 11:09 AM, Prathamesh Kulkarni
>>>>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>>>>> On Thu, Jul 31, 2014 at 2:15 PM, Richard Biener
>>>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>>>> On Thu, Jul 31, 2014 at 7:41 AM, Prathamesh Kulkarni
>>>>>>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>>>>>>> On Wed, Jul 30, 2014 at 11:49 PM, Prathamesh Kulkarni
>>>>>>>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>>>>>>>> On Wed, Jul 30, 2014 at 4:49 PM, Richard Biener
>>>>>>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>>>>>>> On Wed, Jul 30, 2014 at 1:11 PM, Richard Biener
>>>>>>>>>>>> <richard.guenther@gmail.com> wrote:
>>>>>>>>>>>>> On Wed, Jul 30, 2014 at 12:49 PM, Prathamesh Kulkarni
>>>>>>>>>>>>> <bilbotheelffriend@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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]