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.

---
diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
index 
920cf27877d3bf69c8ffcbb3497d9d0b54f662c7..948199c6f0c2a10003919a9ca738bed5d29b1ee9
 100644
--- a/gcc/genmatch.cc
+++ b/gcc/genmatch.cc
@@ -56,6 +56,14 @@ 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;
+
+
 /* Verboseness.  0 is quiet, 1 adds some warnings, 2 is for debugging.  */
 unsigned verbose;
 
@@ -878,22 +886,25 @@ fp_decl_done (FILE *f, const char *trailer)
 static vec<int> dbg_line_numbers;
 
 static void
-write_header_declarations (bool gimple, FILE *f)
+write_header_declarations (bool gimple, ns_info &ns, 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);
+  if (gimple)
+    fprintf (f, "\n#define GIMPLE_MATCH_SIMPLIFIER gimple%s_simplify\n",
+            ns.l);
 }
 
 static void
-define_dump_logs (bool gimple, FILE *f)
+define_dump_logs (bool gimple, ns_info &ns, 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 ());
@@ -2448,10 +2459,10 @@ public:
                            unsigned pos);
   dt_node *append_simplify (simplify *, unsigned, dt_operand **);
 
-  virtual void gen (FILE *, int, bool, int) {}
+  virtual void gen (FILE *, int, ns_info &, bool, int) {}
 
-  void gen_kids (FILE *, int, bool, int);
-  void gen_kids_1 (FILE *, int, bool, int,
+  void gen_kids (FILE *, int, ns_info &, bool, int);
+  void gen_kids_1 (FILE *, int, ns_info &, bool, int,
                   const vec<dt_operand *> &, const vec<dt_operand *> &,
                   const vec<dt_operand *> &, const vec<dt_operand *> &,
                   const vec<dt_operand *> &, const vec<dt_node *> &);
@@ -2475,7 +2486,7 @@ public:
       : dt_node (type, parent_), op (op_), match_dop (match_dop_),
       pos (pos_), value_match (false), for_id (current_id) {}
 
-  void gen (FILE *, int, bool, int) final override;
+  void gen (FILE *, int, ns_info &, bool, int) final override;
   unsigned gen_predicate (FILE *, int, const char *, bool);
   unsigned gen_match_op (FILE *, int, const char *, bool);
 
@@ -2484,7 +2495,7 @@ public:
 
   char *get_name (char *);
   void gen_opname (char *, unsigned);
-  void gen_phi_on_cond (FILE *, int, int);
+  void gen_phi_on_cond (FILE *, int, int, ns_info &);
 };
 
 /* Leaf node of the decision tree, used for DT_SIMPLIFY.  */
@@ -2501,8 +2512,8 @@ public:
        : dt_node (DT_SIMPLIFY, NULL), s (s_), pattern_no (pattern_no_),
          indexes (indexes_), info (NULL)  {}
 
-  void gen_1 (FILE *, int, bool, operand *);
-  void gen (FILE *f, int, bool, int) final override;
+  void gen_1 (FILE *, int, ns_info &, bool, operand *);
+  void gen (FILE *f, int, ns_info &, bool, int) final override;
 };
 
 template<>
@@ -2533,7 +2544,7 @@ public:
   dt_node *root;
 
   void insert (class simplify *, unsigned);
-  void gen (vec <FILE *> &f, bool gimple);
+  void gen (vec <FILE *> &f, ns_info &ns, bool gimple);
   void print (FILE *f = stderr);
 
   decision_tree () { root = new dt_node (dt_node::DT_NODE, NULL); }
@@ -3180,7 +3191,6 @@ capture_info::walk_c_expr (c_expr *e)
     }
 }
 
-
 /* The current label failing the current matched pattern during
    code generation.  */
 static char *fail_label;
@@ -3377,7 +3387,8 @@ expr::gen_transform (FILE *f, int indent, const char 
*dest, bool gimple,
          fprintf_indent (f, indent,
                          "tem_op.ops[0] = _r%d;\n", depth);
          fprintf_indent (f, indent,
-                         "tem_op.resimplify (%s, valueize);\n",
+                         "tem_op.resimplify (%s, valueize, "
+                         "GIMPLE_MATCH_SIMPLIFIER);\n",
                          !force_leaf ? "lseq" : "NULL");
          indent -= 4;
          fprintf_indent (f, indent + 2, "}\n");
@@ -3397,7 +3408,8 @@ expr::gen_transform (FILE *f, int indent, const char 
*dest, bool gimple,
            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",
+                         "%s.resimplify (%s, valueize, "
+                         "GIMPLE_MATCH_SIMPLIFIER);\n",
                          in_place, !force_leaf ? "lseq" : "NULL");
          indent -= 2;
          fprintf_indent (f, indent, "}\n");
@@ -3425,7 +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.resimplify (%s, valueize);\n",
+         fprintf_indent (f, indent, "tem_op.resimplify (%s, valueize, "
+                         "GIMPLE_MATCH_SIMPLIFIER);\n",
                          !force_leaf ? "lseq" : "NULL");
          fprintf_indent (f, indent,
                          "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n",
@@ -3845,7 +3858,7 @@ fns_cmp (const void *p1, const void *p2)
 /* Generate matching code for the children of the decision tree node.  */
 
 void
-dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth)
+dt_node::gen_kids (FILE *f, int indent, ns_info &ns, bool gimple, int depth)
 {
   auto_vec<dt_operand *> gimple_exprs;
   auto_vec<dt_operand *> generic_exprs;
@@ -3917,10 +3930,10 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple, 
int depth)
             for what we have collected sofar.  */
          fns.qsort (fns_cmp);
          generic_fns.qsort (fns_cmp);
-         gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs,
+         gen_kids_1 (f, indent, ns, gimple, depth, gimple_exprs, generic_exprs,
                      fns, generic_fns, preds, others);
          /* And output the true operand itself.  */
-         kids[i]->gen (f, indent, gimple, depth);
+         kids[i]->gen (f, indent, ns, gimple, depth);
          gimple_exprs.truncate (0);
          generic_exprs.truncate (0);
          fns.truncate (0);
@@ -3935,14 +3948,14 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple, 
int depth)
   /* Generate code for the remains.  */
   fns.qsort (fns_cmp);
   generic_fns.qsort (fns_cmp);
-  gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs,
+  gen_kids_1 (f, indent, ns, gimple, depth, gimple_exprs, generic_exprs,
              fns, generic_fns, preds, others);
 }
 
 /* Generate matching code for the children of the decision tree node.  */
 
 void
-dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
+dt_node::gen_kids_1 (FILE *f, int indent, ns_info &ns, bool gimple, int depth,
                     const vec<dt_operand *> &gimple_exprs,
                     const vec<dt_operand *> &generic_exprs,
                     const vec<dt_operand *> &fns,
@@ -4014,7 +4027,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
                    fprintf_indent (f, indent, "case %s:\n", op->id);
                }
              fprintf_indent (f, indent, "  {\n");
-             gimple_exprs[i]->gen (f, indent + 4, true, depth);
+             gimple_exprs[i]->gen (f, indent + 4, ns, true, depth);
              fprintf_indent (f, indent, "    break;\n");
              fprintf_indent (f, indent, "  }\n");
            }
