On Mon, Aug 11, 2014 at 4:58 PM, Richard Biener
<[email protected]> wrote:
> On Sun, Aug 10, 2014 at 11:17 PM, Prathamesh Kulkarni
> <[email protected]> wrote:
>> On Mon, Aug 4, 2014 at 2:13 PM, Richard Biener
>> <[email protected]> wrote:
>>> On Sun, Aug 3, 2014 at 6:58 PM, Prathamesh Kulkarni
>>> <[email protected]> wrote:
>>>> On Tue, Jul 29, 2014 at 4:29 PM, Richard Biener
>>>> <[email protected]> wrote:
>>>>> On Mon, Jul 28, 2014 at 10:02 PM, Prathamesh Kulkarni
>>>>> <[email protected]> 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