This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][match-and-simplify] Apply TLC
- From: Richard Biener <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 25 Sep 2014 10:50:43 +0200 (CEST)
- Subject: [PATCH][match-and-simplify] Apply TLC
- Authentication-results: sourceware.org; auth=none
This shuffles routines around, grouping them properly and adding
function comments. Applies minor code TLC.
Applied.
Richard.
2014-09-25 Richard Biener <rguenther@suse.de>
* genmatch.c: TLC.
Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c (revision 215554)
+++ gcc/genmatch.c (working copy)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
#include "vec.h"
#include "is-a.h"
+
/* libccp helpers. */
static struct line_maps *line_table;
@@ -112,26 +113,8 @@ output_line_directive (FILE *f, source_l
}
-/* Grammar
-
- capture = '@' number
- op = predicate | expr [capture]
- c_expr = '{' ... '}'
- genexpr = '(' code genop... ')'
- genop = capture | genexpr | c_expr
- transform = 'match_and_transform' name expr genop
-
- Match and simplify (A + B) - B -> A
- (simplify foo
- (PLUS_EXPR (MINUS_EXPR integral_op_p@0 @1) @1)
- @0)
-
- Match and simplify (CST + A) + CST to CST' + A
- (simplify bar
- (PLUS_EXPR INTEGER_CST_P@0 (PLUS_EXPR @1 INTEGER_CST_P@2))
- (PLUS_EXPR { int_const_binop (PLUS_EXPR, captures[0], captures[2]); } @1))
-*/
-
+/* Pull in tree codes and builtin function codes from their
+ definition files. */
#define DEFTREECODE(SYM, STRING, TYPE, NARGS) SYM,
enum tree_code {
@@ -150,12 +133,12 @@ END_BUILTINS
};
#undef DEF_BUILTIN
-/* Hashtable of known pattern operators. This is pre-seeded from
- all known tree codes and all known builtin function ids. */
+
+/* Base class for all identifiers the parser knows. */
struct id_base : typed_noop_remove<id_base>
{
- enum id_kind { CODE, FN, PREDICATE, USER_DEFINED } kind;
+ enum id_kind { CODE, FN, PREDICATE, USER } kind;
id_base (id_kind, const char *, int = -1);
@@ -184,6 +167,8 @@ id_base::equal (const value_type *op1,
&& strcmp (op1->id, op2->id) == 0);
}
+/* Hashtable of known pattern operators. This is pre-seeded from
+ all known tree codes and all known builtin function ids. */
static hash_table<id_base> *operators;
id_base::id_base (id_kind kind_, const char *id_, int nargs_)
@@ -194,6 +179,8 @@ id_base::id_base (id_kind kind_, const c
hashval = htab_hash_string (id);
}
+/* Identifier that maps to a tree code. */
+
struct operator_id : public id_base
{
operator_id (enum tree_code code_, const char *id_, unsigned nargs_,
@@ -203,6 +190,8 @@ struct operator_id : public id_base
const char *tcc;
};
+/* Identifier that maps to a builtin function code. */
+
struct fn_id : public id_base
{
fn_id (enum built_in_function fn_, const char *id_)
@@ -212,6 +201,8 @@ struct fn_id : public id_base
struct simplify;
+/* Identifier that maps to a user-defined predicate. */
+
struct predicate_id : public id_base
{
predicate_id (const char *id_)
@@ -219,10 +210,12 @@ struct predicate_id : public id_base
vec<simplify *> matchers;
};
+/* Identifier that maps to a operator defined by a 'for' directive. */
+
struct user_id : public id_base
{
user_id (const char *id_)
- : id_base (id_base::USER_DEFINED, id_), substitutes (vNULL) {}
+ : id_base (id_base::USER, id_), substitutes (vNULL) {}
vec<id_base *> substitutes;
};
@@ -250,6 +243,16 @@ is_a_helper <predicate_id *>::test (id_b
return id->kind == id_base::PREDICATE;
}
+template<>
+template<>
+inline bool
+is_a_helper <user_id *>::test (id_base *id)
+{
+ return id->kind == id_base::USER;
+}
+
+/* Add a predicate identifier to the hash. */
+
static predicate_id *
add_predicate (const char *id)
{
@@ -261,6 +264,8 @@ add_predicate (const char *id)
return p;
}
+/* Add a tree code identifier to the hash. */
+
static void
add_operator (enum tree_code code, const char *id,
const char *tcc, unsigned nargs)
@@ -281,6 +286,8 @@ add_operator (enum tree_code code, const
*slot = op;
}
+/* Add a builtin identifier to the hash. */
+
static void
add_builtin (enum built_in_function code, const char *id)
{
@@ -291,35 +298,80 @@ add_builtin (enum built_in_function code
*slot = fn;
}
+/* Helper for easy comparing ID with tree code CODE. */
+
static bool
operator==(id_base &id, enum tree_code code)
{
- if (id.kind != id_base::CODE)
- return false;
- return static_cast <operator_id&>(id).code == code;
+ if (operator_id *oid = dyn_cast <operator_id *> (&id))
+ return oid->code == code;
+ return false;
+}
+
+/* Lookup the identifier ID. */
+
+id_base *
+get_operator (const char *id)
+{
+ id_base tem (id_base::CODE, id);
+
+ id_base *op = operators->find_with_hash (&tem, tem.hashval);
+ if (op)
+ return op;
+
+ /* Try all-uppercase. */
+ char *id2 = xstrdup (id);
+ for (unsigned i = 0; i < strlen (id2); ++i)
+ id2[i] = TOUPPER (id2[i]);
+ new (&tem) id_base (id_base::CODE, id2);
+ op = operators->find_with_hash (&tem, tem.hashval);
+ if (op)
+ {
+ free (id2);
+ return op;
+ }
+
+ /* Try _EXPR appended. */
+ id2 = (char *)xrealloc (id2, strlen (id2) + sizeof ("_EXPR") + 1);
+ strcat (id2, "_EXPR");
+ new (&tem) id_base (id_base::CODE, id2);
+ op = operators->find_with_hash (&tem, tem.hashval);
+ if (op)
+ {
+ free (id2);
+ return op;
+ }
+
+ return 0;
}
-/* The predicate expression tree structure. */
+/* The AST produced by parsing of the pattern definitions. */
struct dt_operand;
+/* The base class for operands. */
+
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_transform (FILE *f, const char *, bool, int, const char *, dt_operand ** = 0) = 0;
+ virtual void gen_transform (FILE *, const char *, bool, int,
+ const char *, dt_operand ** = 0)
+ { gcc_unreachable (); }
};
+/* A predicate operand. Predicates are leafs in the AST. */
+
struct predicate : public operand
{
predicate (predicate_id *p_) : operand (OP_PREDICATE), p (p_) {}
predicate_id *p;
- virtual void gen_transform (FILE *, const char *, bool, int, const char *, dt_operand ** = 0)
- { gcc_unreachable (); }
};
+/* An operand that constitutes an expression. Expressions include
+ function calls and user-defined predicate invocations. */
struct expr : public operand
{
@@ -327,41 +379,54 @@ struct expr : public operand
: operand (OP_EXPR), operation (operation_),
ops (vNULL), expr_type (NULL), is_commutative (is_commutative_) {}
void append_op (operand *op) { ops.safe_push (op); }
+ /* The operator and its operands. */
id_base *operation;
vec<operand *> ops;
+ /* An explicitely specified type - used exclusively for conversions. */
const char *expr_type;
+ /* Whether the operation is to be applied commutatively. This is
+ later lowered to two separate patterns. */
bool is_commutative;
virtual void gen_transform (FILE *f, const char *, bool, int, const char *, dt_operand ** = 0);
};
+/* An operator that is represented by native C code. This is always
+ a leaf operand in the AST. This class is also used to represent
+ the code to be generated for 'if' and 'with' expressions. */
+
struct c_expr : public operand
{
+ /* A mapping of an identifier and its replacement. Used to apply
+ 'for' lowering. */
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_,
vec<id_tab> ids_ = vNULL)
: operand (OP_C_EXPR), r (r_), code (code_),
- nr_stmts (nr_stmts_), fname (NULL), ids (ids_) {}
+ nr_stmts (nr_stmts_), ids (ids_) {}
+ /* cpplib tokens and state to transform this back to source. */
cpp_reader *r;
vec<cpp_token> code;
+ /* The number of statements parsed (well, the number of ';'s). */
unsigned nr_stmts;
- char *fname;
+ /* The identifier replacement vector. */
vec<id_tab> ids;
-
virtual void gen_transform (FILE *f, const char *, bool, int, const char *, dt_operand **);
};
+/* A wrapper around another operand that captures its value. */
+
struct capture : public operand
{
capture (const char *where_, operand *what_)
: operand (OP_CAPTURE), where (where_), what (what_) {}
+ /* Identifier for the value. */
const char *where;
+ /* The captured value. */
operand *what;
virtual void gen_transform (FILE *f, const char *, bool, int, const char *, dt_operand ** = 0);
};
@@ -398,153 +463,48 @@ is_a_helper <expr *>::test (operand *op)
return op->type == operand::OP_EXPR;
}
-id_base *
-get_operator (const char *id)
-{
- id_base tem (id_base::CODE, id);
-
- id_base *op = operators->find_with_hash (&tem, tem.hashval);
- if (op)
- return op;
+/* Helper to distinguish 'if' from 'with' expressions. */
- /* Try all-uppercase. */
- char *id2 = xstrdup (id);
- for (unsigned i = 0; i < strlen (id2); ++i)
- id2[i] = TOUPPER (id2[i]);
- new (&tem) id_base (id_base::CODE, id2);
- op = operators->find_with_hash (&tem, tem.hashval);
- if (op)
- {
- free (id2);
- return op;
- }
-
- /* Try _EXPR appended. */
- id2 = (char *)xrealloc (id2, strlen (id2) + sizeof ("_EXPR") + 1);
- strcat (id2, "_EXPR");
- new (&tem) id_base (id_base::CODE, id2);
- op = operators->find_with_hash (&tem, tem.hashval);
- if (op)
- {
- free (id2);
- return op;
- }
-
- return 0;
-}
-
-struct if_or_with {
- if_or_with (operand *cexpr_, source_location location_, bool is_with_)
- : location (location_), cexpr (cexpr_), is_with (is_with_) {}
- source_location location;
- operand *cexpr;
- bool is_with;
+struct if_or_with
+{
+ if_or_with (operand *cexpr_, source_location location_, bool is_with_)
+ : location (location_), cexpr (cexpr_), is_with (is_with_) {}
+ source_location location;
+ operand *cexpr;
+ bool is_with;
};
-struct simplify {
+/* The main class of a pattern and its transform. This is used to
+ represent both (simplify ...) and (match ...) kinds. The AST
+ duplicates all outer 'if' and 'for' expressions here so each
+ simplify can exist in isolation. */
+
+struct simplify
+{
simplify (operand *match_, source_location match_location_,
- struct operand *result_, source_location result_location_, vec<if_or_with> ifexpr_vec_, vec<vec<user_id *> > for_vec_)
+ struct operand *result_, source_location result_location_,
+ vec<if_or_with> ifexpr_vec_, vec<vec<user_id *> > for_vec_)
: match (match_), match_location (match_location_),
result (result_), result_location (result_location_),
ifexpr_vec (ifexpr_vec_), for_vec (for_vec_) {}
+ /* The expression that is matched against the GENERIC or GIMPLE IL. */
operand *match;
source_location match_location;
+ /* For a (simplify ...) the expression produced when the pattern applies.
+ For a (match ...) either NULL if it is a simple predicate or the
+ single expression specifying the matched operands. */
struct operand *result;
source_location result_location;
+ /* Collected 'if' expressions that need to evaluate to true to make
+ the pattern apply. */
vec<if_or_with> ifexpr_vec;
+ /* Collected 'for' expression operators that have to be replaced
+ in the lowering phase. */
vec<vec<user_id *> > for_vec;
};
-struct dt_node
-{
- enum dt_type { DT_NODE, DT_OPERAND, DT_TRUE, DT_MATCH, DT_SIMPLIFY };
-
- enum dt_type type;
- unsigned level;
- vec<dt_node *> kids;
-
- dt_node (enum dt_type type_): type (type_), level (0), kids (vNULL) {}
-
- dt_node *append_node (dt_node *);
- dt_node *append_op (operand *, dt_node *parent = 0, unsigned pos = 0);
- dt_node *append_true_op (dt_node *parent = 0, unsigned pos = 0);
- dt_node *append_match_op (dt_operand *, dt_node *parent = 0, unsigned pos = 0);
- dt_node *append_simplify (simplify *, unsigned, dt_operand **);
-
- virtual void gen_gimple (FILE *) {}
- virtual void gen_generic (FILE *) {}
-
- void gen_gimple_kids (FILE *);
- void gen_generic_kids (FILE *);
-};
-
-struct dt_operand: public dt_node
-{
- operand *op;
- dt_operand *match_dop;
- dt_operand *parent;
- unsigned pos;
-
- dt_operand (enum dt_type type, operand *op_, dt_operand *match_dop_, dt_operand *parent_ = 0, unsigned pos_ = 0)
- : 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_predicate (FILE *, const char *, bool);
- unsigned gen_match_op (FILE *, const char *);
-
- unsigned gen_gimple_expr (FILE *);
- unsigned gen_generic_expr (FILE *, const char *);
-
- char *get_name (char *);
- void gen_opname (char *, unsigned);
-};
-
-
-struct dt_simplify: public dt_node
-{
- static const unsigned capture_max = 6;
- simplify *s;
- unsigned pattern_no;
- dt_operand *indexes[capture_max];
-
- dt_simplify (simplify *s_, unsigned pattern_no_, dt_operand **indexes_)
- : dt_node (DT_SIMPLIFY), s (s_), pattern_no (pattern_no_)
- {
- for (unsigned i = 0; i < capture_max; ++i)
- indexes[i] = indexes_[i];
- }
-
- void gen (FILE *f, bool);
- virtual void gen_gimple (FILE *f) { gen (f, true); }
- virtual void gen_generic (FILE *f) { gen (f, false); }
-};
-
-template<>
-template<>
-inline bool
-is_a_helper <dt_operand *>::test (dt_node *n)
-{
- return n->type == dt_node::DT_OPERAND;
-}
-
-struct decision_tree
-{
- dt_node *root;
-
- 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); }
-
- static dt_node *insert_operand (dt_node *, operand *, dt_operand **indexes, unsigned pos = 0, dt_node *parent = 0);
- static dt_node *find_node (vec<dt_node *>&, dt_node *);
- static bool cmp_node (dt_node *, dt_node *);
- static void print_node (dt_node *, FILE *f = stderr, unsigned = 0);
-};
+/* Debugging routines for dumping the AST. */
DEBUG_FUNCTION void
print_operand (operand *o, FILE *f = stderr, bool flattened = false)
@@ -594,7 +554,12 @@ print_matches (struct simplify *s, FILE
putc ('\n', f);
}
-void
+
+/* AST lowering. */
+
+/* Lowering of commutative operators. */
+
+static void
cartesian_product (const vec< vec<operand *> >& ops_vector, vec< vec<operand *> >& result, vec<operand *>& v, unsigned n)
{
if (n == ops_vector.length ())
@@ -611,7 +576,7 @@ cartesian_product (const vec< vec<operan
}
}
-void
+static void
cartesian_product (const vec< vec<operand *> >& ops_vector, vec< vec<operand *> >& result, unsigned n_ops)
{
vec<operand *> v = vNULL;
@@ -619,14 +584,13 @@ cartesian_product (const vec< vec<operan
cartesian_product (ops_vector, result, v, 0);
}
-vec<operand *>
+static vec<operand *>
commutate (operand *op)
{
vec<operand *> ret = vNULL;
- if (op->type == operand::OP_CAPTURE)
+ if (capture *c = dyn_cast <capture *> (op))
{
- capture *c = static_cast<capture *> (op);
if (!c->what)
{
ret.safe_push (op);
@@ -641,19 +605,13 @@ commutate (operand *op)
return ret;
}
- if (op->type != operand::OP_EXPR)
+ expr *e = dyn_cast <expr *> (op);
+ if (!e || e->ops.length () == 0)
{
ret.safe_push (op);
return ret;
}
- expr *e = static_cast<expr *> (op);
- if (e->ops.length () == 0)
- {
- ret.safe_push (e);
- return ret;
- }
-
vec< vec<operand *> > ops_vector = vNULL;
for (unsigned i = 0; i < e->ops.length (); ++i)
ops_vector.safe_push (commutate (e->ops[i]));
@@ -684,7 +642,7 @@ commutate (operand *op)
return ret;
}
-void
+static void
lower_commutative (simplify *s, vec<simplify *>& simplifiers)
{
vec<operand *> matchers = commutate (s->match);
@@ -697,7 +655,9 @@ lower_commutative (simplify *s, vec<simp
}
}
-operand *
+/* Lowering of conditional converts. */
+
+static operand *
lower_opt_convert (operand *o, enum tree_code oper)
{
if (capture *c = dyn_cast<capture *> (o))
@@ -708,10 +668,10 @@ lower_opt_convert (operand *o, enum tree
return c;
}
- if (!is_a<expr *> (o))
+ expr *e = dyn_cast<expr *> (o);
+ if (!e)
return o;
- expr *e = as_a<expr *> (o);
if (*e->operation == oper)
{
expr *ne = new expr (get_operator ("CONVERT_EXPR"));
@@ -737,10 +697,10 @@ remove_opt_convert (operand *o, enum tre
return c;
}
- if (!is_a<expr *> (o))
+ expr *e = as_a<expr *> (o);
+ if (!e)
return o;
- expr *e = as_a<expr *> (o);
if (*e->operation == oper)
return remove_opt_convert (e->ops[0], oper);
@@ -751,7 +711,7 @@ remove_opt_convert (operand *o, enum tre
return ne;
}
-bool
+static bool
has_opt_convert (operand *o, enum tree_code oper)
{
if (capture *c = dyn_cast<capture *> (o))
@@ -762,11 +722,10 @@ has_opt_convert (operand *o, enum tree_c
return false;
}
- if (!is_a<expr *> (o))
+ expr *e = dyn_cast<expr *> (o);
+ if (!e)
return false;
- expr *e = as_a<expr *> (o);
-
if (*e->operation == oper)
return true;
@@ -777,7 +736,7 @@ has_opt_convert (operand *o, enum tree_c
return false;
}
-void
+static void
lower_opt_convert (vec<operand *>& v, operand *o, enum tree_code oper)
{
if (has_opt_convert (o, oper))
@@ -787,7 +746,7 @@ lower_opt_convert (vec<operand *>& v, op
}
}
-vec<operand *>
+static vec<operand *>
lower_opt_convert (operand *o)
{
vec<operand *> v1 = vNULL, v2;
@@ -813,7 +772,7 @@ lower_opt_convert (operand *o)
return v1;
}
-void
+static void
lower_opt_convert (simplify *s, vec<simplify *>& simplifiers)
{
vec<operand *> matchers = lower_opt_convert (s->match);
@@ -862,7 +821,7 @@ replace_id (operand *o, user_id *id, id_
/* Lower recorded fors for SIN and output to SIMPLIFIERS. */
-void
+static void
lower_for (simplify *sin, vec<simplify *>& simplifiers)
{
vec<vec<user_id *> >& for_vec = sin->for_vec;
@@ -918,219 +877,123 @@ lower_for (simplify *sin, vec<simplify *
simplifiers.safe_push (worklist[i]);
}
-bool
-is_conversion (id_base *op)
+/* Lower the AST for everything in SIMPLIFIERS. */
+
+static void
+lower (vec<simplify *>& simplifiers)
{
- return (*op == CONVERT_EXPR
- || *op == NOP_EXPR
- || *op == FLOAT_EXPR
- || *op == FIX_TRUNC_EXPR
- || *op == VIEW_CONVERT_EXPR);
-}
+ auto_vec<simplify *> out_simplifiers0;
+ for (unsigned i = 0; i < simplifiers.length (); ++i)
+ lower_opt_convert (simplifiers[i], out_simplifiers0);
-/* Get the type to be used for generating operands of OP from the
- various sources. */
+ auto_vec<simplify *> out_simplifiers1;
+ for (unsigned i = 0; i < out_simplifiers0.length (); ++i)
+ lower_commutative (out_simplifiers0[i], out_simplifiers1);
-static const char *
-get_operand_type (id_base *op, const char *in_type,
- const char *expr_type,
- const char *other_oprnd_type)
-{
- /* Generally operands whose type does not match the type of the
- expression generated need to know their types but match and
- thus can fall back to 'other_oprnd_type'. */
- if (is_conversion (op))
- return other_oprnd_type;
- else if (*op == REALPART_EXPR
- || *op == IMAGPART_EXPR)
- return other_oprnd_type;
- else if (is_a <operator_id *> (op)
- && strcmp (as_a <operator_id *> (op)->tcc, "tcc_comparison") == 0)
- return other_oprnd_type;
- else
- {
- /* Otherwise all types should match - choose one in order of
- preference. */
- if (expr_type)
- return expr_type;
- else if (in_type)
- return in_type;
- else
- return other_oprnd_type;
- }
+ simplifiers.truncate (0);
+ for (unsigned i = 0; i < out_simplifiers1.length (); ++i)
+ lower_for (out_simplifiers1[i], simplifiers);
}
-/* Code gen off the AST. */
-void
-expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
- const char *in_type, dt_operand **indexes)
+
+
+/* The decision tree built for generating GIMPLE and GENERIC pattern
+ matching code. It represents the 'match' expression of all
+ simplifies and has those as its leafs. */
+
+struct dt_node
{
- bool conversion_p = is_conversion (operation);
- const char *type = expr_type;
- char optype[64];
- if (type)
- /* If there was a type specification in the pattern use it. */
- ;
- else if (conversion_p)
- /* For conversions we need to build the expression using the
- outer type passed in. */
- type = in_type;
- else if (*operation == REALPART_EXPR
- || *operation == IMAGPART_EXPR)
- {
- /* __real and __imag use the component type of its operand. */
- sprintf (optype, "TREE_TYPE (TREE_TYPE (ops%d[0]))", depth);
- type = optype;
- }
- else if (is_a <operator_id *> (operation)
- && strcmp (as_a <operator_id *> (operation)->tcc, "tcc_comparison") == 0)
- {
- /* comparisons use boolean_type_node (or what gets in), but
- their operands need to figure out the types themselves. */
- sprintf (optype, "boolean_type_node");
- type = optype;
- }
- else
- {
- /* Other operations are of the same type as their first operand. */
- sprintf (optype, "TREE_TYPE (ops%d[0])", depth);
- type = optype;
- }
- if (!type)
- fatal ("two conversions in a row");
+ enum dt_type { DT_NODE, DT_OPERAND, DT_TRUE, DT_MATCH, DT_SIMPLIFY };
- fprintf (f, "{\n");
- fprintf (f, " tree ops%d[%u], res;\n", depth, ops.length ());
- char op0type[64];
- snprintf (op0type, 64, "TREE_TYPE (ops%d[0])", depth);
- for (unsigned i = 0; i < ops.length (); ++i)
- {
- char dest[32];
- snprintf (dest, 32, " ops%d[%u]", depth, i);
- const char *optype
- = get_operand_type (operation, in_type, expr_type,
- i == 0 ? NULL : op0type);
- ops[i]->gen_transform (f, dest, gimple, depth + 1, optype, indexes);
- }
+ enum dt_type type;
+ unsigned level;
+ vec<dt_node *> kids;
- if (gimple)
- {
- /* ??? Have another helper that is like gimple_build but may
- fail if seq == NULL. */
- fprintf (f, " if (!seq)\n"
- " {\n"
- " res = gimple_simplify (%s, %s",
- operation->id, type);
- for (unsigned i = 0; i < ops.length (); ++i)
- fprintf (f, ", ops%d[%u]", depth, 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, %s",
- operation->id, type);
- for (unsigned i = 0; i < ops.length (); ++i)
- fprintf (f, ", ops%d[%u]", depth, i);
- fprintf (f, ", valueize);\n");
- }
- else
- {
- if (operation->kind == id_base::CODE)
- fprintf (f, " res = fold_build%d (%s, %s",
- ops.length(), operation->id, type);
- else
- fprintf (f, " res = build_call_expr (builtin_decl_implicit (%s), %d",
- operation->id, ops.length());
- for (unsigned i = 0; i < ops.length (); ++i)
- fprintf (f, ", ops%d[%u]", depth, i);
- fprintf (f, ");\n");
- }
- fprintf (f, " %s = res;\n", dest);
- fprintf (f, "}\n");
-}
+ dt_node (enum dt_type type_): type (type_), level (0), kids (vNULL) {}
+
+ dt_node *append_node (dt_node *);
+ dt_node *append_op (operand *, dt_node *parent = 0, unsigned pos = 0);
+ dt_node *append_true_op (dt_node *parent = 0, unsigned pos = 0);
+ dt_node *append_match_op (dt_operand *, dt_node *parent = 0, unsigned pos = 0);
+ dt_node *append_simplify (simplify *, unsigned, dt_operand **);
-/* Generate code for a c_expr which is either the expression inside
- an if statement or a sequence of statements which computes a
- result to be stored to DEST. */
+ virtual void gen_gimple (FILE *) {}
+ virtual void gen_generic (FILE *) {}
-void
-c_expr::gen_transform (FILE *f, const char *dest,
- bool, int, const char *, dt_operand **)
+ void gen_gimple_kids (FILE *);
+ void gen_generic_kids (FILE *);
+};
+
+struct dt_operand : public dt_node
{
- if (dest && nr_stmts == 1)
- fprintf (f, "%s = ", dest);
+ operand *op;
+ dt_operand *match_dop;
+ dt_operand *parent;
+ unsigned pos;
+
+ dt_operand (enum dt_type type, operand *op_, dt_operand *match_dop_,
+ dt_operand *parent_ = 0, unsigned pos_ = 0)
+ : dt_node (type), op (op_), match_dop (match_dop_),
+ parent (parent_), pos (pos_) {}
- unsigned stmt_nr = 1;
- for (unsigned i = 0; i < code.length (); ++i)
- {
- const cpp_token *token = &code[i];
+ virtual void gen_gimple (FILE *);
+ virtual void gen_generic (FILE *);
+ unsigned gen_predicate (FILE *, const char *, bool);
+ unsigned gen_match_op (FILE *, const char *);
- /* Replace captures for code-gen. */
- if (token->type == CPP_ATSIGN)
- {
- const cpp_token *n = &code[i+1];
- if (n->type == CPP_NUMBER
- && !(n->flags & PREV_WHITE))
- {
- if (token->flags & PREV_WHITE)
- fputc (' ', f);
- fprintf (f, "captures[%s]", n->val.str.text);
- ++i;
- continue;
- }
- }
+ unsigned gen_gimple_expr (FILE *);
+ unsigned gen_generic_expr (FILE *, const char *);
- if (token->flags & PREV_WHITE)
- fputc (' ', f);
+ char *get_name (char *);
+ void gen_opname (char *, unsigned);
+};
- 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;
- }
+struct dt_simplify : public dt_node
+{
+ static const unsigned capture_max = 6;
+ simplify *s;
+ unsigned pattern_no;
+ dt_operand *indexes[capture_max];
+
+ dt_simplify (simplify *s_, unsigned pattern_no_, dt_operand **indexes_)
+ : dt_node (DT_SIMPLIFY), s (s_), pattern_no (pattern_no_)
+ {
+ for (unsigned i = 0; i < capture_max; ++i)
+ indexes[i] = indexes_[i];
+ }
- /* Output the token as string. */
- char *tk = (char *)cpp_token_as_text (r, token);
- fputs (tk, f);
+ void gen (FILE *f, bool);
+ virtual void gen_gimple (FILE *f) { gen (f, true); }
+ virtual void gen_generic (FILE *f) { gen (f, false); }
+};
- if (token->type == CPP_SEMICOLON)
- {
- stmt_nr++;
- if (dest && stmt_nr == nr_stmts)
- fprintf (f, "\n %s = ", dest);
- else
- fputc ('\n', f);
- }
- }
+template<>
+template<>
+inline bool
+is_a_helper <dt_operand *>::test (dt_node *n)
+{
+ return (n->type == dt_node::DT_OPERAND
+ || n->type == dt_node::DT_MATCH);
}
-void
-capture::gen_transform (FILE *f, const char *dest, bool gimple, int depth, const char *in_type, dt_operand **indexes)
+struct decision_tree
{
- if (what && is_a<expr *> (what))
- {
- int index = atoi (where);
- if (indexes[index] == 0)
- {
- char buf[20];
- sprintf (buf, "captures[%s]", where);
- what->gen_transform (f, buf, gimple, depth, in_type, NULL);
- }
- }
-
- fprintf (f, "%s = captures[%s];\n", dest, where);
-}
+ dt_node *root;
+
+ 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); }
+
+ static dt_node *insert_operand (dt_node *, operand *, dt_operand **indexes,
+ unsigned pos = 0, dt_node *parent = 0);
+ static dt_node *find_node (vec<dt_node *>&, dt_node *);
+ static bool cmp_node (dt_node *, dt_node *);
+ static void print_node (dt_node *, FILE *f = stderr, unsigned = 0);
+};
bool
cmp_operand (operand *o1, operand *o2)
@@ -1148,31 +1011,28 @@ cmp_operand (operand *o1, operand *o2)
{
expr *e1 = static_cast<expr *>(o1);
expr *e2 = static_cast<expr *>(o2);
- return strcmp (e1->operation->id, e2->operation->id) == 0;
+ return e1->operation == e2->operation;
}
else
return false;
}
-
bool
decision_tree::cmp_node (dt_node *n1, dt_node *n2)
{
if (!n1 || !n2 || n1->type != n2->type)
return false;
-
if (n1 == n2 || n1->type == dt_node::DT_TRUE)
return true;
if (n1->type == dt_node::DT_OPERAND)
- return cmp_operand ((static_cast<dt_operand *> (n1))->op, (static_cast<dt_operand *> (n2))->op);
-
+ return cmp_operand ((as_a<dt_operand *> (n1))->op,
+ (as_a<dt_operand *> (n2))->op);
else if (n1->type == dt_node::DT_MATCH)
- return (static_cast<dt_operand *> (n1))->match_dop == (static_cast<dt_operand *> (n2))->match_dop;
-
- else
- return false;
+ return ((as_a<dt_operand *> (n1))->match_dop
+ == (as_a<dt_operand *> (n2))->match_dop);
+ return false;
}
dt_node *
@@ -1212,7 +1072,7 @@ dt_node::append_node (dt_node *n)
dt_node *
dt_node::append_op (operand *op, dt_node *parent, unsigned pos)
{
- dt_operand *parent_ = static_cast<dt_operand *> (parent);
+ dt_operand *parent_ = safe_as_a<dt_operand *> (parent);
dt_node *n = new dt_operand (DT_OPERAND, op, 0, parent_, pos);
dt_node *p = append_node (n);
@@ -1225,7 +1085,7 @@ dt_node::append_op (operand *op, dt_node
dt_node *
dt_node::append_true_op (dt_node *parent, unsigned pos)
{
- dt_operand *parent_ = static_cast<dt_operand *> (parent);
+ dt_operand *parent_ = as_a<dt_operand *> (parent);
dt_node *n = new dt_operand (DT_TRUE, 0, 0, parent_, pos);
dt_node *p = append_node (n);
@@ -1260,9 +1120,8 @@ decision_tree::insert_operand (dt_node *
{
dt_node *q, *elm = 0;
- if (o->type == operand::OP_CAPTURE)
+ if (capture *c = dyn_cast<capture *> (o))
{
- capture *c = static_cast<capture *> (o);
unsigned capt_index = atoi (c->where);
if (indexes[capt_index] == 0)
@@ -1275,10 +1134,12 @@ decision_tree::insert_operand (dt_node *
goto at_assert_elm;
}
// get to the last capture
- for (operand *what = c->what; what && is_a<capture *> (what); c = as_a<capture *> (what), what = c->what)
+ for (operand *what = c->what;
+ what && is_a<capture *> (what);
+ c = as_a<capture *> (what), what = c->what)
;
- if (c->what == 0)
+ if (!c->what)
{
unsigned cc_index = atoi (c->where);
dt_operand *match_op = indexes[cc_index];
@@ -1297,13 +1158,14 @@ decision_tree::insert_operand (dt_node *
dt_operand temp (dt_node::DT_OPERAND, c->what, 0);
elm = decision_tree::find_node (p->kids, &temp);
}
-
+
at_assert_elm:
- gcc_assert (elm);
- gcc_assert (elm->type == dt_node::DT_TRUE || elm->type == dt_node::DT_OPERAND || elm->type == dt_node::DT_MATCH);
- indexes[capt_index] = static_cast<dt_operand *> (elm);
- return q;
- }
+ gcc_assert (elm->type == dt_node::DT_TRUE
+ || elm->type == dt_node::DT_OPERAND
+ || elm->type == dt_node::DT_MATCH);
+ indexes[capt_index] = static_cast<dt_operand *> (elm);
+ return q;
+ }
else
{
p = p->append_match_op (indexes[capt_index], parent, pos);
@@ -1316,11 +1178,10 @@ at_assert_elm:
p = p->append_op (o, parent, pos);
q = p;
- if (o->type == operand::OP_EXPR)
+ if (expr *e = dyn_cast <expr *>(o))
{
- expr *e = static_cast<expr *> (o);
for (unsigned i = 0; i < e->ops.length (); ++i)
- q = decision_tree::insert_operand (q, e->ops[i], indexes, i, p);
+ q = decision_tree::insert_operand (q, e->ops[i], indexes, i, p);
}
return q;
@@ -1341,6 +1202,8 @@ decision_tree::insert (struct simplify *
p->append_simplify (s, pattern_no, indexes);
}
+/* Debug functions to dump the decision tree. */
+
DEBUG_FUNCTION void
decision_tree::print_node (dt_node *p, FILE *f, unsigned indent)
{
@@ -1377,13 +1240,228 @@ decision_tree::print_node (dt_node *p, F
decision_tree::print_node (p->kids[i], f, indent + 2);
}
-
DEBUG_FUNCTION void
decision_tree::print (FILE *f)
{
return decision_tree::print_node (root, f);
}
+
+
+/* Code generation off the decision tree and the refered AST nodes. */
+
+bool
+is_conversion (id_base *op)
+{
+ return (*op == CONVERT_EXPR
+ || *op == NOP_EXPR
+ || *op == FLOAT_EXPR
+ || *op == FIX_TRUNC_EXPR
+ || *op == VIEW_CONVERT_EXPR);
+}
+
+/* Get the type to be used for generating operands of OP from the
+ various sources. */
+
+static const char *
+get_operand_type (id_base *op, const char *in_type,
+ const char *expr_type,
+ const char *other_oprnd_type)
+{
+ /* Generally operands whose type does not match the type of the
+ expression generated need to know their types but match and
+ thus can fall back to 'other_oprnd_type'. */
+ if (is_conversion (op))
+ return other_oprnd_type;
+ else if (*op == REALPART_EXPR
+ || *op == IMAGPART_EXPR)
+ return other_oprnd_type;
+ else if (is_a <operator_id *> (op)
+ && strcmp (as_a <operator_id *> (op)->tcc, "tcc_comparison") == 0)
+ return other_oprnd_type;
+ else
+ {
+ /* Otherwise all types should match - choose one in order of
+ preference. */
+ if (expr_type)
+ return expr_type;
+ else if (in_type)
+ return in_type;
+ else
+ return other_oprnd_type;
+ }
+}
+
+void
+expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
+ const char *in_type, dt_operand **indexes)
+{
+ bool conversion_p = is_conversion (operation);
+ const char *type = expr_type;
+ char optype[64];
+ if (type)
+ /* If there was a type specification in the pattern use it. */
+ ;
+ else if (conversion_p)
+ /* For conversions we need to build the expression using the
+ outer type passed in. */
+ type = in_type;
+ else if (*operation == REALPART_EXPR
+ || *operation == IMAGPART_EXPR)
+ {
+ /* __real and __imag use the component type of its operand. */
+ sprintf (optype, "TREE_TYPE (TREE_TYPE (ops%d[0]))", depth);
+ type = optype;
+ }
+ else if (is_a <operator_id *> (operation)
+ && strcmp (as_a <operator_id *> (operation)->tcc, "tcc_comparison") == 0)
+ {
+ /* comparisons use boolean_type_node (or what gets in), but
+ their operands need to figure out the types themselves. */
+ sprintf (optype, "boolean_type_node");
+ type = optype;
+ }
+ else
+ {
+ /* Other operations are of the same type as their first operand. */
+ sprintf (optype, "TREE_TYPE (ops%d[0])", depth);
+ type = optype;
+ }
+ if (!type)
+ fatal ("two conversions in a row");
+
+ fprintf (f, "{\n");
+ fprintf (f, " tree ops%d[%u], res;\n", depth, ops.length ());
+ char op0type[64];
+ snprintf (op0type, 64, "TREE_TYPE (ops%d[0])", depth);
+ for (unsigned i = 0; i < ops.length (); ++i)
+ {
+ char dest[32];
+ snprintf (dest, 32, " ops%d[%u]", depth, i);
+ const char *optype
+ = get_operand_type (operation, in_type, expr_type,
+ i == 0 ? NULL : op0type);
+ ops[i]->gen_transform (f, dest, gimple, depth + 1, optype, indexes);
+ }
+
+ if (gimple)
+ {
+ /* ??? Have another helper that is like gimple_build but may
+ fail if seq == NULL. */
+ fprintf (f, " if (!seq)\n"
+ " {\n"
+ " res = gimple_simplify (%s, %s",
+ operation->id, type);
+ for (unsigned i = 0; i < ops.length (); ++i)
+ fprintf (f, ", ops%d[%u]", depth, 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, %s",
+ operation->id, type);
+ for (unsigned i = 0; i < ops.length (); ++i)
+ fprintf (f, ", ops%d[%u]", depth, i);
+ fprintf (f, ", valueize);\n");
+ }
+ else
+ {
+ if (operation->kind == id_base::CODE)
+ fprintf (f, " res = fold_build%d (%s, %s",
+ ops.length(), operation->id, type);
+ else
+ fprintf (f, " res = build_call_expr (builtin_decl_implicit (%s), %d",
+ operation->id, ops.length());
+ for (unsigned i = 0; i < ops.length (); ++i)
+ fprintf (f, ", ops%d[%u]", depth, i);
+ fprintf (f, ");\n");
+ }
+ fprintf (f, " %s = res;\n", dest);
+ fprintf (f, "}\n");
+}
+
+/* Generate code for a c_expr which is either the expression inside
+ an if statement or a sequence of statements which computes a
+ result to be stored to DEST. */
+
+void
+c_expr::gen_transform (FILE *f, const char *dest,
+ bool, int, const char *, dt_operand **)
+{
+ if (dest && nr_stmts == 1)
+ fprintf (f, "%s = ", dest);
+
+ unsigned stmt_nr = 1;
+ for (unsigned i = 0; i < code.length (); ++i)
+ {
+ const cpp_token *token = &code[i];
+
+ /* Replace captures for code-gen. */
+ if (token->type == CPP_ATSIGN)
+ {
+ const cpp_token *n = &code[i+1];
+ if (n->type == CPP_NUMBER
+ && !(n->flags & PREV_WHITE))
+ {
+ if (token->flags & PREV_WHITE)
+ fputc (' ', f);
+ fprintf (f, "captures[%s]", n->val.str.text);
+ ++i;
+ continue;
+ }
+ }
+
+ 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 < ids.length (); ++j)
+ {
+ if (strcmp (id, ids[j].id) == 0)
+ {
+ fprintf (f, "%s", ids[j].oper);
+ break;
+ }
+ }
+ if (j < ids.length ())
+ continue;
+ }
+
+ /* Output the token as string. */
+ char *tk = (char *)cpp_token_as_text (r, token);
+ fputs (tk, f);
+
+ if (token->type == CPP_SEMICOLON)
+ {
+ stmt_nr++;
+ if (dest && stmt_nr == nr_stmts)
+ fprintf (f, "\n %s = ", dest);
+ else
+ fputc ('\n', f);
+ }
+ }
+}
+
+void
+capture::gen_transform (FILE *f, const char *dest, bool gimple, int depth, const char *in_type, dt_operand **indexes)
+{
+ if (what && is_a<expr *> (what))
+ {
+ int index = atoi (where);
+ if (indexes[index] == 0)
+ {
+ char buf[20];
+ sprintf (buf, "captures[%s]", where);
+ what->gen_transform (f, buf, gimple, depth, in_type, NULL);
+ }
+ }
+
+ fprintf (f, "%s = captures[%s];\n", dest, where);
+}
+
char *
dt_operand::get_name (char *name)
{
@@ -1515,8 +1593,9 @@ dt_node::gen_gimple_kids (FILE *f)
dt_node *true_operand = NULL;
for (unsigned i = 0; i < kids.length (); ++i)
{
- if (dt_operand *op = dyn_cast <dt_operand *> (kids[i]))
+ if (kids[i]->type == dt_node::DT_OPERAND)
{
+ dt_operand *op = as_a<dt_operand *> (kids[i]);
if (expr *e = dyn_cast <expr *> (op->op))
{
if (e->ops.length () == 0)
@@ -1856,13 +1935,17 @@ dt_node::gen_generic_kids (FILE *f)
}
}
+/* Generate code for the '(if ...)', '(with ..)' and actual transform
+ step of a '(simplify ...)' or '(match ...)'. This handles everything
+ that is not part of the decision tree (simplify->match). */
void
dt_simplify::gen (FILE *f, bool gimple)
{
fprintf (f, "{\n");
output_line_directive (f, s->result_location);
- fprintf (f, "tree captures[%u] ATTRIBUTE_UNUSED = {};\n", dt_simplify::capture_max);
+ fprintf (f, "tree captures[%u] ATTRIBUTE_UNUSED = {};\n",
+ dt_simplify::capture_max);
for (unsigned i = 0; i < dt_simplify::capture_max; ++i)
if (indexes[i])
@@ -2021,6 +2104,8 @@ dt_simplify::gen (FILE *f, bool gimple)
fprintf (f, "}\n");
}
+/* Main entry to generate code for matching GIMPLE IL off the decision
+ tree. */
void
decision_tree::gen_gimple (FILE *f)
@@ -2065,6 +2150,8 @@ decision_tree::gen_gimple (FILE *f)
}
}
+/* Main entry to generate code for matching GENERIC IL off the decision
+ tree. */
void
decision_tree::gen_generic (FILE *f)
@@ -2072,7 +2159,8 @@ decision_tree::gen_generic (FILE *f)
for (unsigned n = 1; n <= 3; ++n)
{
fprintf (f, "\ntree\n"
- "generic_simplify (enum tree_code code, tree type ATTRIBUTE_UNUSED");
+ "generic_simplify (enum tree_code code, "
+ "tree type ATTRIBUTE_UNUSED");
for (unsigned i = 0; i < n; ++i)
fprintf (f, ", tree op%d", i);
fprintf (f, ")\n");
@@ -2122,6 +2210,8 @@ decision_tree::gen_generic (FILE *f)
}
}
+/* Write a prototype for the function defined by the predicate P. */
+
void
write_predicate_prototype (FILE *f, predicate_id *p, bool gimple)
{
@@ -2131,6 +2221,8 @@ write_predicate_prototype (FILE *f, pred
gimple ? ", tree (*valueize)(tree) = NULL" : "");
}
+/* Output code to implement the predicate P from the decision tree DT. */
+
void
write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
{
@@ -2156,6 +2248,7 @@ write_predicate (FILE *f, predicate_id *
"}\n");
}
+/* Write the common header for the GIMPLE/GENERIC IL matching routines. */
static void
write_header (FILE *f, const char *head)
@@ -2168,6 +2261,9 @@ write_header (FILE *f, const char *head)
}
+
+/* Lexing helpers. */
+
/* Read the next non-whitespace token from R. */
static const cpp_token *
@@ -2204,6 +2300,9 @@ peek (cpp_reader *r)
return token;
}
+/* Peek at the next identifier token (or return NULL if the next
+ token is not an identifier or equal to ID if supplied). */
+
static const cpp_token *
peek_ident (cpp_reader *r, const char *id = 0)
{
@@ -2262,14 +2361,15 @@ get_ident (cpp_reader *r)
return (const char *)CPP_HASHNODE (token->val.node.node)->ident.str;
}
+/* Eat an identifier token with value S from R. */
+
static void
eat_ident (cpp_reader *r, const char *s)
{
- const cpp_token *token = expect (r, CPP_NAME);
- const char *t = (const char *) CPP_HASHNODE (token->val.node.node)->ident.str;
-
- if (strcmp (s, t))
- fatal_at (token, "expected %s got %s\n", s, t);
+ const cpp_token *token = peek (r);
+ const char *t = get_ident (r);
+ if (strcmp (s, t) != 0)
+ fatal_at (token, "expected '%s' got '%s'\n", s, t);
}
/* Read the next token from R and assert it is of type CPP_NUMBER and
@@ -2283,7 +2383,9 @@ get_number (cpp_reader *r)
}
-/* Parsing. */
+/* AST parsing routines. */
+
+static struct operand * parse_op (cpp_reader *r);
/* Parse the operator ID, special-casing convert?, convert1? and
convert2? */
@@ -2318,7 +2420,8 @@ parse_operation (cpp_reader *r)
return op;
}
-static struct operand * parse_op (cpp_reader *r);
+/* Parse a capture.
+ capture = '@'<number> */
static struct operand *
parse_capture (cpp_reader *r, operand *op)
@@ -2327,9 +2430,9 @@ parse_capture (cpp_reader *r, operand *o
return new capture (get_number (r), op);
}
+/* Parse an expression
+ expr = '(' <operation>[capture][flag][type] <operand>... ')' */
-/* Parse
- expr = (operation[capture] op...) */
static struct operand *
parse_expr (cpp_reader *r)
{
@@ -2379,7 +2482,8 @@ parse_expr (cpp_reader *r)
if (e->ops.length () == 2)
e->is_commutative = true;
else
- fatal_at (token, "only binary operators or function with two arguments can be marked commutative");
+ fatal_at (token, "only binary operators or function with "
+ "two arguments can be marked commutative");
}
e->expr_type = expr_type;
return op;
@@ -2389,13 +2493,13 @@ parse_expr (cpp_reader *r)
while (1);
}
-/* Parse [({] .... [})] literally recording everything as string and only
- replacing captures. */
+/* Lex native C code delimited by START recording the preprocessing tokens
+ for later processing.
+ c_expr = ('{'|'(') <pp token>... ('}'|')') */
static c_expr *
parse_c_expr (cpp_reader *r, cpp_ttype start)
{
- /* ??? Use an obstack to build the string. */
const cpp_token *token;
cpp_ttype end;
unsigned opencnt;
@@ -2420,6 +2524,7 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
&& --opencnt == 0)
break;
+ /* This is a lame way of counting the number of statements. */
if (token->type == CPP_SEMICOLON)
nr_stmts++;
@@ -2430,8 +2535,9 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
return new c_expr (r, code, nr_stmts);
}
-/* Parse
- op = predicate | ( expr ) */
+/* Parse an operand which is either an expression, a predicate or
+ a standalone capture.
+ op = predicate | expr | c_expr | capture */
static struct operand *
parse_op (cpp_reader *r)
@@ -2487,7 +2593,9 @@ parse_op (cpp_reader *r)
}
/* Parse
- 'simplify' [ <ident> ] <expr> <result-op>
+ simplify = 'simplify' <expr> <result-op>
+ or
+ match = 'match' <ident> <expr> [<result-op>]
with
<result-op> = <op> | <if> | <with>
<if> = '(' 'if' '(' <c-expr> ')' <result-op> ')'
@@ -2569,7 +2677,8 @@ parse_simplify (cpp_reader *r, source_lo
{
expr *e = dyn_cast <expr *> (op);
if (!e)
- fatal_at (token, "match operand expression cannot be captured");
+ fatal_at (token, "match operand expression cannot "
+ "be captured");
if (matcher->nargs == -1)
matcher->nargs = e->ops.length ();
if (matcher->nargs == 0
@@ -2624,9 +2733,15 @@ parse_simplify (cpp_reader *r, source_lo
}
}
+/* Parsing of the outer control structures. */
+
void parse_pattern (cpp_reader *, vec<simplify *>&,
vec<if_or_with>&, vec<vec<user_id *> >&);
+/* Parse a for expression
+ for = '(' 'for' <subst>... <pattern> ')'
+ subst = <ident> '(' <ident>... ')' */
+
void
parse_for (cpp_reader *r, source_location, vec<simplify *>& simplifiers,
vec<if_or_with>& active_ifs, vec<vec<user_id *> >& active_fors)
@@ -2721,6 +2836,9 @@ parse_for (cpp_reader *r, source_locatio
operators->remove_elt (user_ids[i]);
}
+/* Parse an outer if expression.
+ if = '(' 'if' '(' <c-expr> ')' <pattern> ')' */
+
void
parse_if (cpp_reader *r, source_location loc, vec<simplify *>& simplifiers,
vec<if_or_with>& active_ifs, vec<vec<user_id *> >& active_fors)
@@ -2743,6 +2861,9 @@ parse_if (cpp_reader *r, source_location
active_ifs.pop ();
}
+/* Parse a list of predefined predicate identifiers.
+ preds = '(' 'define_predicates' <ident>... ')' */
+
static void
parse_predicates (cpp_reader *r, source_location)
{
@@ -2757,11 +2878,8 @@ parse_predicates (cpp_reader *r, source_
while (1);
}
-static size_t
-round_alloc_size (size_t s)
-{
- return s;
-}
+/* Main entry for the parser. Parse outer control structures.
+ pattern = <preds>|<for>|<if>|<simplify>|<match> */
void
parse_pattern (cpp_reader *r, vec<simplify *>& simplifiers,
@@ -2807,23 +2925,15 @@ parse_pattern (cpp_reader *r, vec<simpli
eat_token (r, CPP_CLOSE_PAREN);
}
-static vec<simplify *>
-lower (vec<simplify *> simplifiers)
+static size_t
+round_alloc_size (size_t s)
{
- vec<simplify *> out_simplifiers0 = vNULL;
- for (unsigned i = 0; i < simplifiers.length (); ++i)
- lower_opt_convert (simplifiers[i], out_simplifiers0);
-
- vec<simplify *> out_simplifiers1 = vNULL;
- for (unsigned i = 0; i < out_simplifiers0.length (); ++i)
- lower_commutative (out_simplifiers0[i], out_simplifiers1);
+ return s;
+}
- vec<simplify *> out_simplifiers = vNULL;
- for (unsigned i = 0; i < out_simplifiers1.length (); ++i)
- lower_for (out_simplifiers1[i], out_simplifiers);
- return out_simplifiers;
-}
+/* The genmatch generator progam. It reads from a pattern description
+ and outputs GIMPLE or GENERIC IL matching and simplification routines. */
int
main(int argc, char **argv)
@@ -2922,16 +3032,15 @@ add_operator (CONVERT2, "CONVERT2", "tcc
if (predicate_id *p = dyn_cast <predicate_id *> (id))
if (p->matchers.exists ())
{
- vec<simplify *> matchers = lower (p->matchers);
- p->matchers = matchers;
+ lower (p->matchers);
if (verbose)
- for (unsigned i = 0; i < matchers.length (); ++i)
- print_matches (matchers[i]);
+ for (unsigned i = 0; i < p->matchers.length (); ++i)
+ print_matches (p->matchers[i]);
decision_tree dt;
- for (unsigned i = 0; i < matchers.length (); ++i)
- dt.insert (matchers[i], i);
+ for (unsigned i = 0; i < p->matchers.length (); ++i)
+ dt.insert (p->matchers[i], i);
if (verbose)
dt.print (stderr);
@@ -2940,15 +3049,16 @@ add_operator (CONVERT2, "CONVERT2", "tcc
}
}
- vec<simplify *> out_simplifiers = lower (simplifiers);
+ /* Lower the main simplifiers and generate code for them. */
+ lower (simplifiers);
if (verbose)
- for (unsigned i = 0; i < out_simplifiers.length (); ++i)
- print_matches (out_simplifiers[i]);
+ for (unsigned i = 0; i < simplifiers.length (); ++i)
+ print_matches (simplifiers[i]);
decision_tree dt;
- for (unsigned i = 0; i < out_simplifiers.length (); ++i)
- dt.insert (out_simplifiers[i], i);
+ for (unsigned i = 0; i < simplifiers.length (); ++i)
+ dt.insert (simplifiers[i], i);
if (verbose)
dt.print (stderr);
@@ -2958,6 +3068,7 @@ add_operator (CONVERT2, "CONVERT2", "tcc
else
dt.gen_generic (stdout);
+ /* Finalize. */
cpp_finish (r, NULL);
cpp_destroy (r);