On Fri, Jan 31, 2025 at 4:44 AM Richard Biener <rguent...@suse.de> wrote: > > The following improves genmatch generated code so we avoid more > spurious SSA assignments to be pushed to the GIMPLE sequence or > simplifications rejected when we're not supposed to produce any > for outer and intermediate conversions.
After this goes in, I will test removing the special casing in phiopt_early_allow which was designed to workaround the extra SSA assignment happening. Thanks, Andrew Pinski > > Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for stage1. > > Richard. > > * genmatch.cc (::gen_transform): Add in_place parameter. > Assert it isn't set in unexpected places. > (possible_noop_convert): New. > (expr::gen_transform): Support in_place and emit code to > compute a child in-place when the operation is a conversion. > (dt_simplify::gen_1): Arrange for an outermost conversion > to be elided by generating the transform of the operand > in-place. > * match.pd (__real cepxi (x) -> cos (x)): Use single_use. > --- > gcc/genmatch.cc | 201 +++++++++++++++++++++++++++++++++++++----------- > gcc/match.pd | 10 ++- > 2 files changed, 160 insertions(+), 51 deletions(-) > > diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc > index b9a792e2455..a81629c57b2 100644 > --- a/gcc/genmatch.cc > +++ b/gcc/genmatch.cc > @@ -1475,7 +1475,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 (); } > }; > > @@ -1528,8 +1528,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 > @@ -1562,8 +1562,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. */ > @@ -1583,8 +1583,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. */ > @@ -3186,6 +3186,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. */ > > @@ -3239,7 +3247,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 > @@ -3297,10 +3305,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) > @@ -3312,7 +3333,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; > @@ -3323,45 +3345,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); > @@ -3387,7 +3459,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; > @@ -3407,8 +3479,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); > > @@ -3491,8 +3565,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) > @@ -4343,7 +4420,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; > } > > @@ -4398,16 +4476,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, > diff --git a/gcc/match.pd b/gcc/match.pd > index 6991868fbe2..d452c62b322 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -5629,11 +5629,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > (part (convert?:s@2 (op:s @0 @1))) > (convert (op (part @0) (part @1)))))) > (simplify > - (realpart (convert?:s (CEXPI:s @0))) > - (convert (COS @0))) > + (realpart (convert?@2 (CEXPI@1 @0))) > + (if (single_use (@1) && single_use (@2)) > + (convert (COS @0)))) > (simplify > - (imagpart (convert?:s (CEXPI:s @0))) > - (convert (SIN @0))) > + (imagpart (convert?@2 (CEXPI@1 @0))) > + (if (single_use (@1) && single_use (@2)) > + (convert (SIN @0)))) > > /* conj(conj(x)) -> x */ > (simplify > -- > 2.43.0