@@ -4035,7 +4048,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
                {
                  expr *e = as_a <expr *> (gimple_exprs[i]->op);
                  if (*e->operation == COND_EXPR && e->match_phi)
-                   gimple_exprs[i]->gen_phi_on_cond (f, indent, depth);
+                   gimple_exprs[i]->gen_phi_on_cond (f, indent, depth, ns);
                }
 
              indent -= 2;
@@ -4076,7 +4089,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
                              "  if (gimple_call_num_args (_c%d) == %d)\n",
                              depth, e->ops.length ());
              fprintf_indent (f, indent, "    {\n");
-             fns[i]->gen (f, indent + 6, true, depth);
+             fns[i]->gen (f, indent + 6, ns, true, depth);
              fprintf_indent (f, indent, "    }\n");
            }
 
@@ -4098,7 +4111,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
          if (*op == SSA_NAME && (exprs_len || fns_len))
            {
              fprintf_indent (f, indent + 4, "{\n");
-             generic_exprs[i]->gen (f, indent + 6, gimple, depth);
+             generic_exprs[i]->gen (f, indent + 6, ns, gimple, depth);
              fprintf_indent (f, indent + 4, "}\n");
            }
        }
@@ -4124,7 +4137,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
            fprintf_indent (f, indent, "case %s:\n", op->id);
        }
       fprintf_indent (f, indent, "  {\n");
-      generic_exprs[i]->gen (f, indent + 4, gimple, depth);
+      generic_exprs[i]->gen (f, indent + 4, ns, gimple, depth);
       fprintf_indent (f, indent, "    break;\n");
       fprintf_indent (f, indent, "  }\n");
     }
@@ -4155,7 +4168,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
          last_op = e->operation;
          fprintf_indent (f, indent, "  if (call_expr_nargs (%s) == %d)\n"
                                     "    {\n", kid_opname, e->ops.length ());
-         generic_fns[j]->gen (f, indent + 6, false, depth);
+         generic_fns[j]->gen (f, indent + 6, ns, false, depth);
          fprintf_indent (f, indent, "    }\n");
        }
       fprintf_indent (f, indent, "  break;\n");
@@ -4194,20 +4207,20 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, 
int depth,
          fprintf_indent (f, indent + 4, "tree %s = %s_pops[%d];\n",
                          child_opname, kid_opname, j);
        }
-      preds[i]->gen_kids (f, indent + 4, gimple, depth);
+      preds[i]->gen_kids (f, indent + 4, ns, gimple, depth);
       fprintf_indent (f, indent, "  }\n");
       indent -= 2;
       fprintf_indent (f, indent, "}\n");
     }
 
   for (unsigned i = 0; i < others.length (); ++i)
-    others[i]->gen (f, indent, gimple, depth);
+    others[i]->gen (f, indent, ns, gimple, depth);
 }
 
 /* Generate matching code for the decision tree operand.  */
 
 void
-dt_operand::gen (FILE *f, int indent, bool gimple, int depth)
+dt_operand::gen (FILE *f, int indent, ns_info &ns, bool gimple, int depth)
 {
   char opname[20];
   get_name (opname);
@@ -4239,7 +4252,7 @@ dt_operand::gen (FILE *f, int indent, bool gimple, int 
depth)
     gcc_unreachable ();
 
   indent += 4 * n_braces;
-  gen_kids (f, indent, gimple, depth);
+  gen_kids (f, indent, ns, gimple, depth);
 
   for (unsigned i = 0; i < n_braces; ++i)
     {
@@ -4253,7 +4266,7 @@ dt_operand::gen (FILE *f, int indent, bool gimple, int 
depth)
 /* Generate matching code for the phi when meet COND_EXPR.  */
 
 void
-dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth)
+dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth, ns_info &ns)
 {
   char opname_0[20];
   char opname_1[20];
@@ -4285,7 +4298,7 @@ dt_operand::gen_phi_on_cond (FILE *f, int indent, int 
depth)
     "boolean_type_node, _cond_lhs_%d, _cond_rhs_%d);\n",
     opname_0, depth, depth, depth);
 
-  gen_kids (f, indent, true, depth);
+  gen_kids (f, indent, ns, true, depth);
 
   indent -= 2;
   fprintf_indent (f, indent, "}\n");
@@ -4296,10 +4309,10 @@ dt_operand::gen_phi_on_cond (FILE *f, int indent, int 
depth)
    either the RESULT location or the S's match location if RESULT is null. */
 static void
 emit_logging_call (FILE *f, int indent, class simplify *s, operand *result,
-                                 bool gimple)
+                  ns_info &ns, 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);
@@ -4313,7 +4326,8 @@ emit_logging_call (FILE *f, int indent, class simplify 
*s, operand *result,
    Main recursive worker.  */
 
 void
-dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
+dt_simplify::gen_1 (FILE *f, int indent, ns_info &ns, bool gimple,
+                   operand *result)
 {
   if (result)
     {
@@ -4323,7 +4337,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
          indent += 4;
          output_line_directive (f, w->location);
          w->with->gen_transform (f, indent, NULL, true, 1, "type", NULL);
-         gen_1 (f, indent, gimple, w->subexpr);
+         gen_1 (f, indent, ns, gimple, w->subexpr);
          indent -= 4;
          fprintf_indent (f, indent, "}\n");
          return;
@@ -4336,7 +4350,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
          fprintf (f, ")\n");
          fprintf_indent (f, indent + 2, "{\n");
          indent += 4;
-         gen_1 (f, indent, gimple, ife->trueexpr);
+         gen_1 (f, indent, ns, gimple, ife->trueexpr);
          indent -= 4;
          fprintf_indent (f, indent + 2, "}\n");
          if (ife->falseexpr)
@@ -4344,7 +4358,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
              fprintf_indent (f, indent, "else\n");
              fprintf_indent (f, indent + 2, "{\n");
              indent += 4;
-             gen_1 (f, indent, gimple, ife->falseexpr);
+             gen_1 (f, indent, ns, gimple, ife->falseexpr);
              indent -= 4;
              fprintf_indent (f, indent + 2, "}\n");
            }
@@ -4441,7 +4455,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
   if (!result)
     {
       /* If there is no result then this is a predicate implementation.  */
-      emit_logging_call (f, indent, s, result, gimple);
+      emit_logging_call (f, indent, s, result, ns, gimple);
       fprintf_indent (f, indent, "return true;\n");
     }
   else if (gimple)
@@ -4516,7 +4530,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
                                  "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",
+                                 "res_op->resimplify (%s, valueize, "
+                                 "GIMPLE_MATCH_SIMPLIFIER);\n",
                                  !e->force_leaf ? "lseq" : "NULL");
                  indent -= 4;
                  fprintf_indent (f, indent,
@@ -4524,7 +4539,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
                }
              else
                fprintf_indent (f, indent,
-                               "res_op->resimplify (%s, valueize);\n",
+                               "res_op->resimplify (%s, valueize, "
+                               "GIMPLE_MATCH_SIMPLIFIER);\n",
                                !e->force_leaf ? "lseq" : "NULL");
              if (e->force_leaf)
                {
@@ -4561,7 +4577,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
        }
       else
        gcc_unreachable ();
-      emit_logging_call (f, indent, s, result, gimple);
+      emit_logging_call (f, indent, s, result, ns, gimple);
       fprintf_indent (f, indent, "return true;\n");
     }
   else /* GENERIC */
