On Thu, 16 Jul 2026, Tamar Christina wrote:
> At the moment the match.pd machine machinery can only be used globally.
>
> That is we cannot use it's flexibility to perform rewrites that only happen
> at specific passes.
>
> This changes by teaching genmatch about "namespaces" so that we can generate
> the matching code in differently named functions and then modifies
> gimple_simplify to support changing to other namespaces.
>
> For this to work the resolver code is moved into match.pd in
> decision_tree::gen
> so that that code doesn't have to be repeated for every namespace.
>
> I have two use cases for this.
>
> 1. generic isel where my early break patch series will introduce matches
> related to masked vector comparisons
> 2. aarch64 specific isel, where we have some code that can be simplified a lot
> using match.pd and be better maintainable.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
>
> Ok for master?
>
> Thanks,
> Tamar
>
> gcc/ChangeLog:
>
> * genmatch.cc (struct _ns_info): New.
> (write_header_declarations, define_dump_logs,
> capture_info::walk_c_expr, expr::gen_transform,
> dt_node::gen_kids, dt_node::gen_kids_1, dt_operand::gen,
> dt_operand::gen_phi_on_cond, emit_logging_call,
> dt_simplify::gen_1, dt_simplify::gen, write_predicate, usage): Use it.
> (decision_tree::gen): Use namespaced and wire resolver.
> (main): Iniitalize the namespaces.
> * gimple-match-exports.cc (gimple_simplify, gimple_resimplify1,
> gimple_resimplify2, gimple_resimplify3, gimple_resimplify4,
> gimple_resimplify5, gimple_resimplify6, gimple_resimplify7
> ,gimple_match_op::resimplify, maybe_resimplify_conditional_op,
> try_conditional_simplification): Take additional gimplifier function
> pointer for nested calls.
> * gimple-match.h (class gimple_match_op): Likewise.
> (gimple_simplify): New.
> (gimple_match_op::gimple_match_op): Support new gimplifiers.
> (gimple_match_op::set_simplifier): New.
> * gimple-fold.h (gimple_simplify): New.
> * tree-ssa-sccvn.cc (process_bb): Pass default gimplifier.
> * tree-vect-patterns.cc: Fix include orders.
>
> ---
> diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
> index
> 920cf27877d3bf69c8ffcbb3497d9d0b54f662c7..aff36596b3a1bf2d8571c853ec42a43df9520334
> 100644
> --- a/gcc/genmatch.cc
> +++ b/gcc/genmatch.cc
> @@ -56,6 +56,16 @@ ggc_free (void *)
>
> /* Global state. */
>
> +/* Structure containing namespace information for printing. */
> +typedef struct _ns_info
> +{
> + char *l; /* Lowercase version of the namespace. */
> + char *u; /* Uppercase version of the namespace. */
> +} ns_info;
This is C++, no need for a typedef?
> +
> +/* Namespace space information for code generation. */
> +ns_info ns;
It should be a singleton, so possibly
struct {
...
} ns;
works as well?
> +
> /* Verboseness. 0 is quiet, 1 adds some warnings, 2 is for debugging. */
> unsigned verbose;
>
> @@ -880,9 +890,9 @@ static vec<int> dbg_line_numbers;
> static void
> write_header_declarations (bool gimple, FILE *f)
> {
> - fprintf (f, "\nextern void\n%s_dump_logs (const char *file1, int line1_id,
> "
> + fprintf (f, "\nextern void\n%s%s_dump_logs (const char *file1, int
> line1_id, "
> "const char *file2, int line2, bool simplify);\n",
> - gimple ? "gimple" : "generic");
> + gimple ? "gimple" : "generic", ns.l);
> }
>
> static void
> @@ -891,9 +901,9 @@ define_dump_logs (bool gimple, FILE *f)
> if (dbg_line_numbers.is_empty ())
> return;
>
> - fprintf (f , "void\n%s_dump_logs (const char *file1, int line1_id, "
> + fprintf (f , "void\n%s%s_dump_logs (const char *file1, int line1_id, "
> "const char *file2, int line2, bool simplify)\n{\n",
> - gimple ? "gimple" : "generic");
> + gimple ? "gimple" : "generic", ns.l);
>
> fprintf_indent (f, 2, "static int dbg_line_numbers[%d] = {",
> dbg_line_numbers.length ());
> @@ -3329,6 +3339,8 @@ expr::gen_transform (FILE *f, int indent, const char
> *dest, bool gimple,
> fprintf_indent (f, indent,
> "gimple_match_op tem_op (res_op->cond.any_else (), "
> "ERROR_MARK, error_mark_node, 1);\n");
> + fprintf_indent (f, indent,
> + "tem_op.set_simplifier (gimple%s_simplify);\n", ns.l);
For code-size and compile-time can we elide this for the
"default" namespace and have it default initialized? This would also ...
> }
> else
> fprintf_indent (f, indent,
> @@ -3425,6 +3437,8 @@ expr::gen_transform (FILE *f, int indent, const char
> *dest, bool gimple,
> for (unsigned i = 0; i < ops.length (); ++i)
> fprintf (f, ", _o%d[%u]", depth, i);
> fprintf (f, ");\n");
> + fprintf_indent (f, indent, "tem_op.set_simplifier "
> + "(gimple%s_simplify);\n", ns.l);
> fprintf_indent (f, indent, "tem_op.resimplify (%s, valueize);\n",
> !force_leaf ? "lseq" : "NULL");
> fprintf_indent (f, indent,
> @@ -4299,7 +4313,7 @@ emit_logging_call (FILE *f, int indent, class simplify
> *s, operand *result,
> bool gimple)
> {
> fprintf_indent (f, indent, "if (UNLIKELY (debug_dump)) "
> - "%s_dump_logs (", gimple ? "gimple" : "generic");
> + "%s%s_dump_logs (", gimple ? "gimple" : "generic", ns.l);
> output_line_directive (f,
> result ? result->location : s->match->location,
> true, true, true);
> @@ -4893,8 +4907,8 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
> FILE *f = choose_output (files);
>
> /* Generate a split out function with the leaf transform code. */
> - s->fname = xasprintf ("%s_simplify_%u", gimple ? "gimple" : "generic",
> - fcnt++);
> + s->fname = xasprintf ("%s%s_simplify_%u", gimple ? "gimple" :
> "generic",
> + ns.l, fcnt++);
> if (gimple)
> fp_decl (f, "\nbool\n"
> "%s (gimple_match_op *res_op, gimple_seq *seq,\n"
> @@ -4961,18 +4975,18 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
>
> if (gimple)
> fp_decl (f, "\nbool\n"
> - "gimple_simplify_%s (gimple_match_op *res_op,"
> + "gimple%s_simplify_%s (gimple_match_op *res_op,"
> " gimple_seq *seq,\n"
> " tree (*valueize)(tree) "
> "ATTRIBUTE_UNUSED,\n"
> " code_helper ARG_UNUSED (code), tree "
> "ARG_UNUSED (type)",
> - e->operation->id);
> + ns.l, e->operation->id);
> else
> fp_decl (f, "\ntree\n"
> - "generic_simplify_%s (location_t ARG_UNUSED (loc), enum "
> + "generic%s_simplify_%s (location_t ARG_UNUSED (loc), enum "
> "tree_code ARG_UNUSED (code), const tree ARG_UNUSED
> (type)",
> - e->operation->id);
> + ns.l, e->operation->id);
> for (unsigned i = 0; i < n; ++i)
> fp_decl (f, ", tree _p%d", i);
> fp_decl_done (f, ")");
> @@ -4998,13 +5012,13 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
>
> if (gimple)
> fp_decl (f, "\nbool\n"
> - "gimple_simplify (gimple_match_op*, gimple_seq*,\n"
> + "gimple%s_simplify (gimple_match_op*, gimple_seq*,\n"
> " tree (*)(tree), code_helper,\n"
> - " const tree");
> + " const tree", ns.l);
> else
> fp_decl (f, "\ntree\n"
> - "generic_simplify (location_t, enum tree_code,\n"
> - " const tree");
> + "generic%s_simplify (location_t, enum tree_code,\n"
> + " const tree", ns.l);
> for (unsigned i = 0; i < n; ++i)
> fp_decl (f, ", tree");
> fp_decl_done (f, ")");
> @@ -5025,13 +5039,13 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
> tail-calls to the split-out functions. */
> if (gimple)
> fp_decl (f, "\nbool\n"
> - "gimple_simplify (gimple_match_op *res_op, gimple_seq *seq,\n"
> + "gimple%s_simplify (gimple_match_op *res_op, gimple_seq
> *seq,\n"
> " tree (*valueize)(tree) ATTRIBUTE_UNUSED,\n"
> - " code_helper code, const tree type");
> + " code_helper code, const tree type", ns.l);
> else
> fp_decl (f, "\ntree\n"
> - "generic_simplify (location_t loc, enum tree_code code, "
> - "const tree type ATTRIBUTE_UNUSED");
> + "generic%s_simplify (location_t loc, enum tree_code code, "
> + "const tree type ATTRIBUTE_UNUSED", ns.l);
> for (unsigned i = 0; i < n; ++i)
> fp_decl (f, ", tree _p%d", i);
> fp_decl_done (f, ")");
> @@ -5064,11 +5078,11 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
> is_a <fn_id *> (e->operation) ? "-" : "",
> e->operation->id);
> if (gimple)
> - fprintf (f, " return gimple_simplify_%s (res_op, "
> - "seq, valueize, code, type", e->operation->id);
> + fprintf (f, " return gimple%s_simplify_%s (res_op, "
> + "seq, valueize, code, type", ns.l, e->operation->id);
> else
> - fprintf (f, " return generic_simplify_%s (loc, code, type",
> - e->operation->id);
> + fprintf (f, " return generic%s_simplify_%s (loc, code, type",
> + ns.l, e->operation->id);
> for (unsigned j = 0; j < n; ++j)
> fprintf (f, ", _p%d", j);
> fprintf (f, ");\n");
> @@ -5082,6 +5096,32 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
> fprintf (f, " return NULL_TREE;\n");
> fprintf (f, "}\n");
> }
> +
> + if (gimple)
> + {
> + FILE *f = choose_output (files);
> + fp_decl (f, "\nbool\n"
> + "gimple%s_simplify (gimple_match_op *res_op, gimple_seq *seq,\n"
> + " tree (*valueize)(tree))", ns.l);
> + fp_decl_done (f, "");
> + fprintf (f, "{\n");
> + fprintf_indent (f, 2, "switch (res_op->num_ops)\n");
> + fprintf_indent (f, 4, "{\n");
> + for (unsigned n = 1; n <= 7; ++n)
> + {
> + fprintf_indent (f, 4, "case %u:\n", n);
> + fprintf_indent (f, 6, "return gimple%s_simplify (res_op, seq, "
> + "valueize,\n", ns.l);
> + fprintf_indent (f, 16, "res_op->code, res_op->type");
> + for (unsigned i = 0; i < n; ++i)
> + fprintf (f, ", res_op->ops[%u]", i);
> + fprintf (f, ");\n");
> + }
> + fprintf_indent (f, 4, "default:\n");
> + fprintf_indent (f, 6, "gcc_unreachable ();\n");
> + fprintf_indent (f, 4, "}\n");
> + fprintf (f, "}\n");
> + }
> }
>
> /* Output code to implement the predicate P from the decision tree DT. */
> @@ -5089,8 +5129,8 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
> void
> write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
> {
> - fp_decl (f, "\nbool\n%s%s (tree t%s%s)",
> - gimple ? "gimple_" : "tree_", p->id,
> + fp_decl (f, "\nbool\n%s%s%s (tree t%s%s)",
> + gimple ? "gimple_" : "tree_", ns.l, p->id,
> p->nargs > 0 ? ", tree *res_ops" : "",
> gimple ? ", tree (*valueize)(tree) ATTRIBUTE_UNUSED" : "");
> fp_decl_done (f, "");
> @@ -6271,7 +6311,8 @@ usage ()
> {
> const char *usage = "Usage:\n"
> " %s [--gimple|--generic] [-v[v]] <input>\n"
> - " %s [options] [--include=FILE] --header=FILE <input> <output>...\n";
> + " %s [options] [--include=FILE] [--namespace=NAME] --header=FILE"
> + " <input> <output>...\n";
> fprintf (stderr, usage, progname, progname);
> }
>
> @@ -6300,6 +6341,7 @@ main (int argc, char **argv)
> bool gimple = true;
> char *s_header_file = NULL;
> char *s_include_file = NULL;
> + char *s_namespace = NULL;
> auto_vec <char *> files;
> char *input = NULL;
> int last_file = argc - 1;
> @@ -6313,6 +6355,8 @@ main (int argc, char **argv)
> s_header_file = &argv[i][9];
> else if (strncmp (argv[i], "--include=", 10) == 0)
> s_include_file = &argv[i][10];
> + else if (strncmp (argv[i], "--namespace=", 12) == 0)
> + s_namespace = &argv[i][12];
> else if (strcmp (argv[i], "-v") == 0)
> verbose = 1;
> else if (strcmp (argv[i], "-vv") == 0)
> @@ -6333,6 +6377,36 @@ main (int argc, char **argv)
> return 1;
> }
>
> + /* Initialize priting information. */
> + if (s_namespace)
> + {
> + if (!gimple)
> + {
> + fatal_at ((location_t)0, "%<--namespace%> not supported for GENERIC");
> + return 1;
> + }
> +
> + int len = strlen (s_namespace) + 1;
> + ns.l = XNEWVEC (char, len + 1);
> + ns.u = XNEWVEC (char, len + 1);
> + ns.l[0] = '_';
> + ns.u[0] = '_';
> + for (int i = 0; i < len; i++)
> + {
> + ns.l[i+1] = TOLOWER (s_namespace[i]);
> + ns.u[i+1] = TOUPPER (s_namespace[i]);
> + }
> + ns.l[len] = '\0';
> + ns.u[len] = '\0';
> + }
> + else
> + {
> + ns.l = XNEW (char);
> + ns.u = XNEW (char);
> + ns.l[0] = '\0';
> + ns.u[0] = '\0';
> + }
> +
> genmatch_diag_selftests ();
>
> if (!s_include_file)
> @@ -6406,8 +6480,9 @@ main (int argc, char **argv)
> }
>
> header_file = fopen (s_header_file, "w");
> - fprintf (header_file, "#ifndef GCC_GIMPLE_MATCH_AUTO_H\n"
> - "#define GCC_GIMPLE_MATCH_AUTO_H\n");
> + fprintf (header_file, "#ifndef GCC_GIMPLE_MATCH%s_AUTO_H\n"
> + "#define GCC_GIMPLE_MATCH%s_AUTO_H\n",
> + ns.u, ns.u);
> write_header_includes (gimple, header_file);
> write_header_declarations (gimple, header_file);
> }
> @@ -6462,7 +6537,8 @@ main (int argc, char **argv)
>
> if (header_file)
> {
> - fprintf (header_file, "\n#endif /* GCC_GIMPLE_MATCH_AUTO_H. */\n");
> + fprintf (header_file, "\n#endif /* GCC_GIMPLE_MATCH%s_AUTO_H. */\n",
> + ns.u);
> fclose (header_file);
> }
>
> @@ -6471,6 +6547,8 @@ main (int argc, char **argv)
> cpp_destroy (r);
>
> delete operators;
> + XDELETE (ns.l);
> + XDELETE (ns.u);
>
> return 0;
> }
> diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
> index
> 4422a48383d5ce221deacf44c491130130a47d6c..d1da1f00f0fed7765c8785158a915cb9bb3c88c0
> 100644
> --- a/gcc/gimple-fold.cc
> +++ b/gcc/gimple-fold.cc
> @@ -6937,6 +6937,7 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace,
> tree (*valueize) (tree),
> {
> gimple_seq seq = NULL;
> gimple_match_op res_op;
> + res_op.set_simplifier (gimple_simplify);
... avoid most of these changes.
> if (gimple_simplify (stmt, &res_op, inplace ? NULL : &seq,
> valueize, valueize)
> && replace_stmt_with_simplification (gsi, &res_op, &seq, inplace,
> @@ -9586,6 +9587,7 @@ gimple_fold_stmt_to_constant_1 (gimple *stmt, tree
> (*valueize) (tree),
> tree (*gvalueize) (tree))
> {
> gimple_match_op res_op;
> + res_op.set_simplifier (gimple_simplify);
> /* ??? The SSA propagators do not correctly deal with following SSA
> use-def
> edges if there are intermediate VARYING defs. For this reason
> do not follow SSA edges here even though SCCVN can technically
> @@ -11092,7 +11094,8 @@ gimple_build (gimple_stmt_iterator *gsi,
> gimple_seq seq = NULL;
> tree res
> = gimple_simplify (code, type, op0, &seq,
> - gsi->bb ? follow_all_ssa_edges : gimple_build_valueize);
> + gsi->bb ? follow_all_ssa_edges : gimple_build_valueize,
> + gimple_simplify);
> if (!res)
> {
> res = make_ssa_name (type);
> @@ -11124,7 +11127,8 @@ gimple_build (gimple_stmt_iterator *gsi,
> gimple_seq seq = NULL;
> tree res
> = gimple_simplify (code, type, op0, op1, &seq,
> - gsi->bb ? follow_all_ssa_edges : gimple_build_valueize);
> + gsi->bb ? follow_all_ssa_edges : gimple_build_valueize,
> + gimple_simplify);
And these?
> if (!res)
> {
> res = make_ssa_name (type);
> @@ -11151,7 +11155,8 @@ gimple_build (gimple_stmt_iterator *gsi,
> gimple_seq seq = NULL;
> tree res
> = gimple_simplify (code, type, op0, op1, op2, &seq,
> - gsi->bb ? follow_all_ssa_edges : gimple_build_valueize);
> + gsi->bb ? follow_all_ssa_edges : gimple_build_valueize,
> + gimple_simplify);
> if (!res)
> {
> res = make_ssa_name (type);
> @@ -11212,7 +11217,8 @@ gimple_build (gimple_stmt_iterator *gsi,
> tree type, tree arg0)
> {
> gimple_seq seq = NULL;
> - tree res = gimple_simplify (fn, type, arg0, &seq, gimple_build_valueize);
> + tree res = gimple_simplify (fn, type, arg0, &seq, gimple_build_valueize,
> + gimple_simplify);
> if (!res)
> {
> gcall *stmt;
> @@ -11249,7 +11255,7 @@ gimple_build (gimple_stmt_iterator *gsi,
> {
> gimple_seq seq = NULL;
> tree res = gimple_simplify (fn, type, arg0, arg1, &seq,
> - gimple_build_valueize);
> + gimple_build_valueize, gimple_simplify);
> if (!res)
> {
> gcall *stmt;
> @@ -11286,7 +11292,7 @@ gimple_build (gimple_stmt_iterator *gsi,
> {
> gimple_seq seq = NULL;
> tree res = gimple_simplify (fn, type, arg0, arg1, arg2,
> - &seq, gimple_build_valueize);
> + &seq, gimple_build_valueize, gimple_simplify);
> if (!res)
> {
> gcall *stmt;
> diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
> index
> f18535607791ea33255e475a9582fd6d797251dd..ca7519c4c8904127ad5a80e1d39101550b397d91
> 100644
> --- a/gcc/gimple-fold.h
> +++ b/gcc/gimple-fold.h
> @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
> #define GCC_GIMPLE_FOLD_H
>
> #include "tree-pass.h"
> +#include "gimple-match.h"
>
> extern tree canonicalize_constructor_val (tree, tree);
> extern tree get_symbol_constant_value (tree);
> @@ -270,17 +271,23 @@ extern void mark_lhs_in_seq_for_dce (bitmap,
> gimple_seq);
>
> /* In gimple-match.cc. */
> extern tree gimple_simplify (enum tree_code, tree, tree,
> - gimple_seq *, tree (*)(tree));
> + gimple_seq *, tree (*)(tree),
> + gimple_match_simplify_fn);
> extern tree gimple_simplify (enum tree_code, tree, tree, tree,
> - gimple_seq *, tree (*)(tree));
> + gimple_seq *, tree (*)(tree),
> + gimple_match_simplify_fn);
> extern tree gimple_simplify (enum tree_code, tree, tree, tree, tree,
> - gimple_seq *, tree (*)(tree));
> + gimple_seq *, tree (*)(tree),
> + gimple_match_simplify_fn);
> extern tree gimple_simplify (combined_fn, tree, tree,
> - gimple_seq *, tree (*)(tree));
> + gimple_seq *, tree (*)(tree),
> + gimple_match_simplify_fn);
> extern tree gimple_simplify (combined_fn, tree, tree, tree,
> - gimple_seq *, tree (*)(tree));
> + gimple_seq *, tree (*)(tree),
> + gimple_match_simplify_fn);
> extern tree gimple_simplify (combined_fn, tree, tree, tree, tree,
> - gimple_seq *, tree (*)(tree));
> + gimple_seq *, tree (*)(tree),
> + gimple_match_simplify_fn);
>
> /* Returns true if we are doing the fold before expansion to rtl. */
> inline bool
> diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
> index
> 74f2c5f19bcfdf2e40435119ac757658a110e471..0faaa4c4f036a300bc018c2fac306fb939eb7378
> 100644
> --- a/gcc/gimple-match-exports.cc
> +++ b/gcc/gimple-match-exports.cc
> @@ -66,22 +66,23 @@ extern bool gimple_simplify (gimple_match_op *,
> gimple_seq *, tree (*)(tree),
> extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
> code_helper, tree, tree, tree, tree, tree, tree,
> tree, tree);
> +extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree
> (*)(tree));
>
> /* Functions that are needed by gimple-match but that are exported and used
> in
> other places in the compiler. */
>
> tree gimple_simplify (enum tree_code, tree, tree, gimple_seq *,
> - tree (*)(tree));
> + tree (*)(tree), gimple_match_simplify_fn);
> tree gimple_simplify (enum tree_code, tree, tree, tree, gimple_seq *,
> - tree (*)(tree));
> + tree (*)(tree), gimple_match_simplify_fn);
> tree gimple_simplify (enum tree_code, tree, tree, tree, tree, gimple_seq *,
> - tree (*)(tree));
> + tree (*)(tree), gimple_match_simplify_fn);
> tree gimple_simplify (combined_fn, tree, tree, gimple_seq *,
> - tree (*)(tree));
> + tree (*)(tree), gimple_match_simplify_fn);
> tree gimple_simplify (combined_fn, tree, tree, tree, gimple_seq *,
> - tree (*)(tree));
> + tree (*)(tree), gimple_match_simplify_fn);
> tree gimple_simplify (combined_fn, tree, tree, tree, tree, gimple_seq *,
> - tree (*)(tree));
> + tree (*)(tree), gimple_match_simplify_fn);
>
> tree do_valueize (tree, tree (*)(tree), bool &);
> tree do_valueize (tree (*)(tree), tree);
> @@ -349,6 +350,7 @@ maybe_resimplify_conditional_op (gimple_seq *seq,
> gimple_match_op *res_op,
> create a (VEC_)COND_EXPR between them, then see if it can be further
> simplified. */
> gimple_match_op new_op;
> + new_op.set_simplifier (res_op->m_simplifier);
> if (res_op->cond.else_value
> && gimple_simplified_result_is_gimple_val (res_op))
> {
> @@ -426,6 +428,7 @@ try_conditional_simplification (internal_fn ifn,
> gimple_match_op *res_op,
> gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
> else_value, len, bias),
> op, res_op->type, num_ops - num_cond_ops);
> + cond_op.set_simplifier (res_op->m_simplifier);
>
> memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
> switch (num_ops - num_cond_ops)
> @@ -586,7 +589,8 @@ maybe_push_res_to_seq (gimple_match_op *res_op,
> gimple_seq *seq, tree res)
> tree
> gimple_simplify (enum tree_code code, tree type,
> tree op0,
> - gimple_seq *seq, tree (*valueize)(tree))
> + gimple_seq *seq, tree (*valueize)(tree),
> + gimple_match_simplify_fn simplifier)
> {
> if (constant_for_folding (op0))
> {
> @@ -597,6 +601,7 @@ gimple_simplify (enum tree_code code, tree type,
> }
>
> gimple_match_op res_op;
> + res_op.set_simplifier (simplifier);
> if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
> return NULL_TREE;
> return maybe_push_res_to_seq (&res_op, seq);
> @@ -607,7 +612,8 @@ gimple_simplify (enum tree_code code, tree type,
> tree
> gimple_simplify (enum tree_code code, tree type,
> tree op0, tree op1,
> - gimple_seq *seq, tree (*valueize)(tree))
> + gimple_seq *seq, tree (*valueize)(tree),
> + gimple_match_simplify_fn simplifier)
> {
> if (constant_for_folding (op0) && constant_for_folding (op1))
> {
> @@ -629,6 +635,7 @@ gimple_simplify (enum tree_code code, tree type,
> }
>
> gimple_match_op res_op;
> + res_op.set_simplifier (simplifier);
> if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
> return NULL_TREE;
> return maybe_push_res_to_seq (&res_op, seq);
> @@ -639,7 +646,8 @@ gimple_simplify (enum tree_code code, tree type,
> tree
> gimple_simplify (enum tree_code code, tree type,
> tree op0, tree op1, tree op2,
> - gimple_seq *seq, tree (*valueize)(tree))
> + gimple_seq *seq, tree (*valueize)(tree),
> + gimple_match_simplify_fn simplifier)
> {
> if (constant_for_folding (op0) && constant_for_folding (op1)
> && constant_for_folding (op2))
> @@ -657,6 +665,7 @@ gimple_simplify (enum tree_code code, tree type,
> std::swap (op0, op1);
>
> gimple_match_op res_op;
> + res_op.set_simplifier (simplifier);
Convenience for typing probably also asks for extra gimple_match_op
CTORs with the simplifier specified?
> if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
> return NULL_TREE;
> return maybe_push_res_to_seq (&res_op, seq);
> @@ -667,7 +676,8 @@ gimple_simplify (enum tree_code code, tree type,
> tree
> gimple_simplify (combined_fn fn, tree type,
> tree arg0,
> - gimple_seq *seq, tree (*valueize)(tree))
> + gimple_seq *seq, tree (*valueize)(tree),
> + gimple_match_simplify_fn simplifier)
> {
> if (constant_for_folding (arg0))
> {
> @@ -677,6 +687,7 @@ gimple_simplify (combined_fn fn, tree type,
> }
>
> gimple_match_op res_op;
> + res_op.set_simplifier (simplifier);
> if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
> return NULL_TREE;
> return maybe_push_res_to_seq (&res_op, seq);
> @@ -687,7 +698,8 @@ gimple_simplify (combined_fn fn, tree type,
> tree
> gimple_simplify (combined_fn fn, tree type,
> tree arg0, tree arg1,
> - gimple_seq *seq, tree (*valueize)(tree))
> + gimple_seq *seq, tree (*valueize)(tree),
> + gimple_match_simplify_fn simplifier)
> {
> if (constant_for_folding (arg0)
> && constant_for_folding (arg1))
> @@ -698,6 +710,7 @@ gimple_simplify (combined_fn fn, tree type,
> }
>
> gimple_match_op res_op;
> + res_op.set_simplifier (simplifier);
> if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
> return NULL_TREE;
> return maybe_push_res_to_seq (&res_op, seq);
> @@ -708,7 +721,8 @@ gimple_simplify (combined_fn fn, tree type,
> tree
> gimple_simplify (combined_fn fn, tree type,
> tree arg0, tree arg1, tree arg2,
> - gimple_seq *seq, tree (*valueize)(tree))
> + gimple_seq *seq, tree (*valueize)(tree),
> + gimple_match_simplify_fn simplifier)
> {
> if (constant_for_folding (arg0)
> && constant_for_folding (arg1)
> @@ -720,6 +734,7 @@ gimple_simplify (combined_fn fn, tree type,
> }
>
> gimple_match_op res_op;
> + res_op.set_simplifier (simplifier);
> if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
> return NULL_TREE;
> return maybe_push_res_to_seq (&res_op, seq);
> @@ -949,8 +964,8 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op
> *res_op,
>
> ++depth;
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type, res_op->ops[0]))
> + res_op2.set_simplifier (res_op->m_simplifier);
Like I'd have expected the copy CTOR to also copy the simplifier?
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> --depth;
> *res_op = res_op2;
> @@ -1026,9 +1041,8 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op
> *res_op,
>
> ++depth;
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type,
> - res_op->ops[0], res_op->ops[1]))
> + res_op2.set_simplifier (res_op->m_simplifier);
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> --depth;
> *res_op = res_op2;
> @@ -1102,9 +1116,8 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op
> *res_op,
>
> ++depth;
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type,
> - res_op->ops[0], res_op->ops[1], res_op->ops[2]))
> + res_op2.set_simplifier (res_op->m_simplifier);
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> --depth;
> *res_op = res_op2;
> @@ -1152,10 +1165,8 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op
> *res_op,
>
> ++depth;
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type,
> - res_op->ops[0], res_op->ops[1], res_op->ops[2],
> - res_op->ops[3]))
> + res_op2.set_simplifier (res_op->m_simplifier);
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> --depth;
> *res_op = res_op2;
> @@ -1192,10 +1203,8 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op
> *res_op,
> }
>
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type,
> - res_op->ops[0], res_op->ops[1], res_op->ops[2],
> - res_op->ops[3], res_op->ops[4]))
> + res_op2.set_simplifier (res_op->m_simplifier);
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> *res_op = res_op2;
> return true;
> @@ -1230,10 +1239,8 @@ gimple_resimplify6 (gimple_seq *seq, gimple_match_op
> *res_op,
> }
>
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type,
> - res_op->ops[0], res_op->ops[1], res_op->ops[2],
> - res_op->ops[3], res_op->ops[4], res_op->ops[5]))
> + res_op2.set_simplifier (res_op->m_simplifier);
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> *res_op = res_op2;
> return true;
> @@ -1268,11 +1275,8 @@ gimple_resimplify7 (gimple_seq *seq, gimple_match_op
> *res_op,
> }
>
> gimple_match_op res_op2 (*res_op);
> - if (gimple_simplify (&res_op2, seq, valueize,
> - res_op->code, res_op->type,
> - res_op->ops[0], res_op->ops[1], res_op->ops[2],
> - res_op->ops[3], res_op->ops[4], res_op->ops[5],
> - res_op->ops[6]))
> + res_op2.set_simplifier (res_op->m_simplifier);
> + if (res_op->m_simplifier (&res_op2, seq, valueize))
> {
> *res_op = res_op2;
> return true;
> diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h
> index
> 8ff58e8cd7f27a1adc2fabf0f76ee940dea09199..39bd70b33af2ca44991079b6baf2f3aa524c84cd
> 100644
> --- a/gcc/gimple-match.h
> +++ b/gcc/gimple-match.h
> @@ -23,6 +23,14 @@ along with GCC; see the file COPYING3. If not see
> #define GCC_GIMPLE_MATCH_H
>
>
> +class gimple_match_op;
> +
> +/* Dispatch to the entry points provided by a generated GIMPLE match file.
> */
> +typedef bool (*gimple_match_simplify_fn) (gimple_match_op *, gimple_seq *,
> + tree (*) (tree));
> +/* Default implementation for match.pd. */
> +extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree
> (*)(tree));
> +
> /* Represents the condition under which an operation should happen,
> and the value to use otherwise. The condition applies elementwise
> (as for VEC_COND_EXPR) if the values are vectors. */
> @@ -108,6 +116,7 @@ public:
> void set_op (code_helper, tree, tree, tree, tree, tree, tree);
> void set_op (code_helper, tree, tree, tree, tree, tree, tree, tree);
> void set_op (code_helper, tree, tree, tree, tree, tree, tree, tree, tree);
> + void set_simplifier (gimple_match_simplify_fn);
> void set_value (tree);
>
> tree op_or_null (unsigned int) const;
> @@ -134,6 +143,9 @@ public:
> /* The number of operands to CODE. */
> unsigned int num_ops;
>
> + /* The simplifier to use when regimplifying statements. */
> + gimple_match_simplify_fn m_simplifier = NULL;
> +
why NSMDI here?
> /* The operands to CODE. Only the first NUM_OPS entries are meaningful.
> */
> tree ops[MAX_NUM_OPS];
>
> @@ -143,7 +155,7 @@ public:
> inline
> gimple_match_op::gimple_match_op ()
> : cond (gimple_match_cond::UNCOND), type (NULL_TREE), reverse (false),
> - num_ops (0)
> + num_ops (0), m_simplifier (gimple_simplify)
> {
> }
>
> @@ -155,7 +167,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> code_helper code_in, tree type_in,
> unsigned int num_ops_in)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (num_ops_in)
> + num_ops (num_ops_in), m_simplifier (gimple_simplify)
> {
> }
>
> @@ -166,7 +178,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> code_helper code_in, tree type_in,
> tree op0)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (1)
> + num_ops (1), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> }
> @@ -176,7 +188,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> code_helper code_in, tree type_in,
> tree op0, tree op1)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (2)
> + num_ops (2), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> ops[1] = op1;
> @@ -187,7 +199,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> code_helper code_in, tree type_in,
> tree op0, tree op1, tree op2)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (3)
> + num_ops (3), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> ops[1] = op1;
> @@ -199,7 +211,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> code_helper code_in, tree type_in,
> tree op0, tree op1, tree op2, tree op3)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (4)
> + num_ops (4), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> ops[1] = op1;
> @@ -213,7 +225,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> tree op0, tree op1, tree op2, tree op3,
> tree op4)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (5)
> + num_ops (5), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> ops[1] = op1;
> @@ -228,7 +240,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> tree op0, tree op1, tree op2, tree op3,
> tree op4, tree op5)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (6)
> + num_ops (6), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> ops[1] = op1;
> @@ -244,7 +256,7 @@ gimple_match_op::gimple_match_op (const gimple_match_cond
> &cond_in,
> tree op0, tree op1, tree op2, tree op3,
> tree op4, tree op5, tree op6)
> : cond (cond_in), code (code_in), type (type_in), reverse (false),
> - num_ops (7)
> + num_ops (7), m_simplifier (gimple_simplify)
> {
> ops[0] = op0;
> ops[1] = op1;
> @@ -375,6 +387,14 @@ gimple_match_op::set_op (code_helper code_in, tree
> type_in,
> ops[6] = op6;
> }
>
> +/* Set SIMPLIFIER to use when regimplifying statements. */
> +
> +inline void
> +gimple_match_op::set_simplifier (gimple_match_simplify_fn simplifier)
> +{
> + m_simplifier = simplifier;
> +}
> +
> /* Set the "operation" to be the single value VALUE, such as a constant
> or SSA_NAME. */
>
> diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
> index
> a95350abccbf4725c8798b3d34e08e0a0e6b5527..45676560693a1d687b6fb05b76c9f2b16eb8c80a
> 100644
> --- a/gcc/tree-ssa-sccvn.cc
> +++ b/gcc/tree-ssa-sccvn.cc
> @@ -79,6 +79,7 @@ along with GCC; see the file COPYING3. If not see
> #include "ipa-cp.h"
> #include "ipa-prop.h"
> #include "target.h"
> +#include "gimple-match.h"
>
> /* This algorithm is based on the SCC algorithm presented by Keith
> Cooper and L. Taylor Simpson in "SCC-Based Value numbering"
> @@ -8532,7 +8533,7 @@ process_bb (rpo_elim &avail, basic_block bb,
> }
> tree val = gimple_simplify (cmpcode,
> boolean_type_node, lhs, rhs,
> - NULL, vn_valueize);
> + NULL, vn_valueize, gimple_simplify);
> /* If the condition didn't simplify see if we have recorded
> an expression from sofar taken edges. */
> if (! val || TREE_CODE (val) != INTEGER_CST)
> diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
> index
> e0fbe25216351c10b7c85b7a53d6cd87957b529e..ab0a5d9c176979f490aaa19008acf281fdaeafa2
> 100644
> --- a/gcc/tree-vect-patterns.cc
> +++ b/gcc/tree-vect-patterns.cc
> @@ -26,10 +26,10 @@ along with GCC; see the file COPYING3. If not see
> #include "tree.h"
> #include "gimple.h"
> #include "gimple-iterator.h"
> -#include "gimple-fold.h"
> #include "ssa.h"
> #include "expmed.h"
> #include "optabs-tree.h"
> +#include "gimple-fold.h"
> #include "insn-config.h"
> #include "recog.h" /* FIXME: for insn_data */
> #include "fold-const.h"
>
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)