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: [GSoC] replacing op in c_expr


On Mon, Aug 11, 2014 at 4:58 PM, Richard Biener
<richard.guenther@gmail.com> wrote:
> On Sun, Aug 10, 2014 at 11:17 PM, Prathamesh Kulkarni
> <bilbotheelffriend@gmail.com> wrote:
>> On Mon, Aug 4, 2014 at 2:13 PM, Richard Biener
>> <richard.guenther@gmail.com> wrote:
>>> On Sun, Aug 3, 2014 at 6:58 PM, Prathamesh Kulkarni
>>> <bilbotheelffriend@gmail.com> wrote:
>>>> On Tue, Jul 29, 2014 at 4:29 PM, Richard Biener
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Mon, Jul 28, 2014 at 10:02 PM, Prathamesh Kulkarni
>>>>> <bilbotheelffriend@gmail.com> wrote:
>>>>>> I am having few issues replacing op in c_expr.
>>>>>> I thought of following possibilities:
>>>>>>
>>>>>> a) create a new vec<cpp_token> vector new_code.
>>>>>> for each token in code
>>>>>>   {
>>>>>>     if token.type is not CPP_NAME
>>>>>>       new_code.safe_push (token);
>>>>>>     else
>>>>>>      {
>>>>>>         cpp_token new_token =
>>>>>>             ??? create new token of type CPP_NAME
>>>>>>                   with contents as name of operator ???
>>>>>>      }
>>>>>>   }
>>>>>>
>>>>>> I tried to go this way, but am stuck with creating a new token type.
>>>>>> i started by:
>>>>>> cpp_token new_token = token;  // get same attrs as token.
>>>>>> CPP_HASHNODE (new_token.val.node.node)->ident.str = name of operator.
>>>>>> CPP_HASHNODE (new_token.val.node.node)->ident.len = len of operator name.
>>>>>> name of operator is obtained from opers[i] in parse_for.
>>>>>>
>>>>>> however this does not work because I guess
>>>>>>  new_token = token, shallow copies
>>>>>> the token (default assignment operator, i didn't find an overloaded version).
>>>>>>
>>>>>> b) create new struct c_expr_elem and use
>>>>>> vec<c_expr_elem> code, instead of vec<cpp_token> code;
>>>>>>
>>>>>> sth like:
>>>>>> struct c_expr_elem
>>>>>> {
>>>>>>    enum c_expr_elem_type { ID, TOKEN };
>>>>>>    enum c_expr_elem_type type;
>>>>>>
>>>>>>    union {
>>>>>>      cpp_token token;
>>>>>>      const char *id;
>>>>>>    };
>>>>>> };
>>>>>>
>>>>>> while replacing op, compare token with op, and if it matches,
>>>>>> create a new c_expr_elem with type = ID, and id = name of operator.
>>>>>> This shall probably work, but shall require many changes to other parts
>>>>>> since we change c_expr::code.
>>>>>>
>>>>>> I would like to hear any other suggestions.
>>>>>
>>>>> Together with the vector of tokens recorded at parse_c_expr time
>>>>> record a vector of token mappings (op -> plus, op2 -> ...) and do
>>>>> the replacement at code-generation time where we also special-case
>>>>> captures.
>>>>>
>>>>> Yeah, it's a but unfortunate that c_expr parsing is done the way it
>>>>> is done....
>>>> Thanks. I guess we would require a multi-map for this since there can
>>>> be many operators
>>>> (op -> [plus, minus], op2 -> [negate]) ?
>>>
>>> Well, it would be enough to attach the mapping to c_expr()s after the
>>> AST lowering when there is at most one?  Because obviously
>>> code-generation cannot know which to replace.
>>>
>>>> Unfortunately, I somehow seem to have missed your response and ended up with a
>>>> hackish way of doing it, although it works. I will soon change that to
>>>> use token mappings.
>>>>
>>>> I mostly followed b), except i made it sub-class of cpp_token, so the
>>>> other code using c_expr::code
>>>> (outline_c_expr, c_expr::gen_transform) did not require changes except
>>>> for special-casing op.
>>>
>>> Indeed not too ugly.  Still at the point where you replace in the for()
>>> processing
>>>
>>> -             operand *result_op = replace_id (s->result, user_id, opers[i]);
>>> +
>>> +             operand *result_op;
>>> +             if (is_a<c_expr *> (s->result))
>>> +               result_op = replace_op_in_c_expr (s->result, user_id, opers[i]);
>>> +             else
>>> +               result_op = replace_id (s->result, user_id, opers[i]);
>>> +
>>> +
>>>
>>> it should be "easy" to attach a replacemet vector/map to the c_expr
>>> and use that duing code-generation.
>>>
>>> Note that sub-expressions can also be c_exprs, thus
>>>
>>> (match-and-simplify
>>>    (....)
>>>    (plus { ... } @2))
>>>
>>> I don't think your patch covers that.  That is, you should add
>>> c_expr handing to replace_id instead.
>> Thanks, this patch covers that case.
>> For now, I have still kept the old way, since the change was one-liner.
>> I will change it after I am done with conditional convert
>
> I'll wait for that - the patch introduces extra warnings which will break
> bootstrap.
>
Hi,
    This patch replaces op in c_expr, by using vector in c_expr to record
