On Tue, Jun 24, 2014 at 9:00 PM, Richard Biener <[email protected]> wrote:
>
> This massages things so GENERIC code-gen works (well, is emitted
> and compiles). The GENERIC interface matches that of
> fold_{unary,binary,ternary} with also supporting calls here.
> It's supposed to be called at the start of those functions
> (and if it returns NULL_TREE their remains is executed).
>
> At the moment it just creates dead code. I'll see if it works
> to wire it in tomorrow.
>
> Committed.
Small point: I renamed
dt_operand::gen_gimple_predicate/gen_gimple_match_op to
gen_predicate/gen_match_op.
* genmatch.c (dt_operand::gen_gimple_predicate): Rename to ...
(dt_operand::gen_predicate): ... this.
(dt_operand::gen_gimple_match_op): Rename to ...
(dt_operand::gen_match_op): ... this.
Thanks and Regards,
Prathamesh.
>
> Richard.
>
> 2014-06-24 Richard Biener <[email protected]>
>
> * genmatch.c (operand::gen_gimple_transform): Rename to...
> (operand::gen_transform): ... this and add a flag argument for
> the kind of IL to generate.
> (predicate::gen_gimple_transform): Likewise.
> (expr::gen_gimple_transform): Likewise.
> (c_expr::gen_gimple_transform): Likewise.
> (capture::gen_gimple_transform): Likewise.
> (dt_node::gen_generic): Add.
> (dt_operand::gen_generic_expr): Add flag whether to valueize.
> (dt_operand::gen_generic_expr_expr): Likewise.
> (dt_operand::gen_generic_expr_fn): Likewise.
> (dt_simplify::gen_genric): Add.
> (decision_tree::gen_generic): Likewise.
> (main): Uncomment generic codegen.
>
> Index: genmatch.c
> ===================================================================
> --- genmatch.c (revision 211941)
> +++ genmatch.c (working copy)
> @@ -206,14 +206,14 @@ struct operand {
> enum op_type { OP_PREDICATE, OP_EXPR, OP_CAPTURE, OP_C_EXPR };
> operand (enum op_type type_) : type (type_) {}
> enum op_type type;
> - virtual void gen_gimple_transform (FILE *f, const char *) = 0;
> + virtual void gen_transform (FILE *f, const char *, bool) = 0;
> };
>
> struct predicate : public operand
> {
> predicate (const char *ident_) : operand (OP_PREDICATE), ident (ident_) {}
> const char *ident;
> - virtual void gen_gimple_transform (FILE *, const char *) { gcc_unreachable
> (); }
> + virtual void gen_transform (FILE *, const char *, bool) { gcc_unreachable
> (); }
> };
>
> struct e_operation {
> @@ -230,7 +230,7 @@ struct expr : public operand
> void append_op (operand *op) { ops.safe_push (op); }
> e_operation *operation;
> vec<operand *> ops;
> - virtual void gen_gimple_transform (FILE *f, const char *);
> + virtual void gen_transform (FILE *f, const char *, bool);
> };
>
> struct c_expr : public operand
> @@ -242,7 +242,7 @@ struct c_expr : public operand
> vec<cpp_token> code;
> unsigned nr_stmts;
> char *fname;
> - virtual void gen_gimple_transform (FILE *f, const char *);
> + virtual void gen_transform (FILE *f, const char *, bool);
> };
>
> struct capture : public operand
> @@ -251,7 +251,7 @@ struct capture : public operand
> : operand (OP_CAPTURE), where (where_), what (what_) {}
> const char *where;
> operand *what;
> - virtual void gen_gimple_transform (FILE *f, const char *);
> + virtual void gen_transform (FILE *f, const char *, bool);
> };
>
>
> @@ -324,6 +324,7 @@ struct dt_node
> dt_node *append_simplify (simplify *, unsigned, dt_operand **);
>
> virtual void gen_gimple (FILE *) {}
> + virtual void gen_generic (FILE *) {}
> };
>
> struct dt_operand: public dt_node
> @@ -337,6 +338,7 @@ struct dt_operand: public dt_node
> : dt_node (type), op (op_), match_dop (match_dop_), parent (parent_),
> pos (pos_) {}
>
> virtual void gen_gimple (FILE *);
> + virtual void gen_generic (FILE *);
> unsigned gen_gimple_predicate (FILE *, const char *);
> unsigned gen_gimple_match_op (FILE *, const char *);
>
> @@ -344,9 +346,9 @@ struct dt_operand: public dt_node
> void gen_gimple_expr_expr (FILE *, expr *);
> void gen_gimple_expr_fn (FILE *, expr *);
>
> - unsigned gen_generic_expr (FILE *, const char *);
> - void gen_generic_expr_expr (FILE *, expr *, const char *);
> - void gen_generic_expr_fn (FILE *, expr *, const char *);
> + unsigned gen_generic_expr (FILE *, const char *, bool);
> + void gen_generic_expr_expr (FILE *, expr *, const char *, bool);
> + void gen_generic_expr_fn (FILE *, expr *, const char *, bool);
>
> char *get_name (char *);
> void gen_opname (char *, unsigned);
> @@ -369,6 +371,7 @@ struct dt_simplify: public dt_node
> }
>
> virtual void gen_gimple (FILE *f);
> + virtual void gen_generic (FILE *f);
> };
>
> struct decision_tree
> @@ -377,6 +380,7 @@ struct decision_tree
>
> void insert (struct simplify *, unsigned);
> void gen_gimple (FILE *f = stderr);
> + void gen_generic (FILE *f = stderr);
> void print (FILE *f = stderr);
>
> decision_tree () { root = new dt_node (dt_node::DT_NODE); }
> @@ -535,7 +539,7 @@ commutate (operand *op)
> /* Code gen off the AST. */
>
> void
> -expr::gen_gimple_transform (FILE *f, const char *dest)
> +expr::gen_transform (FILE *f, const char *dest, bool gimple)
> {
> fprintf (f, "{\n");
> fprintf (f, " tree ops[%u], res;\n", ops.length ());
> @@ -543,31 +547,46 @@ expr::gen_gimple_transform (FILE *f, con
> {
> char dest[32];
> snprintf (dest, 32, " ops[%u]", i);
> - ops[i]->gen_gimple_transform (f, dest);
> + ops[i]->gen_transform (f, dest, gimple);
> + }
> + if (gimple)
> + {
> + /* ??? Have another helper that is like gimple_build but may
> + fail if seq == NULL. */
> + fprintf (f, " if (!seq)\n"
> + " {\n"
> + " res = gimple_match_and_simplify (%s, TREE_TYPE
> (ops[0])",
> + operation->op->id);
> + for (unsigned i = 0; i < ops.length (); ++i)
> + fprintf (f, ", ops[%u]", i);
> + fprintf (f, ", seq, valueize);\n");
> + fprintf (f, " if (!res) return false;\n");
> + fprintf (f, " }\n");
> + fprintf (f, " else\n");
> + fprintf (f, " res = gimple_build (seq, UNKNOWN_LOCATION, %s, "
> + "TREE_TYPE (ops[0])", operation->op->id);
> + for (unsigned i = 0; i < ops.length (); ++i)
> + fprintf (f, ", ops[%u]", i);
> + fprintf (f, ", valueize);\n");
> + }
> + else
> + {
> + if (operation->op->kind == id_base::CODE)
> + fprintf (f, " res = fold_build%d (%s, TREE_TYPE (ops[0])",
> + ops.length(), operation->op->id);
> + else
> + fprintf (f, " res = build_call_expr (builtin_decl_implicit (%s), %d",
> + operation->op->id, ops.length());
> + for (unsigned i = 0; i < ops.length (); ++i)
> + fprintf (f, ", ops[%u]", i);
> + fprintf (f, ");\n");
> }
> - /* ??? Have another helper that is like gimple_build but may
> - fail if seq == NULL. */
> - fprintf (f, " if (!seq)\n"
> - " {\n"
> - " res = gimple_match_and_simplify (%s, TREE_TYPE (ops[0])",
> - operation->op->id);
> - for (unsigned i = 0; i < ops.length (); ++i)
> - fprintf (f, ", ops[%u]", i);
> - fprintf (f, ", seq, valueize);\n");
> - fprintf (f, " if (!res) return false;\n");
> - fprintf (f, " }\n");
> - fprintf (f, " else\n");
> - fprintf (f, " res = gimple_build (seq, UNKNOWN_LOCATION, %s, "
> - "TREE_TYPE (ops[0])", operation->op->id);
> - for (unsigned i = 0; i < ops.length (); ++i)
> - fprintf (f, ", ops[%u]", i);
> - fprintf (f, ", valueize);\n");
> fprintf (f, " %s = res;\n", dest);
> fprintf (f, "}");
> }
>
> void
> -c_expr::gen_gimple_transform (FILE *f, const char *dest)
> +c_expr::gen_transform (FILE *f, const char *dest, bool gimple)
> {
> /* If this expression has an outlined function variant, call it. */
> if (fname)
> @@ -614,7 +633,7 @@ c_expr::gen_gimple_transform (FILE *f, c
> }
>
> void
> -capture::gen_gimple_transform (FILE *f, const char *dest)
> +capture::gen_transform (FILE *f, const char *dest, bool)
> {
> fprintf (f, "%s = captures[%s];\n", dest, where);
> }
> @@ -949,7 +968,8 @@ dt_operand::gen_gimple_expr (FILE *f, co
>
>
> void
> -dt_operand::gen_generic_expr_expr (FILE *f, expr *e, const char *opname)
> +dt_operand::gen_generic_expr_expr (FILE *f, expr *e, const char *opname,
> + bool valueize)
> {
> unsigned n_ops = e->ops.length ();
>
> @@ -962,13 +982,16 @@ dt_operand::gen_generic_expr_expr (FILE
> gen_opname (child_opname, i);
>
> fprintf (f, "tree %s = TREE_OPERAND (%s, %u);\n", child_opname,
> opname, i);
> - fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n",
> child_opname, child_opname);
> - fprintf (f, "{\n");
> + if (valueize)
> + {
> + fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n",
> child_opname, child_opname);
> + fprintf (f, "{\n");
> + }
> }
> }
>
> void
> -dt_operand::gen_generic_expr_fn (FILE *f, expr *e, const char *opname)
> +dt_operand::gen_generic_expr_fn (FILE *f, expr *e, const char *opname, bool
> valueize)
> {
> unsigned n_ops = e->ops.length ();
> fn_id *op = static_cast <fn_id *> (e->operation->op);
> @@ -987,17 +1010,20 @@ dt_operand::gen_generic_expr_fn (FILE *f
> gen_opname (child_opname, i);
>
> fprintf (f, "tree %s = CALL_EXPR_ARG (%s, %u);\n", child_opname,
> opname, i);
> - fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n",
> child_opname, child_opname);
> - fprintf (f, "{\n");
> + if (valueize)
> + {
> + fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n",
> child_opname, child_opname);
> + fprintf (f, "{\n");
> + }
> }
> }
>
> unsigned
> -dt_operand::gen_generic_expr (FILE *f, const char *opname)
> +dt_operand::gen_generic_expr (FILE *f, const char *opname, bool valueize)
> {
> expr *e = static_cast<expr *> (op);
> - (e->operation->op->kind == id_base::CODE) ? gen_generic_expr_expr (f, e,
> opname) : gen_generic_expr_fn (f, e, opname);
> - return e->ops.length () + 1;
> + (e->operation->op->kind == id_base::CODE) ? gen_generic_expr_expr (f, e,
> opname, valueize) : gen_generic_expr_fn (f, e, opname, valueize);
> + return valueize ? e->ops.length () + 1 : 1;
> }
>
> void
> @@ -1024,14 +1050,14 @@ dt_operand::gen_gimple (FILE *f)
> enum tree_code code = op_id->code;
>
> if (code == REALPART_EXPR || code == IMAGPART_EXPR || code ==
> VIEW_CONVERT_EXPR || code == BIT_FIELD_REF)
> - n_braces = gen_generic_expr (f, opname);
> + n_braces = gen_generic_expr (f, opname, true);
>
> // check for cond_expr, 0th operand -> generic
> else if (parent->type == dt_node::DT_OPERAND && parent->op->type ==
> operand::OP_EXPR)
> {
> e = static_cast<expr *> (parent->op);
> op_id = static_cast <operator_id *> (e->operation->op);
> - n_braces = (op_id->code == COND_EXPR && pos == 0) ?
> gen_generic_expr (f, opname) : gen_gimple_expr (f, opname);
> + n_braces = (op_id->code == COND_EXPR && pos == 0) ?
> gen_generic_expr (f, opname, true) : gen_gimple_expr (f, opname);
> }
> else
> n_braces = gen_gimple_expr (f, opname);
> @@ -1060,6 +1086,48 @@ dt_operand::gen_gimple (FILE *f)
> }
>
> void
> +dt_operand::gen_generic (FILE *f)
> +{
> + char opname[20];
> + get_name (opname);
> +
> + fprintf (f, "{\n");
> +
> + unsigned n_braces = 0;
> +
> + if (type == DT_OPERAND)
> + switch (op->type)
> + {
> + case operand::OP_PREDICATE:
> + n_braces = gen_gimple_predicate (f, opname);
> + break;
> +
> + case operand::OP_EXPR:
> + n_braces = gen_generic_expr (f, opname, false);
> + break;
> +
> + default:
> + gcc_unreachable ();
> + }
> + else if (type == DT_TRUE)
> + ;
> + else if (type == DT_MATCH)
> + n_braces = gen_gimple_match_op (f, opname);
> + else
> + gcc_unreachable ();
> +
> + unsigned i;
> +
> + for (i = 0; i < kids.length (); ++i)
> + kids[i]->gen_generic (f);
> +
> + for (i = 0; i < n_braces; ++i)
> + fprintf (f, "}\n");
> +
> + fprintf (f, "}\n");
> +}
> +
> +void
> dt_simplify::gen_gimple (FILE *f)
> {
>
> @@ -1079,7 +1147,7 @@ dt_simplify::gen_gimple (FILE *f)
> {
> output_line_directive (f, s->ifexpr_location);
> fprintf (f, "if (");
> - s->ifexpr->gen_gimple_transform (f, NULL);
> + s->ifexpr->gen_transform (f, NULL, true);
> fprintf (f, ")\n");
> fprintf (f, "{\n");
> }
> @@ -1093,7 +1161,7 @@ dt_simplify::gen_gimple (FILE *f)
> {
> char dest[32];
> snprintf (dest, 32, " res_ops[%d]", j);
> - e->ops[j]->gen_gimple_transform (f, dest);
> + e->ops[j]->gen_transform (f, dest, true);
> }
> /* Re-fold the toplevel result. It's basically an embedded
> gimple_build w/o actually building the stmt. */
> @@ -1103,8 +1171,7 @@ dt_simplify::gen_gimple (FILE *f)
> else if (s->result->type == operand::OP_CAPTURE
> || s->result->type == operand::OP_C_EXPR)
> {
> - s->result->gen_gimple_transform (f,
> - "res_ops[0]");
> + s->result->gen_transform (f, "res_ops[0]", true);
> fprintf (f, "*res_code = TREE_CODE (res_ops[0]);\n");
> }
> else
> @@ -1118,6 +1185,70 @@ dt_simplify::gen_gimple (FILE *f)
> }
>
>
> +void
> +dt_simplify::gen_generic (FILE *f)
> +{
> +
> + fprintf (f, "/* simplify %u */\n", pattern_no);
> +
> + fprintf (f, "{\n");
> + fprintf (f, "tree captures[4] = {};\n");
> +
> + for (unsigned i = 0; i < dt_simplify::capture_max; ++i)
> + if (indexes[i])
> + {
> + char opname[20];
> + fprintf (f, "captures[%u] = %s;\n", i, indexes[i]->get_name (opname));
> + }
> +
> + if (s->ifexpr)
> + {
> + output_line_directive (f, s->ifexpr_location);
> + fprintf (f, "if (");
> + s->ifexpr->gen_transform (f, NULL, false);
> + fprintf (f, ")\n");
> + fprintf (f, "{\n");
> + }
> + output_line_directive (f, s->result_location);
> +
> + if (s->result->type == operand::OP_EXPR)
> + {
> + expr *e = static_cast <expr *> (s->result);
> + for (unsigned j = 0; j < e->ops.length (); ++j)
> + {
> + fprintf (f, " tree res_op%d;\n", j);
> + char dest[32];
> + snprintf (dest, 32, " res_op%d", j);
> + e->ops[j]->gen_transform (f, dest, false);
> + }
> + /* Re-fold the toplevel result. */
> + if (e->operation->op->kind == id_base::CODE)
> + fprintf (f, " return fold_build%d (%s, TREE_TYPE (res_op0)",
> + e->ops.length (), e->operation->op->id);
> + else
> + fprintf (f, " return build_call_expr (builtin_decl_implicit
> (%s), %d",
> + e->operation->op->id, e->ops.length());
> + for (unsigned j = 0; j < e->ops.length (); ++j)
> + fprintf (f, ", res_op%d", j);
> + fprintf (f, ");\n");
> + }
> + else if (s->result->type == operand::OP_CAPTURE
> + || s->result->type == operand::OP_C_EXPR)
> + {
> + fprintf (f, " tree res;\n");
> + s->result->gen_transform (f, " res", false);
> + fprintf (f, " return res;\n");
> + }
> + else
> + gcc_unreachable ();
> +
> + if (s->ifexpr)
> + fprintf (f, "}\n");
> +
> + fprintf (f, "}\n");
> +}
> +
> +
>
> void
> decision_tree::gen_gimple (FILE *f)
> @@ -1152,6 +1283,37 @@ decision_tree::gen_gimple (FILE *f)
> }
>
>
> +void
> +decision_tree::gen_generic (FILE *f)
> +{
> + fprintf (f, "tree\n"
> + "generic_match_and_simplify (code_helper code, tree type");
> + for (unsigned i = 0; i < 3; ++i)
> + fprintf (f, ", tree op%d", i);
> + fprintf (f, ")\n");
> + fprintf (f, "{\n");
> +
> + for (unsigned i = 0; i < root->kids.length (); i++)
> + {
> + dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
> + expr *e = static_cast<expr *>(dop->op);
> +
> + if (i)
> + fprintf (f, "else ");
> + fprintf (f, "if (code == %s)\n", e->operation->op->id);
> + fprintf (f, "{\n");
> +
> + for (unsigned j = 0; j < dop->kids.length (); ++j)
> + dop->kids[j]->gen_generic (f);
> +
> + fprintf (f, "}\n");
> + }
> +
> + fprintf (f, "return NULL_TREE;\n");
> + fprintf (f, "}\n");
> +}
> +
> +
> static void
> outline_c_exprs (FILE *f, struct operand *op)
> {
> @@ -1602,7 +1764,7 @@ main(int argc, char **argv)
> else if (strcmp (argv[1], "-generic") == 0)
> {
> write_header (stdout, simplifiers, "generic-match-head.c");
> - //dt.gen_generic (stdout);
> + dt.gen_generic (stdout);
> }
> else
> return 1;
Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c (revision 211950)
+++ gcc/genmatch.c (working copy)
@@ -339,8 +339,8 @@ struct dt_operand: public dt_node
virtual void gen_gimple (FILE *);
virtual void gen_generic (FILE *);
- unsigned gen_gimple_predicate (FILE *, const char *);
- unsigned gen_gimple_match_op (FILE *, const char *);
+ unsigned gen_predicate (FILE *, const char *);
+ unsigned gen_match_op (FILE *, const char *);
unsigned gen_gimple_expr (FILE *, const char *);
void gen_gimple_expr_expr (FILE *, expr *);
@@ -887,7 +887,7 @@ dt_operand::gen_opname (char *name, unsi
}
unsigned
-dt_operand::gen_gimple_predicate (FILE *f, const char *opname)
+dt_operand::gen_predicate (FILE *f, const char *opname)
{
predicate *p = static_cast<predicate *> (op);
@@ -897,7 +897,7 @@ dt_operand::gen_gimple_predicate (FILE *
}
unsigned
-dt_operand::gen_gimple_match_op (FILE *f, const char *opname)
+dt_operand::gen_match_op (FILE *f, const char *opname)
{
char match_opname[20];
match_dop->get_name (match_opname);
@@ -1040,7 +1040,7 @@ dt_operand::gen_gimple (FILE *f)
switch (op->type)
{
case operand::OP_PREDICATE:
- n_braces = gen_gimple_predicate (f, opname);
+ n_braces = gen_predicate (f, opname);
break;
case operand::OP_EXPR:
@@ -1070,7 +1070,7 @@ dt_operand::gen_gimple (FILE *f)
else if (type == DT_TRUE)
;
else if (type == DT_MATCH)
- n_braces = gen_gimple_match_op (f, opname);
+ n_braces = gen_match_op (f, opname);
else
gcc_unreachable ();
@@ -1099,7 +1099,7 @@ dt_operand::gen_generic (FILE *f)
switch (op->type)
{
case operand::OP_PREDICATE:
- n_braces = gen_gimple_predicate (f, opname);
+ n_braces = gen_predicate (f, opname);
break;
case operand::OP_EXPR:
@@ -1112,7 +1112,7 @@ dt_operand::gen_generic (FILE *f)
else if (type == DT_TRUE)
;
else if (type == DT_MATCH)
- n_braces = gen_gimple_match_op (f, opname);
+ n_braces = gen_match_op (f, opname);
else
gcc_unreachable ();