@@ -4616,7 +4632,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
            }
          if (is_predicate)
            {
-             emit_logging_call (f, indent, s, result, gimple);
+             emit_logging_call (f, indent, s, result, ns, gimple);
              fprintf_indent (f, indent, "return true;\n");
            }
          else
@@ -4684,7 +4700,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
                                  i);
                }
            }
-         emit_logging_call (f, indent, s, result, gimple);
+         emit_logging_call (f, indent, s, result, ns, gimple);
          fprintf_indent (f, indent, "return _r;\n");
        }
     }
@@ -4700,7 +4716,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, 
operand *result)
    that is not part of the decision tree (simplify->match).  */
 
 void
-dt_simplify::gen (FILE *f, int indent, bool gimple, int depth ATTRIBUTE_UNUSED)
+dt_simplify::gen (FILE *f, int indent, ns_info &ns, bool gimple, int depth 
ATTRIBUTE_UNUSED)
 {
   fprintf_indent (f, indent, "{\n");
   indent += 2;
@@ -4767,7 +4783,7 @@ dt_simplify::gen (FILE *f, int indent, bool gimple, int 
depth ATTRIBUTE_UNUSED)
          else
            gcc_unreachable ();
        }
-      gen_1 (f, indent, gimple, s->result);
+      gen_1 (f, indent, ns, gimple, s->result);
     }
 
   indent -= 2;
@@ -4860,7 +4876,7 @@ sinfo_hashmap_traits::equal_keys (const key_type &v,
    tree.  */
 
 void
-decision_tree::gen (vec <FILE *> &files, bool gimple)
+decision_tree::gen (vec <FILE *> &files, ns_info &ns, bool gimple)
 {
   sinfo_map_t si;
 
@@ -4893,8 +4909,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"
@@ -4928,7 +4944,7 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
       fprintf (f, "{\n");
       fprintf_indent (f, 2, "const bool debug_dump = "
                            "dump_file && (dump_flags & TDF_FOLDING);\n");
-      s->s->gen_1 (f, 2, gimple, s->s->s->result);
+      s->s->gen_1 (f, 2, ns, gimple, s->s->s->result);
       if (gimple)
        fprintf (f, "  return false;\n");
       else
@@ -4961,25 +4977,25 @@ 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, ")");
          fprintf (f, "{\n");
          fprintf_indent (f, 2, "const bool debug_dump = "
                                "dump_file && (dump_flags & TDF_FOLDING);\n");
-         dop->gen_kids (f, 2, gimple, 0);
+         dop->gen_kids (f, 2, ns, gimple, 0);
          if (gimple)
            fprintf (f, "  return false;\n");
          else
@@ -4998,13 +5014,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 +5041,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 +5080,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,15 +5098,42 @@ 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.  */
 
 void
-write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
+write_predicate (FILE *f, predicate_id *p, decision_tree &dt, ns_info &ns,
+                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, "");
@@ -5102,7 +5145,7 @@ write_predicate (FILE *f, predicate_id *p, decision_tree 
&dt, bool gimple)
 
   if (!gimple)
     fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
-  dt.root->gen_kids (f, 2, gimple, 0);
+  dt.root->gen_kids (f, 2, ns, gimple, 0);
 
   fprintf_indent (f, 2, "return false;\n"
           "}\n");
@@ -6271,7 +6314,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 +6344,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 +6358,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 +6380,31 @@ main (int argc, char **argv)
       return 1;
     }
 
+  /* Initialize priting information. */
+  ns_info ns;
+  if (s_namespace)
+    {
+      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)
@@ -6395,7 +6467,7 @@ main (int argc, char **argv)
       parts.quick_push (stdout);
       write_header (stdout, s_include_file);
       write_header_includes (gimple, stdout);
-      write_header_declarations (gimple, stdout);
+      write_header_declarations (gimple, ns, stdout);
     }
   else
     {
@@ -6406,10 +6478,11 @@ 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);
+      write_header_declarations (gimple, ns, header_file);
     }
 
   /* Go over all predicates defined with patterns and perform
@@ -6433,7 +6506,7 @@ main (int argc, char **argv)
       /* Cycle the file buffers.  */
       FILE *f = choose_output (parts);
 
-      write_predicate (f, pred, dt, gimple);
+      write_predicate (f, pred, dt, ns, gimple);
     }
 
   /* Lower the main simplifiers and generate code for them.  */
@@ -6450,9 +6523,9 @@ main (int argc, char **argv)
   if (verbose == 2)
     dt.print (stderr);
 
-  dt.gen (parts, gimple);
+  dt.gen (parts, ns, gimple);
 
-  define_dump_logs (gimple, choose_output (parts));
+  define_dump_logs (gimple, ns, choose_output (parts));
 
   for (FILE *f : parts)
     {
@@ -6462,7 +6535,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 +6545,8 @@ main (int argc, char **argv)
   cpp_destroy (r);
 
   delete operators;
+  XDELETE (ns.l);
+  XDELETE (ns.u);
 
   return 0;
 }
diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
index 
74f2c5f19bcfdf2e40435119ac757658a110e471..8626a1990bd81d1f8950e172726c5f9e61abc628
 100644
--- a/gcc/gimple-match-exports.cc
+++ b/gcc/gimple-match-exports.cc
@@ -66,6 +66,7 @@ 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.  */
@@ -90,37 +91,48 @@ tree do_valueize (tree (*)(tree), tree);
    They expect valueized operands in canonical order and do not
    perform simplification of all-constant operands.  */
 