<user_id, operator> mapping.
Sorry for late response.

I needed to clone c_expr, so added clone member function to operand hierarchy.
Ideally it should be a pure member function (= 0) in operand, however
for simplicity I have
put gcc_unreachable (), since I only want it used for c_expr (not
required so far for other classes).
Is that okay for now ? Eventually I will implement clone for other classes...

* genmatch.c (operand): New member function clone.
     (c_expr): Override clone.
     (c_expr): New struct id_tab.
     (c_expr): New member ids.
     (simplify::simplify): Adjust to clone c_expr.
     (replace_id): New default parameter replace_c_expr.
     (c_expr::gen_transform): Adjust to replace user-defined
identifier in c_expr.
     (outline_c_expr): Likewise.
     (parse_for): Likewise.

Thanks,
Prathamesh

> Thanks,
> Richard.
>
>> * genmatch.c (c_expr::elem): New struct.
>>      (c_expr::code): Change type to vec<c_expr::elem>.
>>      (replace_op_in_c_expr): New function.
>>      (replace_id): Call replace_op_in_c_expr.
>>      (c_expr::gen_transform): Adjust to changes in c_expr.
>>      (outline_c_expr): Likewise.
>>      (parse_c_expr): Likewise.
>>      (parse_for): Call replace_op_in_c_expr.
>> Thanks,
>> Prathamesh
>>>
>>> Richard.
>>>
>>>> * genmatch.c (c_expr::elem): New struct.
>>>>      (c_expr::code): Change type to vec<c_expr::elem>.
>>>>      (replace_op_in_c_expr): New function.
>>>>      (c_expr::gen_transform): Adjust to changes in c_expr.
>>>>      (outline_c_expr): Likewise.
>>>>      (parse_c_expr): Likewise.
>>>>      (parse_for): Call replace_op_in_c_expr.
>>>>
>>>> Thanks,
>>>> Prathamesh
>>>>
>>>>>
>>>>> Richard.
>>>>>
>>>>>> Thanks,
>>>>>> Prathamesh.
Index: genmatch.c
===================================================================
--- genmatch.c	(revision 214020)
+++ genmatch.c	(working copy)
@@ -222,6 +222,8 @@ struct operand {
   operand (enum op_type type_) : type (type_) {}
   enum op_type type;
   virtual void gen_transform (FILE *f, const char *, bool, int) = 0;
+
+  virtual operand *clone() { gcc_unreachable (); }
 };
 
 struct predicate : public operand
@@ -251,14 +253,36 @@ struct expr : public operand
 
 struct c_expr : public operand
 {
+  struct id_tab {
+    const char *id;
+    const char *oper;
+
+    id_tab (const char *id_, const char *oper_): id (id_), oper (oper_) {}
+  };
+
+
   c_expr (cpp_reader *r_, vec<cpp_token> code_, unsigned nr_stmts_)
     : operand (OP_C_EXPR), r (r_), code (code_),
-      nr_stmts (nr_stmts_), fname (NULL) {}
+      nr_stmts (nr_stmts_), fname (NULL), ids (vNULL) {}
   cpp_reader *r;
   vec<cpp_token> code;
   unsigned nr_stmts;
   char *fname;
+  vec<id_tab> ids;
+
   virtual void gen_transform (FILE *f, const char *, bool, int);
+
+  operand *clone()
+  {
+    // we only want to copy ids 
+    c_expr *ce = new c_expr (r, code, nr_stmts);
+    for (unsigned i = 0; i < ids.length (); ++i)
+      {
+ 	id_tab temp (ids[i].id, ids[i].oper);
+	ce->ids.safe_push (temp);
+      }
+    return ce;
+  } 
 };
 
 struct capture : public operand
@@ -356,8 +380,17 @@ struct simplify {
 	    operand *match_, source_location match_location_,
 	    struct operand *result_, source_location result_location_, vec<operand *> ifexpr_vec_ = vNULL)
       : name (name_), match (match_), match_location (match_location_),
-      result (result_), result_location (result_location_),
-      ifexpr_vec (ifexpr_vec_) {}
+      result_location (result_location_)
+        {
+	  ifexpr_vec = vNULL;
+	  for (unsigned i = 0; i < ifexpr_vec_.length (); ++i)
+	    ifexpr_vec.safe_push (ifexpr_vec_[i]->clone ());
+
+	  if (is_a<c_expr *> (result_))
+	    result = result_->clone ();
+	  else
+	    result = result_;
+	}
 
   const char *name;
   operand *match; 
