aboutsummaryrefslogtreecommitdiff
path: root/gcc/genmatch.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/genmatch.c')
-rw-r--r--gcc/genmatch.c165
1 files changed, 106 insertions, 59 deletions
diff --git a/gcc/genmatch.c b/gcc/genmatch.c
index 7045bb9103c..9da911a3695 100644
--- a/gcc/genmatch.c
+++ b/gcc/genmatch.c
@@ -793,13 +793,17 @@ struct simplify
{
enum simplify_kind { SIMPLIFY, MATCH };
- simplify (simplify_kind kind_, operand *match_, operand *result_,
- vec<vec<user_id *> > for_vec_, cid_map_t *capture_ids_)
- : kind (kind_), match (match_), result (result_),
+ simplify (simplify_kind kind_, unsigned id_, operand *match_,
+ operand *result_, vec<vec<user_id *> > for_vec_,
+ cid_map_t *capture_ids_)
+ : kind (kind_), id (id_), match (match_), result (result_),
for_vec (for_vec_), for_subst_vec (vNULL),
capture_ids (capture_ids_), capture_max (capture_ids_->elements () - 1) {}
simplify_kind kind;
+ /* ID. This is kept to easily associate related simplifies expanded
+ from the same original one. */
+ unsigned id;
/* The expression that is matched against the GENERIC or GIMPLE IL. */
operand *match;
/* For a (simplify ...) an expression with ifs and withs with the expression
@@ -1008,7 +1012,7 @@ lower_commutative (simplify *s, vec<simplify *>& simplifiers)
vec<operand *> matchers = commutate (s->match, s->for_vec);
for (unsigned i = 0; i < matchers.length (); ++i)
{
- simplify *ns = new simplify (s->kind, matchers[i], s->result,
+ simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result,
s->for_vec, s->capture_ids);
simplifiers.safe_push (ns);
}
@@ -1137,7 +1141,7 @@ lower_opt_convert (simplify *s, vec<simplify *>& simplifiers)
vec<operand *> matchers = lower_opt_convert (s->match);
for (unsigned i = 0; i < matchers.length (); ++i)
{
- simplify *ns = new simplify (s->kind, matchers[i], s->result,
+ simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result,
s->for_vec, s->capture_ids);
simplifiers.safe_push (ns);
}
@@ -1238,7 +1242,7 @@ lower_cond (simplify *s, vec<simplify *>& simplifiers)
vec<operand *> matchers = lower_cond (s->match);
for (unsigned i = 0; i < matchers.length (); ++i)
{
- simplify *ns = new simplify (s->kind, matchers[i], s->result,
+ simplify *ns = new simplify (s->kind, s->id, matchers[i], s->result,
s->for_vec, s->capture_ids);
simplifiers.safe_push (ns);
}
@@ -1453,7 +1457,7 @@ lower_for (simplify *sin, vec<simplify *>& simplifiers)
if (skip)
continue;
- simplify *ns = new simplify (s->kind, match_op, result_op,
+ simplify *ns = new simplify (s->kind, s->id, match_op, result_op,
vNULL, s->capture_ids);
ns->for_subst_vec.safe_splice (s->for_subst_vec);
if (result_op
@@ -1527,8 +1531,11 @@ struct sinfo_hashmap_traits : simple_hashmap_traits<pointer_hash<dt_simplify>,
typedef hash_map<void * /* unused */, sinfo *, sinfo_hashmap_traits>
sinfo_map_t;
+/* Current simplifier ID we are processing during insertion into the
+ decision tree. */
+static unsigned current_id;
-/* Decision tree base class, used for DT_TRUE and DT_NODE. */
+/* Decision tree base class, used for DT_NODE. */
struct dt_node
{
@@ -1536,6 +1543,7 @@ struct dt_node
enum dt_type type;
unsigned level;
+ dt_node *parent;
vec<dt_node *> kids;
/* Statistics. */
@@ -1543,12 +1551,14 @@ struct dt_node
unsigned total_size;
unsigned max_level;
- dt_node (enum dt_type type_): type (type_), level (0), kids (vNULL) {}
+ dt_node (enum dt_type type_, dt_node *parent_)
+ : type (type_), level (0), parent (parent_), 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_op (operand *, dt_node *parent, unsigned pos);
+ dt_node *append_true_op (operand *, dt_node *parent, unsigned pos);
+ dt_node *append_match_op (operand *, dt_operand *, dt_node *parent,
+ unsigned pos);
dt_node *append_simplify (simplify *, unsigned, dt_operand **);
virtual void gen (FILE *, int, bool) {}
@@ -1561,20 +1571,20 @@ struct dt_node
void analyze (sinfo_map_t &);
};
-/* Generic decision tree node used for DT_OPERAND and DT_MATCH. */
+/* Generic decision tree node used for DT_OPERAND, DT_MATCH and DT_TRUE. */
struct dt_operand : public dt_node
{
operand *op;
dt_operand *match_dop;
- dt_operand *parent;
unsigned pos;
bool value_match;
+ unsigned for_id;
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_), value_match (false) {}
+ dt_operand *parent_, unsigned pos_)
+ : dt_node (type, parent_), op (op_), match_dop (match_dop_),
+ pos (pos_), value_match (false), for_id (current_id) {}
void gen (FILE *, int, bool);
unsigned gen_predicate (FILE *, int, const char *, bool);
@@ -1597,7 +1607,7 @@ struct dt_simplify : public dt_node
sinfo *info;
dt_simplify (simplify *s_, unsigned pattern_no_, dt_operand **indexes_)
- : dt_node (DT_SIMPLIFY), s (s_), pattern_no (pattern_no_),
+ : dt_node (DT_SIMPLIFY, NULL), s (s_), pattern_no (pattern_no_),
indexes (indexes_), info (NULL) {}
void gen_1 (FILE *, int, bool, operand *);
@@ -1610,7 +1620,8 @@ inline bool
is_a_helper <dt_operand *>::test (dt_node *n)
{
return (n->type == dt_node::DT_OPERAND
- || n->type == dt_node::DT_MATCH);
+ || n->type == dt_node::DT_MATCH
+ || n->type == dt_node::DT_TRUE);
}
template<>
@@ -1633,7 +1644,7 @@ struct decision_tree
void gen (FILE *f, bool gimple);
void print (FILE *f = stderr);
- decision_tree () { root = new dt_node (dt_node::DT_NODE); }
+ decision_tree () { root = new dt_node (dt_node::DT_NODE, NULL); }
static dt_node *insert_operand (dt_node *, operand *, dt_operand **indexes,
unsigned pos = 0, dt_node *parent = 0);
@@ -1703,15 +1714,48 @@ decision_tree::find_node (vec<dt_node *>& ops, dt_node *p)
&& !ops.is_empty ()
&& ops.last ()->type == dt_node::DT_TRUE)
return ops.last ();
+ dt_operand *true_node = NULL;
for (int i = ops.length () - 1; i >= 0; --i)
{
/* But we can't merge across DT_TRUE nodes as they serve as
pattern order barriers to make sure that patterns apply
in order of appearance in case multiple matches are possible. */
if (ops[i]->type == dt_node::DT_TRUE)
- return NULL;
+ {
+ if (! true_node
+ || as_a <dt_operand *> (ops[i])->for_id > true_node->for_id)
+ true_node = as_a <dt_operand *> (ops[i]);
+ }
if (decision_tree::cmp_node (ops[i], p))
- return ops[i];
+ {
+ /* Unless we are processing the same pattern or the blocking
+ pattern is before the one we are going to merge with. */
+ if (true_node
+ && true_node->for_id != current_id
+ && true_node->for_id > as_a <dt_operand *> (ops[i])->for_id)
+ {
+ if (verbose >= 1)
+ {
+ source_location p_loc = 0;
+ if (p->type == dt_node::DT_OPERAND)
+ p_loc = as_a <dt_operand *> (p)->op->location;
+ source_location op_loc = 0;
+ if (ops[i]->type == dt_node::DT_OPERAND)
+ op_loc = as_a <dt_operand *> (ops[i])->op->location;
+ source_location true_loc = 0;
+ true_loc = true_node->op->location;
+ warning_at (p_loc,
+ "failed to merge decision tree node");
+ warning_at (op_loc,
+ "with the following");
+ warning_at (true_loc,
+ "because of the following which serves as ordering "
+ "barrier");
+ }
+ return NULL;
+ }
+ return ops[i];
+ }
}
return NULL;
}
@@ -1747,20 +1791,21 @@ dt_node::append_op (operand *op, dt_node *parent, unsigned pos)
/* Append a DT_TRUE decision tree node. */
dt_node *
-dt_node::append_true_op (dt_node *parent, unsigned pos)
+dt_node::append_true_op (operand *op, dt_node *parent, unsigned pos)
{
dt_operand *parent_ = safe_as_a<dt_operand *> (parent);
- dt_operand *n = new dt_operand (DT_TRUE, 0, 0, parent_, pos);
+ dt_operand *n = new dt_operand (DT_TRUE, op, 0, parent_, pos);
return append_node (n);
}
/* Append a DT_MATCH decision tree node. */
dt_node *
-dt_node::append_match_op (dt_operand *match_dop, dt_node *parent, unsigned pos)
+dt_node::append_match_op (operand *op, dt_operand *match_dop,
+ dt_node *parent, unsigned pos)
{
dt_operand *parent_ = as_a<dt_operand *> (parent);
- dt_operand *n = new dt_operand (DT_MATCH, 0, match_dop, parent_, pos);
+ dt_operand *n = new dt_operand (DT_MATCH, op, match_dop, parent_, pos);
return append_node (n);
}
@@ -1839,7 +1884,7 @@ decision_tree::insert_operand (dt_node *p, operand *o, dt_operand **indexes,
q = insert_operand (p, c->what, indexes, pos, parent);
else
{
- q = elm = p->append_true_op (parent, pos);
+ q = elm = p->append_true_op (o, parent, pos);
goto at_assert_elm;
}
// get to the last capture
@@ -1853,19 +1898,19 @@ decision_tree::insert_operand (dt_node *p, operand *o, dt_operand **indexes,
unsigned cc_index = c->where;
dt_operand *match_op = indexes[cc_index];
- dt_operand temp (dt_node::DT_TRUE, 0, 0);
+ dt_operand temp (dt_node::DT_TRUE, 0, 0, 0, 0);
elm = decision_tree::find_node (p->kids, &temp);
if (elm == 0)
{
- dt_operand temp (dt_node::DT_MATCH, 0, match_op);
+ dt_operand temp (dt_node::DT_MATCH, 0, match_op, 0, 0);
temp.value_match = c->value_match;
elm = decision_tree::find_node (p->kids, &temp);
}
}
else
{
- dt_operand temp (dt_node::DT_OPERAND, c->what, 0);
+ dt_operand temp (dt_node::DT_OPERAND, c->what, 0, 0, 0);
elm = decision_tree::find_node (p->kids, &temp);
}
@@ -1878,7 +1923,7 @@ at_assert_elm:
}
else
{
- p = p->append_match_op (indexes[capt_index], parent, pos);
+ p = p->append_match_op (o, indexes[capt_index], parent, pos);
as_a <dt_operand *>(p)->value_match = c->value_match;
if (c->what)
return insert_operand (p, c->what, indexes, 0, p);
@@ -1903,6 +1948,7 @@ at_assert_elm:
void
decision_tree::insert (struct simplify *s, unsigned pattern_no)
{
+ current_id = s->id;
dt_operand **indexes = XCNEWVEC (dt_operand *, s->capture_max + 1);
dt_node *p = decision_tree::insert_operand (root, s->match, indexes);
p->append_simplify (s, pattern_no, indexes);
@@ -1938,9 +1984,12 @@ decision_tree::print_node (dt_node *p, FILE *f, unsigned indent)
fprintf (f, "%p, ", (void *) s->indexes[i]);
fprintf (f, " } ");
}
+ if (is_a <dt_operand *> (p))
+ fprintf (f, " [%u]", as_a <dt_operand *> (p)->for_id);
}
- fprintf (stderr, " (%p), %u, %u\n", (void *) p, p->level, p->kids.length ());
+ fprintf (stderr, " (%p, %p), %u, %u\n",
+ (void *) p, (void *) p->parent, p->level, p->kids.length ());
for (unsigned i = 0; i < p->kids.length (); ++i)
decision_tree::print_node (p->kids[i], f, indent + 2);
@@ -2572,12 +2621,12 @@ capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
char *
dt_operand::get_name (char *name)
{
- if (!parent)
+ if (! parent)
sprintf (name, "t");
else if (parent->level == 1)
sprintf (name, "op%u", pos);
else if (parent->type == dt_node::DT_MATCH)
- return parent->get_name (name);
+ return as_a <dt_operand *> (parent)->get_name (name);
else
sprintf (name, "o%u%u", parent->level, pos);
return name;
@@ -2588,7 +2637,7 @@ dt_operand::get_name (char *name)
void
dt_operand::gen_opname (char *name, unsigned pos)
{
- if (!parent)
+ if (! parent)
sprintf (name, "op%u", pos);
else
sprintf (name, "o%u%u", level, pos);
@@ -2646,6 +2695,7 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
expr *e = static_cast<expr *> (op);
id_base *id = e->operation;
unsigned n_ops = e->ops.length ();
+ unsigned n_braces = 0;
for (unsigned i = 0; i < n_ops; ++i)
{
@@ -2678,14 +2728,15 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
"if ((TREE_CODE (%s) == SSA_NAME\n",
child_opname);
fprintf_indent (f, indent,
- " || is_gimple_min_invariant (%s))\n",
+ " || is_gimple_min_invariant (%s)))\n",
child_opname);
fprintf_indent (f, indent,
- " && (%s = do_valueize (valueize, %s)))\n",
- child_opname, child_opname);
- fprintf_indent (f, indent,
" {\n");
indent += 4;
+ n_braces++;
+ fprintf_indent (f, indent,
+ "%s = do_valueize (valueize, %s);\n",
+ child_opname, child_opname);
continue;
}
else
@@ -2698,10 +2749,8 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
"tree %s = gimple_call_arg (def, %u);\n",
child_opname, i);
fprintf_indent (f, indent,
- "if ((%s = do_valueize (valueize, %s)))\n",
+ "%s = do_valueize (valueize, %s);\n",
child_opname, child_opname);
- fprintf_indent (f, indent, " {\n");
- indent += 4;
}
/* While the toplevel operands are canonicalized by the caller
after valueizing operands of sub-expressions we have to
@@ -2726,7 +2775,7 @@ dt_operand::gen_gimple_expr (FILE *f, int indent)
}
}
- return n_ops;
+ return n_braces;
}
/* Generate GENERIC matching code for the decision tree operand. */
@@ -2867,14 +2916,10 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple,
fprintf_indent (f, indent,
"case SSA_NAME:\n");
fprintf_indent (f, indent,
- " if (do_valueize (valueize, %s) != NULL_TREE)\n",
+ " if (gimple *def_stmt = get_def (valueize, %s))\n",
kid_opname);
fprintf_indent (f, indent,
" {\n");
- fprintf_indent (f, indent,
- " gimple *def_stmt = SSA_NAME_DEF_STMT (%s);\n",
- kid_opname);
-
indent += 6;
if (exprs_len)
{
@@ -3461,11 +3506,11 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
if (! s->for_subst_vec[i].first->used)
continue;
if (is_a <operator_id *> (s->for_subst_vec[i].second))
- fprintf_indent (f, indent, "enum tree_code %s = %s;\n",
+ fprintf_indent (f, indent, "const enum tree_code %s = %s;\n",
s->for_subst_vec[i].first->id,
s->for_subst_vec[i].second->id);
else if (is_a <fn_id *> (s->for_subst_vec[i].second))
- fprintf_indent (f, indent, "combined_fn %s = %s;\n",
+ fprintf_indent (f, indent, "const combined_fn %s = %s;\n",
s->for_subst_vec[i].first->id,
s->for_subst_vec[i].second->id);
else
@@ -3601,13 +3646,13 @@ decision_tree::gen (FILE *f, bool gimple)
"%s (code_helper *res_code, tree *res_ops,\n"
" gimple_seq *seq, tree (*valueize)(tree) "
"ATTRIBUTE_UNUSED,\n"
- " tree ARG_UNUSED (type), tree *ARG_UNUSED "
+ " const tree ARG_UNUSED (type), tree *ARG_UNUSED "
"(captures)\n",
s->fname);
else
{
fprintf (f, "\nstatic tree\n"
- "%s (location_t ARG_UNUSED (loc), tree ARG_UNUSED (type),\n",
+ "%s (location_t ARG_UNUSED (loc), const tree ARG_UNUSED (type),\n",
(*iter).second->fname);
for (unsigned i = 0;
i < as_a <expr *>(s->s->s->match)->ops.length (); ++i)
@@ -3619,10 +3664,10 @@ decision_tree::gen (FILE *f, bool gimple)
if (! s->s->s->for_subst_vec[i].first->used)
continue;
if (is_a <operator_id *> (s->s->s->for_subst_vec[i].second))
- fprintf (f, ", enum tree_code ARG_UNUSED (%s)",
+ fprintf (f, ", const enum tree_code ARG_UNUSED (%s)",
s->s->s->for_subst_vec[i].first->id);
else if (is_a <fn_id *> (s->s->s->for_subst_vec[i].second))
- fprintf (f, ", combined_fn ARG_UNUSED (%s)",
+ fprintf (f, ", const combined_fn ARG_UNUSED (%s)",
s->s->s->for_subst_vec[i].first->id);
}
@@ -3663,7 +3708,7 @@ decision_tree::gen (FILE *f, bool gimple)
else
fprintf (f, "\nstatic tree\n"
"generic_simplify_%s (location_t ARG_UNUSED (loc), enum "
- "tree_code ARG_UNUSED (code), tree ARG_UNUSED (type)",
+ "tree_code ARG_UNUSED (code), const tree ARG_UNUSED (type)",
e->operation->id);
for (unsigned i = 0; i < n; ++i)
fprintf (f, ", tree op%d", i);
@@ -3683,11 +3728,11 @@ decision_tree::gen (FILE *f, bool gimple)
fprintf (f, "\nstatic bool\n"
"gimple_simplify (code_helper *res_code, tree *res_ops,\n"
" gimple_seq *seq, tree (*valueize)(tree),\n"
- " code_helper code, tree type");
+ " code_helper code, const tree type");
else
fprintf (f, "\ntree\n"
"generic_simplify (location_t loc, enum tree_code code, "
- "tree type ATTRIBUTE_UNUSED");
+ "const tree type ATTRIBUTE_UNUSED");
for (unsigned i = 0; i < n; ++i)
fprintf (f, ", tree op%d", i);
fprintf (f, ")\n");
@@ -3751,7 +3796,7 @@ write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
p->nargs > 0 ? ", tree *res_ops" : "",
gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : "");
/* Conveniently make 'type' available. */
- fprintf_indent (f, 2, "tree type = TREE_TYPE (t);\n");
+ fprintf_indent (f, 2, "const tree type = TREE_TYPE (t);\n");
if (!gimple)
fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
@@ -3823,6 +3868,7 @@ private:
vec<user_id *> oper_lists;
cid_map_t *capture_ids;
+ unsigned last_id;
public:
vec<simplify *> simplifiers;
@@ -4318,7 +4364,7 @@ parser::push_simplify (simplify::simplify_kind kind,
active_fors.safe_push (oper_lists);
simplifiers.safe_push
- (new simplify (kind, match, result,
+ (new simplify (kind, last_id++, match, result,
active_fors.copy (), capture_ids));
if (!oper_lists.is_empty ())
@@ -4883,6 +4929,7 @@ parser::parser (cpp_reader *r_)
capture_ids = NULL;
user_predicates = vNULL;
parsing_match_operand = false;
+ last_id = 0;
const cpp_token *token = next ();
while (token->type != CPP_EOF)