-static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
-static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
-static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
-static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
-static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
-static bool gimple_resimplify6 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
-static bool gimple_resimplify7 (gimple_seq *, gimple_match_op *, tree 
(*)(tree));
+static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
+static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
+static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
+static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
+static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
+static bool gimple_resimplify6 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
+static bool gimple_resimplify7 (gimple_seq *, gimple_match_op *, tree 
(*)(tree),
+                               gimple_match_simplify_fn);
 
 /* Match and simplify the toplevel valueized operation THIS.
    Replaces THIS with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
 bool
-gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
+gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree),
+                            gimple_match_simplify_fn simplifier)
 {
+  if (!simplifier)
+    simplifier = gimple_simplify;
+
   switch (num_ops)
     {
     case 1:
-      return gimple_resimplify1 (seq, this, valueize);
+      return gimple_resimplify1 (seq, this, valueize, simplifier);
     case 2:
-      return gimple_resimplify2 (seq, this, valueize);
+      return gimple_resimplify2 (seq, this, valueize, simplifier);
     case 3:
-      return gimple_resimplify3 (seq, this, valueize);
+      return gimple_resimplify3 (seq, this, valueize, simplifier);
     case 4:
-      return gimple_resimplify4 (seq, this, valueize);
+      return gimple_resimplify4 (seq, this, valueize, simplifier);
     case 5:
-      return gimple_resimplify5 (seq, this, valueize);
+      return gimple_resimplify5 (seq, this, valueize, simplifier);
     case 6:
-      return gimple_resimplify6 (seq, this, valueize);
+      return gimple_resimplify6 (seq, this, valueize, simplifier);
     case 7:
-      return gimple_resimplify7 (seq, this, valueize);
+      return gimple_resimplify7 (seq, this, valueize, simplifier);
     default:
       gcc_unreachable ();
     }
@@ -303,7 +315,8 @@ build_call_internal (internal_fn fn, gimple_match_op 
*res_op)
 
 static bool
 maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
-                                tree (*valueize) (tree))
+                                tree (*valueize) (tree),
+                                gimple_match_simplify_fn simplifier)
 {
   if (!res_op->cond.cond)
     return false;
@@ -370,7 +383,7 @@ maybe_resimplify_conditional_op (gimple_seq *seq, 
gimple_match_op *res_op,
                       res_op->cond.cond, res_op->ops[0],
                       res_op->cond.else_value);
       *res_op = new_op;
-      return gimple_resimplify3 (seq, res_op, valueize);
+      return gimple_resimplify3 (seq, res_op, valueize, simplifier);
     }
 
   /* Otherwise try rewriting the operation as an IFN_COND_* call.
@@ -400,7 +413,8 @@ maybe_resimplify_conditional_op (gimple_seq *seq, 
gimple_match_op *res_op,
 
 static bool
 try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
-                               gimple_seq *seq, tree (*valueize) (tree))
+                               gimple_seq *seq, tree (*valueize) (tree),
+                               gimple_match_simplify_fn simplifier)
 {
   code_helper op;
   tree_code code = conditional_internal_fn_code (ifn);
@@ -431,22 +445,22 @@ try_conditional_simplification (internal_fn ifn, 
gimple_match_op *res_op,
   switch (num_ops - num_cond_ops)
     {
     case 1:
-      if (!gimple_resimplify1 (seq, &cond_op, valueize))
+      if (!gimple_resimplify1 (seq, &cond_op, valueize, simplifier))
        return false;
       break;
     case 2:
-      if (!gimple_resimplify2 (seq, &cond_op, valueize))
+      if (!gimple_resimplify2 (seq, &cond_op, valueize, simplifier))
        return false;
       break;
     case 3:
-      if (!gimple_resimplify3 (seq, &cond_op, valueize))
+      if (!gimple_resimplify3 (seq, &cond_op, valueize, simplifier))
        return false;
       break;
     default:
       gcc_unreachable ();
     }
   *res_op = cond_op;
-  maybe_resimplify_conditional_op (seq, res_op, valueize);
+  maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
   return true;
 }
 
@@ -873,8 +887,12 @@ gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
 
 bool
 gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
-                tree (*valueize)(tree), tree (*top_valueize)(tree))
+                tree (*valueize)(tree), tree (*top_valueize)(tree),
+                gimple_match_simplify_fn simplifier)
 {
+  if (!simplifier)
+    simplifier = gimple_simplify;
+
   bool valueized = false;
   auto valueize_op = [&](tree op)
     {
@@ -887,13 +905,14 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, 
gimple_seq *seq,
   if (res_op->code.is_internal_fn ())
     {
       internal_fn ifn = internal_fn (res_op->code);
-      if (try_conditional_simplification (ifn, res_op, seq, valueize))
+      if (try_conditional_simplification (ifn, res_op, seq, valueize,
+                                         simplifier))
        return true;
     }
 
   if (!res_op->reverse
       && res_op->num_ops
-      && res_op->resimplify (seq, valueize))
+      && res_op->resimplify (seq, valueize, simplifier))
     return true;
 
   return valueized;
@@ -907,7 +926,8 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, 
gimple_seq *seq,
 
 static bool
 gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   if (constant_for_folding (res_op->ops[0]))
     {
@@ -928,7 +948,7 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op 
*res_op,
          if (TREE_OVERFLOW_P (tem))
            tem = drop_tree_overflow (tem);
          res_op->set_value (tem);
-         maybe_resimplify_conditional_op (seq, res_op, valueize);
+         maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
          return true;
        }
     }
@@ -949,8 +969,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -958,7 +977,7 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op 
*res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return false;
@@ -972,7 +991,8 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op 
*res_op,
 
 static bool
 gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   if (constant_for_folding (res_op->ops[0])
       && constant_for_folding (res_op->ops[1]))
@@ -995,7 +1015,7 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op 
*res_op,
          if (TREE_OVERFLOW_P (tem))
            tem = drop_tree_overflow (tem);
          res_op->set_value (tem);
-         maybe_resimplify_conditional_op (seq, res_op, valueize);
+         maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
          return true;
        }
     }
@@ -1026,9 +1046,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -1036,7 +1054,7 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op 
*res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1050,7 +1068,8 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op 
*res_op,
 
 static bool
 gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   if (constant_for_folding (res_op->ops[0])
       && constant_for_folding (res_op->ops[1])
@@ -1075,7 +1094,7 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op 
*res_op,
          if (TREE_OVERFLOW_P (tem))
            tem = drop_tree_overflow (tem);
          res_op->set_value (tem);
-         maybe_resimplify_conditional_op (seq, res_op, valueize);
+         maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
          return true;
        }
     }
@@ -1102,9 +1121,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -1112,7 +1129,7 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op 
*res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1126,7 +1143,8 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op 
*res_op,
 
 static bool
 gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for four-operand functions.  */
 
@@ -1152,10 +1170,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -1163,7 +1178,7 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op 
*res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1177,7 +1192,8 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op 
*res_op,
 
 static bool
 gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for five-operand functions.  */
 
@@ -1192,16 +1208,13 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       *res_op = res_op2;
       return true;
     }
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1215,7 +1228,8 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op 
*res_op,
 
 static bool
 gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for six-operand functions.  */
 
@@ -1230,16 +1244,13 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       *res_op = res_op2;
       return true;
     }
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1253,7 +1264,8 @@ gimple_resimplify6 (gimple_seq *seq, gimple_match_op 
*res_op,
 
 static bool
 gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
-                   tree (*valueize)(tree))
+                   tree (*valueize)(tree),
+                   gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for seven-operand functions.  */
 
@@ -1268,17 +1280,13 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       *res_op = res_op2;
       return true;
     }
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h
index 
8ff58e8cd7f27a1adc2fabf0f76ee940dea09199..5f6a48edfb5883a964537287e0675bfb273e3005
 100644
--- a/gcc/gimple-match.h
+++ b/gcc/gimple-match.h
@@ -23,6 +23,12 @@ 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));
+
 /* 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.  */
@@ -112,7 +118,8 @@ public:
 
   tree op_or_null (unsigned int) const;
 
-  bool resimplify (gimple_seq *, tree (*)(tree));
+  bool resimplify (gimple_seq *, tree (*)(tree),
+                  gimple_match_simplify_fn = NULL);
 
   /* The maximum value of NUM_OPS.  */
   static const unsigned int MAX_NUM_OPS = 7;
@@ -408,7 +415,8 @@ extern tree (*mprts_hook) (gimple_match_op *);
 
 bool gimple_extract_op (gimple *, gimple_match_op *);
 bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *,
-                     tree (*)(tree), tree (*)(tree));
+                     tree (*)(tree), tree (*)(tree),
+                     gimple_match_simplify_fn = NULL);
 tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *,
                            tree res = NULL_TREE);
 void maybe_build_generic_op (gimple_match_op *);


-- 
diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
index 920cf27877d3bf69c8ffcbb3497d9d0b54f662c7..948199c6f0c2a10003919a9ca738bed5d29b1ee9 100644
--- a/gcc/genmatch.cc
+++ b/gcc/genmatch.cc
@@ -56,6 +56,14 @@ 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;
+
+
 /* Verboseness.  0 is quiet, 1 adds some warnings, 2 is for debugging.  */
 unsigned verbose;
 