@@ -760,7 +793,7 @@ check_operator (id_base *op, unsigned n_
 }
         
 operand *
-replace_id (operand *o, const char *user_id, const char *oper)
+replace_id (operand *o, const char *user_id, const char *oper, bool replace_c_expr = false)
 {
   if (o->type == operand::OP_CAPTURE)
     {
@@ -771,6 +804,15 @@ replace_id (operand *o, const char *user
       return nc;
     }
 
+  c_expr *ce;
+  if ((ce = dyn_cast<c_expr *> (o)) != 0 && replace_c_expr == true)
+    {
+      id_base *idb = get_operator (oper);
+      c_expr::id_tab temp (user_id, idb->id);
+      ce->ids.safe_push (temp);
+      return ce;
+    }
+
   if (o->type != operand::OP_EXPR)
     return o;
 
@@ -909,6 +951,23 @@ c_expr::gen_transform (FILE *f, const ch
 	    }
 	}
 
+      if (token->type == CPP_NAME)
+	{
+	  const char *id = (const char *) NODE_NAME (token->val.node.node);
+	  unsigned j;
+	  for (j = 0; j < ids.length (); ++j)
+	    {
+	    if (strcmp (id, ids[j].id) == 0)
+	      {
+		fprintf (f, "%s", ids[j].oper);
+		break;
+	      }
+	    }
+	  if (j < ids.length ())
+	    continue;
+	}
+	  
+
       if (token->flags & PREV_WHITE)
 	fputc (' ', f);
 
@@ -1912,6 +1971,25 @@ outline_c_exprs (FILE *f, struct operand
 	      if (token->flags & PREV_WHITE)
 		fputc (' ', f);
 
+	      if (token->type == CPP_NAME)
+		{
+		  const char *id = (const char *) NODE_NAME (token->val.node.node);
+		  unsigned j;
+
+		  for (j = 0; j < e->ids.length (); ++j)
+		    {
+		      if (strcmp (id, e->ids[j].id) == 0)
+			{
+			  fprintf (f, "%s", e->ids[j].oper);
+			  break;
+			}
+		    }
+
+		  if (j < e->ids.length ())
+		    continue;
+		}
+
+
 	      /* Output the token as string.  */
 	      char *tk = (char *)cpp_token_as_text (e->r, token);
 	      fputs (tk, f);
@@ -2292,10 +2370,11 @@ parse_simplify (cpp_reader *r, source_lo
 void parse_pattern (cpp_reader *, vec<simplify *>&);
 
 void
-parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers) 
+parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers_out) 
 {
   const char *user_id = get_ident (r);
   eat_ident (r, "in");
+  vec<const char *> replace_opers = vNULL;
 
   if (get_operator (user_id) != 0)
     fatal_at (peek (r), "%s is an operator, cannot be used as variable in for", user_id);
@@ -2319,30 +2398,49 @@ parse_for (cpp_reader *r, source_locatio
     fatal_at (token, "no pattern defined in for");
 
 
+  vec<simplify *> for_simplifiers = vNULL;
+  vec<simplify *> simplifiers = vNULL;
+
   while (1)
     {
       const cpp_token *token = peek (r);
       if (token->type == CPP_CLOSE_PAREN)
 	break;
       
-      vec<simplify *> for_simplifiers = vNULL;
       parse_pattern (r, for_simplifiers);
-      
+    }  
+    
       for (unsigned i = 0; i < opers.length (); ++i)
 	{
+	  id_base *idb = get_operator (opers[i]);	      
+	  gcc_assert (idb);
+
 	  for (unsigned j = 0; j < for_simplifiers.length (); ++j)
 	    {
 	      simplify *s = for_simplifiers[j];
 	      operand *match_op = replace_id (s->match, user_id, opers[i]);
 	      operand *result_op = replace_id (s->result, user_id, opers[i]);
 
+	      replace_opers.safe_push (idb->id);	      
 	      simplify *ns = new simplify (s->name, match_op, s->match_location,
 					   result_op, s->result_location, s->ifexpr_vec);
 
 	      simplifiers.safe_push (ns);
 	    }
 	}
-    }
+
+    gcc_assert (replace_opers.length () == simplifiers.length ()); 
+
+    for (unsigned i = 0; i < simplifiers.length (); ++i)
+      {
+	simplify *s = simplifiers[i];
+	for (unsigned j = 0; j < s->ifexpr_vec.length (); ++j)
+	  s->ifexpr_vec[j] = replace_id (s->ifexpr_vec[j], user_id, replace_opers[i], true);
+	s->result = replace_id (s->result, user_id, replace_opers[i], true);
+      }
+
+  for (unsigned i = 0; i < simplifiers.length (); ++i)
+    simplifiers_out.safe_push (simplifiers[i]);
 }
 
 void

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