aboutsummaryrefslogtreecommitdiff
path: root/gcc/genmatch.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/genmatch.cc')
-rw-r--r--gcc/genmatch.cc201
1 files changed, 154 insertions, 47 deletions
diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
index 85bd77a..c6097cd 100644
--- a/gcc/genmatch.cc
+++ b/gcc/genmatch.cc
@@ -1485,7 +1485,7 @@ public:
virtual void gen_transform (FILE *, int, const char *, bool, int,
const char *, capture_info *,
dt_operand ** = 0,
- int = 0)
+ int = 0, const char * = nullptr)
{ gcc_unreachable (); }
};
@@ -1538,8 +1538,8 @@ public:
/* If non-zero, the group for optional handling. */
unsigned char opt_grp;
void gen_transform (FILE *f, int, const char *, bool, int,
- const char *, capture_info *,
- dt_operand ** = 0, int = 0) override;
+ const char *, capture_info *, dt_operand ** = 0,
+ int = 0, const char * = nullptr) override;
};
/* An operator that is represented by native C code. This is always
@@ -1572,8 +1572,8 @@ public:
/* The identifier replacement vector. */
vec<id_tab> ids;
void gen_transform (FILE *f, int, const char *, bool, int,
- const char *, capture_info *,
- dt_operand ** = 0, int = 0) final override;
+ const char *, capture_info *, dt_operand ** = 0,
+ int = 0, const char * = nullptr) final override;
};
/* A wrapper around another operand that captures its value. */
@@ -1593,8 +1593,8 @@ public:
/* The captured value. */
operand *what;
void gen_transform (FILE *f, int, const char *, bool, int,
- const char *, capture_info *,
- dt_operand ** = 0, int = 0) final override;
+ const char *, capture_info *, dt_operand ** = 0,
+ int = 0, const char * = nullptr) final override;
};
/* if expression. */
@@ -3196,6 +3196,14 @@ is_conversion (id_base *op)
|| *op == VIEW_CONVERT_EXPR);
}
+bool
+possible_noop_convert (id_base *op)
+{
+ return (*op == CONVERT_EXPR
+ || *op == NOP_EXPR
+ || *op == VIEW_CONVERT_EXPR);
+}
+
/* Get the type to be used for generating operand POS of OP from the
various sources. */
@@ -3249,7 +3257,7 @@ get_operand_type (id_base *op, unsigned pos,
void
expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
int depth, const char *in_type, capture_info *cinfo,
- dt_operand **indexes, int)
+ dt_operand **indexes, int, const char *in_place)
{
id_base *opr = operation;
/* When we delay operator substituting during lowering of fors we
@@ -3307,10 +3315,23 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
if (!type)
fatal_at (location, "cannot determine type of operand");
+ bool child_in_place = (!in_place
+ && gimple
+ && possible_noop_convert (opr)
+ && is_a <expr *> (ops[0]));
+
fprintf_indent (f, indent, "{\n");
indent += 2;
- fprintf_indent (f, indent,
- "tree _o%d[%u], _r%d;\n", depth, ops.length (), depth);
+ if (child_in_place)
+ {
+ fprintf_indent (f, indent, "tree _r%d;\n", depth);
+ fprintf_indent (f, indent,
+ "gimple_match_op tem_op (res_op->cond.any_else (), "
+ "ERROR_MARK, error_mark_node, 1);\n");
+ }
+ else
+ fprintf_indent (f, indent,
+ "tree _o%d[%u], _r%d;\n", depth, ops.length (), depth);
char op0type[64];
snprintf (op0type, sizeof (op0type), "TREE_TYPE (_o%d[0])", depth);
for (unsigned i = 0; i < ops.length (); ++i)
@@ -3322,7 +3343,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
i == 0 ? NULL : op0type);
ops[i]->gen_transform (f, indent, dest1, gimple, depth + 1, optype1,
cinfo, indexes,
- *opr == COND_EXPR && i == 0 ? 1 : 2);
+ *opr == COND_EXPR && i == 0 ? 1 : 2,
+ child_in_place ? "tem_op" : NULL);
}
const char *opr_name;
@@ -3333,45 +3355,95 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
if (gimple)
{
- if (*opr == CONVERT_EXPR)
+ if (child_in_place)
{
+ gcc_assert (!in_place);
fprintf_indent (f, indent,
- "if (%s != TREE_TYPE (_o%d[0])\n",
- type, depth);
+ "if (%s != tem_op.type\n", type);
fprintf_indent (f, indent,
- " && !useless_type_conversion_p (%s, TREE_TYPE "
- "(_o%d[0])))\n",
- type, depth);
+ " && !useless_type_conversion_p (%s, tem_op.type))\n",
+ type);
fprintf_indent (f, indent + 2, "{\n");
indent += 4;
+ fprintf_indent (f, indent,
+ "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n",
+ depth, (!as_a <expr *> (ops[0])->force_leaf
+ ? "lseq" : "NULL"));
+ fprintf_indent (f, indent,
+ "if (!_r%d) goto %s;\n", depth, fail_label);
+ fprintf_indent (f, indent,
+ "tem_op.set_op (%s, %s, 1);\n", opr_name, type);
+ fprintf_indent (f, indent,
+ "tem_op.ops[0] = _r%d;\n", depth);
+ fprintf_indent (f, indent,
+ "tem_op.resimplify (%s, valueize);\n",
+ !force_leaf ? "lseq" : "NULL");
+ indent -= 4;
+ fprintf_indent (f, indent + 2, "}\n");
+ fprintf_indent (f, indent,
+ "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n",
+ depth, !force_leaf ? "lseq" : "NULL");
+ fprintf_indent (f, indent,
+ "if (!_r%d) goto %s;\n", depth, fail_label);
}
- /* ??? Building a stmt can fail for various reasons here, seq being
- NULL or the stmt referencing SSA names occuring in abnormal PHIs.
- So if we fail here we should continue matching other patterns. */
- fprintf_indent (f, indent, "gimple_match_op tem_op "
- "(res_op->cond.any_else (), %s, %s", opr_name, type);
- for (unsigned i = 0; i < ops.length (); ++i)
- fprintf (f, ", _o%d[%u]", depth, i);
- fprintf (f, ");\n");
- fprintf_indent (f, indent, "tem_op.resimplify (%s, valueize);\n",
- !force_leaf ? "lseq" : "NULL");
- fprintf_indent (f, indent,
- "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n", depth,
- !force_leaf ? "lseq" : "NULL");
- fprintf_indent (f, indent,
- "if (!_r%d) goto %s;\n",
- depth, fail_label);
- if (*opr == CONVERT_EXPR)
+ else if (in_place)
{
- indent -= 4;
- fprintf_indent (f, indent, " }\n");
- fprintf_indent (f, indent, "else\n");
- fprintf_indent (f, indent, " _r%d = _o%d[0];\n", depth, depth);
+ gcc_assert (!child_in_place);
+ fprintf_indent (f, indent,
+ "%s.set_op (%s, %s, %d);\n", in_place,
+ opr_name, type, ops.length ());
+ for (unsigned i = 0; i < ops.length (); ++i)
+ fprintf_indent (f, indent,
+ "%s.ops[%u] = _o%d[%u];\n", in_place, i, depth, i);
+ fprintf_indent (f, indent,
+ "%s.resimplify (%s, valueize);\n",
+ in_place, !force_leaf ? "lseq" : "NULL");
+ indent -= 2;
+ fprintf_indent (f, indent, "}\n");
+ return;
+ }
+ else
+ {
+ if (possible_noop_convert (opr))
+ {
+ fprintf_indent (f, indent,
+ "if (%s != TREE_TYPE (_o%d[0]) /* XXX */\n",
+ type, depth);
+ fprintf_indent (f, indent,
+ " && !useless_type_conversion_p (%s, TREE_TYPE "
+ "(_o%d[0])))\n",
+ type, depth);
+ fprintf_indent (f, indent + 2, "{\n");
+ indent += 4;
+ }
+ /* ??? Building a stmt can fail for various reasons here, seq being
+ NULL or the stmt referencing SSA names occuring in abnormal PHIs.
+ So if we fail here we should continue matching other patterns. */
+ fprintf_indent (f, indent, "gimple_match_op tem_op "
+ "(res_op->cond.any_else (), %s, %s", opr_name, type);
+ for (unsigned i = 0; i < ops.length (); ++i)
+ fprintf (f, ", _o%d[%u]", depth, i);
+ fprintf (f, ");\n");
+ fprintf_indent (f, indent, "tem_op.resimplify (%s, valueize);\n",
+ !force_leaf ? "lseq" : "NULL");
+ fprintf_indent (f, indent,
+ "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n",
+ depth, !force_leaf ? "lseq" : "NULL");
+ fprintf_indent (f, indent,
+ "if (!_r%d) goto %s;\n",
+ depth, fail_label);
+ if (possible_noop_convert (opr))
+ {
+ indent -= 4;
+ fprintf_indent (f, indent, " }\n");
+ fprintf_indent (f, indent, "else\n");
+ fprintf_indent (f, indent, " _r%d = _o%d[0];\n", depth, depth);
+ }
}
}
else
{
- if (*opr == CONVERT_EXPR)
+ if (possible_noop_convert (opr))
{
fprintf_indent (f, indent, "if (TREE_TYPE (_o%d[0]) != %s)\n",
depth, type);
@@ -3397,7 +3469,7 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
fprintf_indent (f, indent, "if (EXPR_P (_r%d))\n", depth);
fprintf_indent (f, indent, " goto %s;\n", fail_label);
}
- if (*opr == CONVERT_EXPR)
+ if (possible_noop_convert (opr))
{
fprintf_indent (f, indent - 2, "}\n");
indent -= 4;
@@ -3417,8 +3489,10 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
void
c_expr::gen_transform (FILE *f, int indent, const char *dest,
bool, int, const char *, capture_info *,
- dt_operand **, int)
+ dt_operand **, int, const char *in_place)
{
+ gcc_assert (!in_place);
+
if (dest && nr_stmts == 1)
fprintf_indent (f, indent, "%s = ", dest);
@@ -3501,8 +3575,11 @@ c_expr::gen_transform (FILE *f, int indent, const char *dest,
void
capture::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
int depth, const char *in_type, capture_info *cinfo,
- dt_operand **indexes, int cond_handling)
+ dt_operand **indexes, int cond_handling,
+ const char *in_place)
{
+ gcc_assert (!in_place);
+
if (what && is_a<expr *> (what))
{
if (indexes[where] == 0)
@@ -4353,7 +4430,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
if (s->kind == simplify::SIMPLIFY)
{
- fprintf_indent (f, indent, "if (UNLIKELY (!dbg_cnt (match))) goto %s;\n", fail_label);
+ fprintf_indent (f, indent, "if (UNLIKELY (!dbg_cnt (match))) goto %s;\n",
+ fail_label);
needs_label = true;
}
@@ -4408,16 +4486,45 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
if (!is_predicate)
cond_handling = (*opr == COND_EXPR && j == 0) ? 1 : 2;
e->ops[j]->gen_transform (f, indent, dest, true, 1, optype,
- &cinfo, indexes, cond_handling);
+ &cinfo, indexes, cond_handling,
+ (possible_noop_convert (opr)
+ && is_a <expr *> (e->ops[j]))
+ ? "(*res_op)" : NULL);
}
/* Re-fold the toplevel result. It's basically an embedded
gimple_build w/o actually building the stmt. */
if (!is_predicate)
{
- fprintf_indent (f, indent,
- "res_op->resimplify (%s, valueize);\n",
- !e->force_leaf ? "lseq" : "NULL");
+ if (possible_noop_convert (opr)
+ && is_a <expr *> (e->ops[0]))
+ {
+ fprintf_indent (f, indent,
+ "if (type != res_op->type\n");
+ fprintf_indent (f, indent,
+ " && !useless_type_conversion_p (type, res_op->type))\n");
+ fprintf_indent (f, indent,
+ " {\n");
+ indent += 4;
+ fprintf_indent (f, indent,
+ "if (!(res_op->ops[0] = maybe_push_res_to_seq (res_op, %s))) goto %s;\n",
+ !as_a <expr *> (e->ops[0])->force_leaf
+ ? "lseq" : "NULL", fail_label);
+ needs_label = true;
+ fprintf_indent (f, indent,
+ "res_op->set_op (%s, type, 1);\n",
+ *opr == CONVERT_EXPR ? "NOP_EXPR" : opr->id);
+ fprintf_indent (f, indent,
+ "res_op->resimplify (%s, valueize);\n",
+ !e->force_leaf ? "lseq" : "NULL");
+ indent -= 4;
+ fprintf_indent (f, indent,
+ " }\n");
+ }
+ else
+ fprintf_indent (f, indent,
+ "res_op->resimplify (%s, valueize);\n",
+ !e->force_leaf ? "lseq" : "NULL");
if (e->force_leaf)
{
fprintf_indent (f, indent,