@@ -878,22 +886,25 @@ fp_decl_done (FILE *f, const char *trailer)
 static vec<int> dbg_line_numbers;
 
 static void
-write_header_declarations (bool gimple, FILE *f)
+write_header_declarations (bool gimple, ns_info &ns, 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);
+  if (gimple)
+    fprintf (f, "\n#define GIMPLE_MATCH_SIMPLIFIER gimple%s_simplify\n",
+	     ns.l);
 }
 
 static void
-define_dump_logs (bool gimple, FILE *f)
+define_dump_logs (bool gimple, ns_info &ns, 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 ());
@@ -2448,10 +2459,10 @@ public:
 			    unsigned pos);
   dt_node *append_simplify (simplify *, unsigned, dt_operand **);
 
-  virtual void gen (FILE *, int, bool, int) {}
+  virtual void gen (FILE *, int, ns_info &, bool, int) {}
 
-  void gen_kids (FILE *, int, bool, int);
-  void gen_kids_1 (FILE *, int, bool, int,
+  void gen_kids (FILE *, int, ns_info &, bool, int);
+  void gen_kids_1 (FILE *, int, ns_info &, bool, int,
 		   const vec<dt_operand *> &, const vec<dt_operand *> &,
 		   const vec<dt_operand *> &, const vec<dt_operand *> &,
 		   const vec<dt_operand *> &, const vec<dt_node *> &);
@@ -2475,7 +2486,7 @@ public:
       : dt_node (type, parent_), op (op_), match_dop (match_dop_),
       pos (pos_), value_match (false), for_id (current_id) {}
 
-  void gen (FILE *, int, bool, int) final override;
+  void gen (FILE *, int, ns_info &, bool, int) final override;
   unsigned gen_predicate (FILE *, int, const char *, bool);
   unsigned gen_match_op (FILE *, int, const char *, bool);
 
@@ -2484,7 +2495,7 @@ public:
 
   char *get_name (char *);
   void gen_opname (char *, unsigned);
-  void gen_phi_on_cond (FILE *, int, int);
+  void gen_phi_on_cond (FILE *, int, int, ns_info &);
 };
 
 /* Leaf node of the decision tree, used for DT_SIMPLIFY.  */
@@ -2501,8 +2512,8 @@ public:
 	: dt_node (DT_SIMPLIFY, NULL), s (s_), pattern_no (pattern_no_),
 	  indexes (indexes_), info (NULL)  {}
 
-  void gen_1 (FILE *, int, bool, operand *);
-  void gen (FILE *f, int, bool, int) final override;
+  void gen_1 (FILE *, int, ns_info &, bool, operand *);
+  void gen (FILE *f, int, ns_info &, bool, int) final override;
 };
 
 template<>
@@ -2533,7 +2544,7 @@ public:
   dt_node *root;
 
   void insert (class simplify *, unsigned);
-  void gen (vec <FILE *> &f, bool gimple);
+  void gen (vec <FILE *> &f, ns_info &ns, bool gimple);
   void print (FILE *f = stderr);
 
   decision_tree () { root = new dt_node (dt_node::DT_NODE, NULL); }
@@ -3180,7 +3191,6 @@ capture_info::walk_c_expr (c_expr *e)
     }
 }
 
-
 /* The current label failing the current matched pattern during
    code generation.  */
 static char *fail_label;
@@ -3377,7 +3387,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
 	  fprintf_indent (f, indent,
 			  "tem_op.ops[0] = _r%d;\n", depth);
 	  fprintf_indent (f, indent,
-			  "tem_op.resimplify (%s, valueize);\n",
+			  "tem_op.resimplify (%s, valueize, "
+			  "GIMPLE_MATCH_SIMPLIFIER);\n",
 			  !force_leaf ? "lseq" : "NULL");
 	  indent -= 4;
 	  fprintf_indent (f, indent + 2, "}\n");
@@ -3397,7 +3408,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
 	    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",
+			  "%s.resimplify (%s, valueize, "
+			  "GIMPLE_MATCH_SIMPLIFIER);\n",
 			  in_place, !force_leaf ? "lseq" : "NULL");
 	  indent -= 2;
 	  fprintf_indent (f, indent, "}\n");
@@ -3425,7 +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.resimplify (%s, valueize);\n",
+	  fprintf_indent (f, indent, "tem_op.resimplify (%s, valueize, "
+			  "GIMPLE_MATCH_SIMPLIFIER);\n",
 			  !force_leaf ? "lseq" : "NULL");
 	  fprintf_indent (f, indent,
 			  "_r%d = maybe_push_res_to_seq (&tem_op, %s);\n",
@@ -3845,7 +3858,7 @@ fns_cmp (const void *p1, const void *p2)
 /* Generate matching code for the children of the decision tree node.  */
 
 void
-dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth)
+dt_node::gen_kids (FILE *f, int indent, ns_info &ns, bool gimple, int depth)
 {
   auto_vec<dt_operand *> gimple_exprs;
   auto_vec<dt_operand *> generic_exprs;
@@ -3917,10 +3930,10 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth)
 	     for what we have collected sofar.  */
 	  fns.qsort (fns_cmp);
 	  generic_fns.qsort (fns_cmp);
-	  gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs,
+	  gen_kids_1 (f, indent, ns, gimple, depth, gimple_exprs, generic_exprs,
 		      fns, generic_fns, preds, others);
 	  /* And output the true operand itself.  */
-	  kids[i]->gen (f, indent, gimple, depth);
+	  kids[i]->gen (f, indent, ns, gimple, depth);
 	  gimple_exprs.truncate (0);
 	  generic_exprs.truncate (0);
 	  fns.truncate (0);
@@ -3935,14 +3948,14 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple, int depth)
   /* Generate code for the remains.  */
   fns.qsort (fns_cmp);
   generic_fns.qsort (fns_cmp);
-  gen_kids_1 (f, indent, gimple, depth, gimple_exprs, generic_exprs,
+  gen_kids_1 (f, indent, ns, gimple, depth, gimple_exprs, generic_exprs,
 	      fns, generic_fns, preds, others);
 }
 
 /* Generate matching code for the children of the decision tree node.  */
 
 void
-dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
+dt_node::gen_kids_1 (FILE *f, int indent, ns_info &ns, bool gimple, int depth,
 		     const vec<dt_operand *> &gimple_exprs,
 		     const vec<dt_operand *> &generic_exprs,
 		     const vec<dt_operand *> &fns,
@@ -4014,7 +4027,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 		    fprintf_indent (f, indent, "case %s:\n", op->id);
 		}
 	      fprintf_indent (f, indent, "  {\n");
-	      gimple_exprs[i]->gen (f, indent + 4, true, depth);
+	      gimple_exprs[i]->gen (f, indent + 4, ns, true, depth);
 	      fprintf_indent (f, indent, "    break;\n");
 	      fprintf_indent (f, indent, "  }\n");
 	    }
@@ -4035,7 +4048,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 		{
 		  expr *e = as_a <expr *> (gimple_exprs[i]->op);
 		  if (*e->operation == COND_EXPR && e->match_phi)
-		    gimple_exprs[i]->gen_phi_on_cond (f, indent, depth);
+		    gimple_exprs[i]->gen_phi_on_cond (f, indent, depth, ns);
 		}
 
 	      indent -= 2;
