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. Richard. 2014-06-24 Richard Biener <rguent...@suse.de> * 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;