@@ -4076,7 +4089,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 			      "  if (gimple_call_num_args (_c%d) == %d)\n",
 			      depth, e->ops.length ());
 	      fprintf_indent (f, indent, "    {\n");
-	      fns[i]->gen (f, indent + 6, true, depth);
+	      fns[i]->gen (f, indent + 6, ns, true, depth);
 	      fprintf_indent (f, indent, "    }\n");
 	    }
 
@@ -4098,7 +4111,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 	  if (*op == SSA_NAME && (exprs_len || fns_len))
 	    {
 	      fprintf_indent (f, indent + 4, "{\n");
-	      generic_exprs[i]->gen (f, indent + 6, gimple, depth);
+	      generic_exprs[i]->gen (f, indent + 6, ns, gimple, depth);
 	      fprintf_indent (f, indent + 4, "}\n");
 	    }
 	}
@@ -4124,7 +4137,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 	    fprintf_indent (f, indent, "case %s:\n", op->id);
 	}
       fprintf_indent (f, indent, "  {\n");
-      generic_exprs[i]->gen (f, indent + 4, gimple, depth);
+      generic_exprs[i]->gen (f, indent + 4, ns, gimple, depth);
       fprintf_indent (f, indent, "    break;\n");
       fprintf_indent (f, indent, "  }\n");
     }
@@ -4155,7 +4168,7 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 	  last_op = e->operation;
 	  fprintf_indent (f, indent, "  if (call_expr_nargs (%s) == %d)\n"
 				     "    {\n", kid_opname, e->ops.length ());
-	  generic_fns[j]->gen (f, indent + 6, false, depth);
+	  generic_fns[j]->gen (f, indent + 6, ns, false, depth);
 	  fprintf_indent (f, indent, "    }\n");
 	}
       fprintf_indent (f, indent, "  break;\n");
@@ -4194,20 +4207,20 @@ dt_node::gen_kids_1 (FILE *f, int indent, bool gimple, int depth,
 	  fprintf_indent (f, indent + 4, "tree %s = %s_pops[%d];\n",
 			  child_opname, kid_opname, j);
 	}
-      preds[i]->gen_kids (f, indent + 4, gimple, depth);
+      preds[i]->gen_kids (f, indent + 4, ns, gimple, depth);
       fprintf_indent (f, indent, "  }\n");
       indent -= 2;
       fprintf_indent (f, indent, "}\n");
     }
 
   for (unsigned i = 0; i < others.length (); ++i)
-    others[i]->gen (f, indent, gimple, depth);
+    others[i]->gen (f, indent, ns, gimple, depth);
 }
 
 /* Generate matching code for the decision tree operand.  */
 
 void
-dt_operand::gen (FILE *f, int indent, bool gimple, int depth)
+dt_operand::gen (FILE *f, int indent, ns_info &ns, bool gimple, int depth)
 {
   char opname[20];
   get_name (opname);
@@ -4239,7 +4252,7 @@ dt_operand::gen (FILE *f, int indent, bool gimple, int depth)
     gcc_unreachable ();
 
   indent += 4 * n_braces;
-  gen_kids (f, indent, gimple, depth);
+  gen_kids (f, indent, ns, gimple, depth);
 
   for (unsigned i = 0; i < n_braces; ++i)
     {
@@ -4253,7 +4266,7 @@ dt_operand::gen (FILE *f, int indent, bool gimple, int depth)
 /* Generate matching code for the phi when meet COND_EXPR.  */
 
 void
-dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth)
+dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth, ns_info &ns)
 {
   char opname_0[20];
   char opname_1[20];
@@ -4285,7 +4298,7 @@ dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth)
     "boolean_type_node, _cond_lhs_%d, _cond_rhs_%d);\n",
     opname_0, depth, depth, depth);
 
-  gen_kids (f, indent, true, depth);
+  gen_kids (f, indent, ns, true, depth);
 
   indent -= 2;
   fprintf_indent (f, indent, "}\n");
@@ -4296,10 +4309,10 @@ dt_operand::gen_phi_on_cond (FILE *f, int indent, int depth)
    either the RESULT location or the S's match location if RESULT is null. */
 static void
 emit_logging_call (FILE *f, int indent, class simplify *s, operand *result,
-				  bool gimple)
+		   ns_info &ns, 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);
@@ -4313,7 +4326,8 @@ emit_logging_call (FILE *f, int indent, class simplify *s, operand *result,
    Main recursive worker.  */
 
 void
-dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
+dt_simplify::gen_1 (FILE *f, int indent, ns_info &ns, bool gimple,
+		    operand *result)
 {
   if (result)
     {
@@ -4323,7 +4337,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 	  indent += 4;
 	  output_line_directive (f, w->location);
 	  w->with->gen_transform (f, indent, NULL, true, 1, "type", NULL);
-	  gen_1 (f, indent, gimple, w->subexpr);
+	  gen_1 (f, indent, ns, gimple, w->subexpr);
 	  indent -= 4;
 	  fprintf_indent (f, indent, "}\n");
 	  return;
@@ -4336,7 +4350,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 	  fprintf (f, ")\n");
 	  fprintf_indent (f, indent + 2, "{\n");
 	  indent += 4;
-	  gen_1 (f, indent, gimple, ife->trueexpr);
+	  gen_1 (f, indent, ns, gimple, ife->trueexpr);
 	  indent -= 4;
 	  fprintf_indent (f, indent + 2, "}\n");
 	  if (ife->falseexpr)
@@ -4344,7 +4358,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 	      fprintf_indent (f, indent, "else\n");
 	      fprintf_indent (f, indent + 2, "{\n");
 	      indent += 4;
-	      gen_1 (f, indent, gimple, ife->falseexpr);
+	      gen_1 (f, indent, ns, gimple, ife->falseexpr);
 	      indent -= 4;
 	      fprintf_indent (f, indent + 2, "}\n");
 	    }
@@ -4441,7 +4455,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
   if (!result)
     {
       /* If there is no result then this is a predicate implementation.  */
-      emit_logging_call (f, indent, s, result, gimple);
+      emit_logging_call (f, indent, s, result, ns, gimple);
       fprintf_indent (f, indent, "return true;\n");
     }
   else if (gimple)
@@ -4516,7 +4530,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 				  "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",
+				  "res_op->resimplify (%s, valueize, "
+				  "GIMPLE_MATCH_SIMPLIFIER);\n",
 				  !e->force_leaf ? "lseq" : "NULL");
 		  indent -= 4;
 		  fprintf_indent (f, indent,
@@ -4524,7 +4539,8 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 		}
 	      else
 		fprintf_indent (f, indent,
-				"res_op->resimplify (%s, valueize);\n",
+				"res_op->resimplify (%s, valueize, "
+				"GIMPLE_MATCH_SIMPLIFIER);\n",
 				!e->force_leaf ? "lseq" : "NULL");
 	      if (e->force_leaf)
 		{
@@ -4561,7 +4577,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 	}
       else
 	gcc_unreachable ();
-      emit_logging_call (f, indent, s, result, gimple);
+      emit_logging_call (f, indent, s, result, ns, gimple);
       fprintf_indent (f, indent, "return true;\n");
     }
   else /* GENERIC */
@@ -4616,7 +4632,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 	    }
 	  if (is_predicate)
 	    {
-	      emit_logging_call (f, indent, s, result, gimple);
+	      emit_logging_call (f, indent, s, result, ns, gimple);
 	      fprintf_indent (f, indent, "return true;\n");
 	    }
 	  else
@@ -4684,7 +4700,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
 				  i);
 		}
 	    }
-	  emit_logging_call (f, indent, s, result, gimple);
+	  emit_logging_call (f, indent, s, result, ns, gimple);
 	  fprintf_indent (f, indent, "return _r;\n");
 	}
     }
@@ -4700,7 +4716,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result)
    that is not part of the decision tree (simplify->match).  */
 
 void
-dt_simplify::gen (FILE *f, int indent, bool gimple, int depth ATTRIBUTE_UNUSED)
+dt_simplify::gen (FILE *f, int indent, ns_info &ns, bool gimple, int depth ATTRIBUTE_UNUSED)
 {
   fprintf_indent (f, indent, "{\n");
   indent += 2;
@@ -4767,7 +4783,7 @@ dt_simplify::gen (FILE *f, int indent, bool gimple, int depth ATTRIBUTE_UNUSED)
 	  else
 	    gcc_unreachable ();
 	}
-      gen_1 (f, indent, gimple, s->result);
+      gen_1 (f, indent, ns, gimple, s->result);
     }
 
   indent -= 2;
@@ -4860,7 +4876,7 @@ sinfo_hashmap_traits::equal_keys (const key_type &v,
    tree.  */
 
 void
-decision_tree::gen (vec <FILE *> &files, bool gimple)
+decision_tree::gen (vec <FILE *> &files, ns_info &ns, bool gimple)
 {
   sinfo_map_t si;
 
@@ -4893,8 +4909,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"
@@ -4928,7 +4944,7 @@ decision_tree::gen (vec <FILE *> &files, bool gimple)
       fprintf (f, "{\n");
       fprintf_indent (f, 2, "const bool debug_dump = "
 			    "dump_file && (dump_flags & TDF_FOLDING);\n");
-      s->s->gen_1 (f, 2, gimple, s->s->s->result);
+      s->s->gen_1 (f, 2, ns, gimple, s->s->s->result);
       if (gimple)
 	fprintf (f, "  return false;\n");
       else
@@ -4961,25 +4977,25 @@ 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, ")");
 	  fprintf (f, "{\n");
 	  fprintf_indent (f, 2, "const bool debug_dump = "
 				"dump_file && (dump_flags & TDF_FOLDING);\n");
-	  dop->gen_kids (f, 2, gimple, 0);
+	  dop->gen_kids (f, 2, ns, gimple, 0);
 	  if (gimple)
 	    fprintf (f, "  return false;\n");
 	  else
@@ -4998,13 +5014,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 +5041,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 +5080,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,15 +5098,42 @@ 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.  */
 
 void
-write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
+write_predicate (FILE *f, predicate_id *p, decision_tree &dt, ns_info &ns,
+		 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, "");
@@ -5102,7 +5145,7 @@ write_predicate (FILE *f, predicate_id *p, decision_tree &dt, bool gimple)
 
   if (!gimple)
     fprintf_indent (f, 2, "if (TREE_SIDE_EFFECTS (t)) return false;\n");
-  dt.root->gen_kids (f, 2, gimple, 0);
+  dt.root->gen_kids (f, 2, ns, gimple, 0);
 
   fprintf_indent (f, 2, "return false;\n"
 	   "}\n");
@@ -6271,7 +6314,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 +6344,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 +6358,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 +6380,31 @@ main (int argc, char **argv)
       return 1;
     }
 
+  /* Initialize priting information. */
+  ns_info ns;
+  if (s_namespace)
+    {
+      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)
@@ -6395,7 +6467,7 @@ main (int argc, char **argv)
       parts.quick_push (stdout);
       write_header (stdout, s_include_file);
       write_header_includes (gimple, stdout);
-      write_header_declarations (gimple, stdout);
+      write_header_declarations (gimple, ns, stdout);
     }
   else
     {
@@ -6406,10 +6478,11 @@ 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);
+      write_header_declarations (gimple, ns, header_file);
     }
 
   /* Go over all predicates defined with patterns and perform
@@ -6433,7 +6506,7 @@ main (int argc, char **argv)
       /* Cycle the file buffers.  */
       FILE *f = choose_output (parts);
 
-      write_predicate (f, pred, dt, gimple);
+      write_predicate (f, pred, dt, ns, gimple);
     }
 
   /* Lower the main simplifiers and generate code for them.  */
@@ -6450,9 +6523,9 @@ main (int argc, char **argv)
   if (verbose == 2)
     dt.print (stderr);
 
-  dt.gen (parts, gimple);
+  dt.gen (parts, ns, gimple);
 
-  define_dump_logs (gimple, choose_output (parts));
+  define_dump_logs (gimple, ns, choose_output (parts));
 
   for (FILE *f : parts)
     {
@@ -6462,7 +6535,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 +6545,8 @@ main (int argc, char **argv)
   cpp_destroy (r);
 
   delete operators;
+  XDELETE (ns.l);
+  XDELETE (ns.u);
 
   return 0;
 }
diff --git a/gcc/gimple-match-exports.cc b/gcc/gimple-match-exports.cc
index 74f2c5f19bcfdf2e40435119ac757658a110e471..8626a1990bd81d1f8950e172726c5f9e61abc628 100644
--- a/gcc/gimple-match-exports.cc
+++ b/gcc/gimple-match-exports.cc
@@ -66,6 +66,7 @@ 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.  */
@@ -90,37 +91,48 @@ tree do_valueize (tree (*)(tree), tree);
    They expect valueized operands in canonical order and do not
    perform simplification of all-constant operands.  */
 
-static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree (*)(tree));
-static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree (*)(tree));
-static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree (*)(tree));
-static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree (*)(tree));
-static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree (*)(tree));
-static bool gimple_resimplify6 (gimple_seq *, gimple_match_op *, tree (*)(tree));
-static bool gimple_resimplify7 (gimple_seq *, gimple_match_op *, tree (*)(tree));
+static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
+static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
+static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
+static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
+static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
+static bool gimple_resimplify6 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
+static bool gimple_resimplify7 (gimple_seq *, gimple_match_op *, tree (*)(tree),
+				gimple_match_simplify_fn);
 
 /* Match and simplify the toplevel valueized operation THIS.
    Replaces THIS with a simplified and/or canonicalized result and
    returns whether any change was made.  */
 
 bool
-gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
+gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree),
+			     gimple_match_simplify_fn simplifier)
 {
+  if (!simplifier)
+    simplifier = gimple_simplify;
+
   switch (num_ops)
     {
     case 1:
-      return gimple_resimplify1 (seq, this, valueize);
+      return gimple_resimplify1 (seq, this, valueize, simplifier);
     case 2:
-      return gimple_resimplify2 (seq, this, valueize);
+      return gimple_resimplify2 (seq, this, valueize, simplifier);
     case 3:
-      return gimple_resimplify3 (seq, this, valueize);
+      return gimple_resimplify3 (seq, this, valueize, simplifier);
     case 4:
-      return gimple_resimplify4 (seq, this, valueize);
+      return gimple_resimplify4 (seq, this, valueize, simplifier);
     case 5:
-      return gimple_resimplify5 (seq, this, valueize);
+      return gimple_resimplify5 (seq, this, valueize, simplifier);
     case 6:
-      return gimple_resimplify6 (seq, this, valueize);
+      return gimple_resimplify6 (seq, this, valueize, simplifier);
     case 7:
-      return gimple_resimplify7 (seq, this, valueize);
+      return gimple_resimplify7 (seq, this, valueize, simplifier);
     default:
       gcc_unreachable ();
     }
@@ -303,7 +315,8 @@ build_call_internal (internal_fn fn, gimple_match_op *res_op)
 
 static bool
 maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
-				 tree (*valueize) (tree))
+				 tree (*valueize) (tree),
+				 gimple_match_simplify_fn simplifier)
 {
   if (!res_op->cond.cond)
     return false;
@@ -370,7 +383,7 @@ maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
 		       res_op->cond.cond, res_op->ops[0],
 		       res_op->cond.else_value);
       *res_op = new_op;
-      return gimple_resimplify3 (seq, res_op, valueize);
+      return gimple_resimplify3 (seq, res_op, valueize, simplifier);
     }
 
   /* Otherwise try rewriting the operation as an IFN_COND_* call.
@@ -400,7 +413,8 @@ maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
-				gimple_seq *seq, tree (*valueize) (tree))
+				gimple_seq *seq, tree (*valueize) (tree),
+				gimple_match_simplify_fn simplifier)
 {
   code_helper op;
   tree_code code = conditional_internal_fn_code (ifn);
@@ -431,22 +445,22 @@ try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
   switch (num_ops - num_cond_ops)
     {
     case 1:
-      if (!gimple_resimplify1 (seq, &cond_op, valueize))
+      if (!gimple_resimplify1 (seq, &cond_op, valueize, simplifier))
 	return false;
       break;
     case 2:
-      if (!gimple_resimplify2 (seq, &cond_op, valueize))
+      if (!gimple_resimplify2 (seq, &cond_op, valueize, simplifier))
 	return false;
       break;
     case 3:
-      if (!gimple_resimplify3 (seq, &cond_op, valueize))
+      if (!gimple_resimplify3 (seq, &cond_op, valueize, simplifier))
 	return false;
       break;
     default:
       gcc_unreachable ();
     }
   *res_op = cond_op;
-  maybe_resimplify_conditional_op (seq, res_op, valueize);
+  maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
   return true;
 }
 
@@ -873,8 +887,12 @@ gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
 
 bool
 gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
-		 tree (*valueize)(tree), tree (*top_valueize)(tree))
+		 tree (*valueize)(tree), tree (*top_valueize)(tree),
+		 gimple_match_simplify_fn simplifier)
 {
+  if (!simplifier)
+    simplifier = gimple_simplify;
+
   bool valueized = false;
   auto valueize_op = [&](tree op)
     {
@@ -887,13 +905,14 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
   if (res_op->code.is_internal_fn ())
     {
       internal_fn ifn = internal_fn (res_op->code);
-      if (try_conditional_simplification (ifn, res_op, seq, valueize))
+      if (try_conditional_simplification (ifn, res_op, seq, valueize,
+					  simplifier))
 	return true;
     }
 
   if (!res_op->reverse
       && res_op->num_ops
-      && res_op->resimplify (seq, valueize))
+      && res_op->resimplify (seq, valueize, simplifier))
     return true;
 
   return valueized;
@@ -907,7 +926,8 @@ gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
 
 static bool
 gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   if (constant_for_folding (res_op->ops[0]))
     {
@@ -928,7 +948,7 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
 	  if (TREE_OVERFLOW_P (tem))
 	    tem = drop_tree_overflow (tem);
 	  res_op->set_value (tem);
-	  maybe_resimplify_conditional_op (seq, res_op, valueize);
+	  maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
 	  return true;
 	}
     }
@@ -949,8 +969,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -958,7 +977,7 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return false;
@@ -972,7 +991,8 @@ gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   if (constant_for_folding (res_op->ops[0])
       && constant_for_folding (res_op->ops[1]))
@@ -995,7 +1015,7 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
 	  if (TREE_OVERFLOW_P (tem))
 	    tem = drop_tree_overflow (tem);
 	  res_op->set_value (tem);
-	  maybe_resimplify_conditional_op (seq, res_op, valueize);
+	  maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
 	  return true;
 	}
     }
@@ -1026,9 +1046,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -1036,7 +1054,7 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1050,7 +1068,8 @@ gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   if (constant_for_folding (res_op->ops[0])
       && constant_for_folding (res_op->ops[1])
@@ -1075,7 +1094,7 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
 	  if (TREE_OVERFLOW_P (tem))
 	    tem = drop_tree_overflow (tem);
 	  res_op->set_value (tem);
-	  maybe_resimplify_conditional_op (seq, res_op, valueize);
+	  maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier);
 	  return true;
 	}
     }
@@ -1102,9 +1121,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -1112,7 +1129,7 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1126,7 +1143,8 @@ gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for four-operand functions.  */
 
@@ -1152,10 +1170,7 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       --depth;
       *res_op = res_op2;
@@ -1163,7 +1178,7 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
     }
   --depth;
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1177,7 +1192,8 @@ gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for five-operand functions.  */
 
@@ -1192,16 +1208,13 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       *res_op = res_op2;
       return true;
     }
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1215,7 +1228,8 @@ gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for six-operand functions.  */
 
@@ -1230,16 +1244,13 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       *res_op = res_op2;
       return true;
     }
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
@@ -1253,7 +1264,8 @@ gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
 
 static bool
 gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
-		    tree (*valueize)(tree))
+		    tree (*valueize)(tree),
+		    gimple_match_simplify_fn simplifier)
 {
   /* No constant folding is defined for seven-operand functions.  */
 
@@ -1268,17 +1280,13 @@ 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]))
+  if (simplifier (&res_op2, seq, valueize))
     {
       *res_op = res_op2;
       return true;
     }
 
-  if (maybe_resimplify_conditional_op (seq, res_op, valueize))
+  if (maybe_resimplify_conditional_op (seq, res_op, valueize, simplifier))
     return true;
 
   return canonicalized;
diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h
index 8ff58e8cd7f27a1adc2fabf0f76ee940dea09199..5f6a48edfb5883a964537287e0675bfb273e3005 100644
--- a/gcc/gimple-match.h
+++ b/gcc/gimple-match.h
@@ -23,6 +23,12 @@ 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));
+
 /* 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.  */
@@ -112,7 +118,8 @@ public:
 
   tree op_or_null (unsigned int) const;
 
-  bool resimplify (gimple_seq *, tree (*)(tree));
+  bool resimplify (gimple_seq *, tree (*)(tree),
+		   gimple_match_simplify_fn = NULL);
 
   /* The maximum value of NUM_OPS.  */
   static const unsigned int MAX_NUM_OPS = 7;
@@ -408,7 +415,8 @@ extern tree (*mprts_hook) (gimple_match_op *);
 
 bool gimple_extract_op (gimple *, gimple_match_op *);
 bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *,
-		      tree (*)(tree), tree (*)(tree));
+		      tree (*)(tree), tree (*)(tree),
+		      gimple_match_simplify_fn = NULL);
 tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *,
 			    tree res = NULL_TREE);
 void maybe_build_generic_op (gimple_match_op *);

Reply via email to