This commits adds gimple-isel-match.pd which is a match.pd version that only
applies it's rewriting rules at gimple-isel time.  The normal match.pd rules
are also later applied.

The file is currently empty, but I have some patches to add vector comparisons
matching to this and I noticed a few cases already in isel that can be
simplified using the match.pd machinery.

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:

        * Makefile.in: Add entries for gimple-isel-match.pd
        * gimple-isel.cc (gimple_isel_simplify): Forward declare.
        (gimple_isel_match_stmt): New.
        (pass_gimple_isel::execute): Call it.
        * gimple-isel-match.pd: New file.

---
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 
536e2faaaf882d412bdb5bba649f184e672f2be5..f13972b9a5a01efefa5ae98d1eaab7138bf2c9f2
 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -228,6 +228,10 @@ GIMPLE_MATCH_PD_SEQ_O = $(patsubst %, gimple-match-%.o, 
$(MATCH_SPLITS_SEQ))
 GENERIC_MATCH_PD_SEQ_SRC = $(patsubst %, generic-match-%.cc, 
$(MATCH_SPLITS_SEQ))
 GENERIC_MATCH_PD_SEQ_O = $(patsubst %, generic-match-%.o, $(MATCH_SPLITS_SEQ))
 
+# The number of splits to be made for the gimple-isel-match.pd files.
+GIMPLE_ISEL_MATCH_PD_SEQ_SRC = $(patsubst %, gimple-isel-match-%.cc, 
$(MATCH_SPLITS_SEQ))
+GIMPLE_ISEL_MATCH_PD_SEQ_O = $(patsubst %, gimple-isel-match-%.o, 
$(MATCH_SPLITS_SEQ))
+
 # The number of splits to be made for the insn-emit files.
 NUM_INSNEMIT_SPLITS = @DEFAULT_INSNEMIT_PARTITIONS@
 INSNEMIT_SPLITS_SEQ = $(wordlist 1,$(NUM_INSNEMIT_SPLITS),$(one_to_9999))
@@ -1401,6 +1405,7 @@ ANALYZER_OBJS = \
 # the last objects to finish building.
 OBJS = \
        $(GIMPLE_MATCH_PD_SEQ_O) \
+       $(GIMPLE_ISEL_MATCH_PD_SEQ_O) \
        gimple-match-exports.o \
        $(GENERIC_MATCH_PD_SEQ_O) \
        insn-attrtab.o \
@@ -1988,7 +1993,8 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h 
insn-codes.h \
  insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \
  insn-latencytab.cc insn-opinit.cc insn-opinit.h insn-preds.cc 
insn-constants.h \
  tm-preds.h tm-constrs.h checksum-options $(GIMPLE_MATCH_PD_SEQ_SRC) \
- $(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \
+ $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
+ gimple-match-auto.h generic-match-auto.h \
  tree-check.h min-insn-modes.cc insn-modes.cc insn-modes.h insn-modes-inline.h 
\
  genrtl.h gt-*.h gtype-*.h gtype-desc.cc gtyp-input.list \
  case-cfn-macros.h cfn-operators.pd \
@@ -2763,6 +2769,7 @@ $(common_out_object_file): $(common_out_file)
   insn-extract.cc insn-output.cc \
   insn-peep.cc insn-attr.h insn-attr-common.h insn-attrtab.cc \
   insn-dfatab.cc insn-latencytab.cc insn-preds.cc \
+  $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC) \
   $(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
   gimple-match-auto.h generic-match-auto.h insn-target-def.h
 
@@ -3078,6 +3085,23 @@ s-generic-match: build/genmatch$(build_exeext) \
                                                generic-match-auto.h
        $(STAMP) s-generic-match
 
+# Add gimple-isel-match.pd
+$(GIMPLE_ISEL_MATCH_PD_SEQ_SRC): s-gimple-isel-match gimple-match-head.cc; 
@true
+gimple-isel-match-auto.h: s-gimple-isel-match; @true
+
+s-gimple-isel-match: build/genmatch$(build_exeext) \
+           $(srcdir)/gimple-isel-match.pd cfn-operators.pd
+       $(RUN_GEN) build/genmatch$(build_exeext) --gimple \
+           --header=tmp-gimple-isel-match-auto.h \
+           --include=gimple-isel-match-auto.h --namespace=isel \
+           $(srcdir)/gimple-isel-match.pd $(patsubst %, tmp-%, 
$(GIMPLE_ISEL_MATCH_PD_SEQ_SRC))
+       $(foreach id, $(MATCH_SPLITS_SEQ), \
+         $(SHELL) $(srcdir)/../move-if-change tmp-gimple-isel-match-$(id).cc \
+           gimple-isel-match-$(id).cc;)
+       $(SHELL) $(srcdir)/../move-if-change tmp-gimple-isel-match-auto.h \
+                                               gimple-isel-match-auto.h
+       $(STAMP) s-gimple-isel-match
+
 GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(host_xm_file_list) \
   $(OPTIONS_H_EXTRA) \
@@ -3217,6 +3241,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) 
$(TM_JIT_H) $(TM_H) \
        $(ALL_GTFILES_H) gtype-desc.cc gtype-desc.h version.h \
        options.h target-hooks-def.h insn-opinit.h \
        common/common-target-hooks-def.h pass-instances.def \
+       $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC) \
        $(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
        gimple-match-auto.h generic-match-auto.h \
        c-family/c-target-hooks-def.h d/d-target-hooks-def.h \
diff --git a/gcc/gimple-isel-match.pd b/gcc/gimple-isel-match.pd
new file mode 100644
index 
0000000000000000000000000000000000000000..9e2a2044ba5866389067cfff529b064d1885ea36
--- /dev/null
+++ b/gcc/gimple-isel-match.pd
@@ -0,0 +1,46 @@
+/* Match-and-simplify patterns for GIMPLE folding during instruction selection.
+   This file is consumed by genmatch which produces gimple-isel-match.cc.
+
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* Generic tree predicates we inherit.  */
+(define_predicates
+   integer_onep integer_zerop integer_all_onesp integer_minus_onep
+   integer_each_onep integer_truep integer_nonzerop
+   real_zerop real_onep real_minus_onep
+   zerop
+   initializer_each_zero_or_onep
+   CONSTANT_CLASS_P
+   poly_int_tree_p
+   tree_expr_nonnegative_p
+   tree_expr_nonzero_p
+   integer_valued_real_p
+   integer_pow2p
+   uniform_integer_cst_p
+   HONOR_NANS
+   uniform_vector_p
+   expand_vec_cmp_expr_p
+   bitmask_inv_cst_vector_p)
+
+/* Operator lists.  */
+(define_operator_list tcc_comparison
+  lt   le   eq ne ge   gt   unordered ordered   unlt unle ungt unge uneq ltgt)
+
+#include "cfn-operators.pd"
diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index 
b193e27b183e1a83d73369b629c81ea0d7db43cd..b834c05d65eab82b06e6b0be00b73d50384a734e
 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -40,6 +40,39 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "internal-fn.h"
 #include "fold-const.h"
+#include "gimple-match.h"
+
+extern bool gimple_isel_simplify (gimple_match_op *, gimple_seq *,
+                                 tree (*) (tree));
+
+/* Try to apply the instruction-selection-specific match.pd rules to *GSI.  */
+
+static bool
+gimple_isel_match_stmt (gimple_stmt_iterator *gsi)
+{
+  gimple *stmt = gsi_stmt (*gsi);
+  if (!gimple_has_lhs (stmt))
+    return false;
+
+  gimple_seq seq = NULL;
+  gimple_match_op res_op;
+  if (!gimple_simplify (stmt, &res_op, &seq, NULL, NULL,
+                       gimple_isel_simplify))
+    {
+      gimple_seq_discard (seq);
+      return false;
+    }
+
+  tree lhs = gimple_get_lhs (stmt);
+  if (!maybe_push_res_to_seq (&res_op, &seq, lhs))
+    {
+      gimple_seq_discard (seq);
+      return false;
+    }
+
+  gsi_replace_with_seq_vops (gsi, seq);
+  return true;
+}
 
 /* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to
    internal function based on vector type of selected expansion.
@@ -1360,6 +1393,9 @@ pass_gimple_isel::execute (struct function *fun)
          /* Give the target first try at replacing the instruction.  */
          cfg_changed |= targetm.instruction_selection (fun, &gsi);
 
+         /* Apply gimple-isel-match.pd patterns.  */
+         gimple_isel_match_stmt (&gsi);
+
          /* Pre-expand VEC_COND_EXPRs to .VCOND* internal function
             calls mapping to supported optabs.  */
          gimple *g = gimple_expand_vec_cond_expr (&gsi);
@@ -1400,4 +1436,3 @@ make_pass_gimple_isel (gcc::context *ctxt)
 {
   return new pass_gimple_isel (ctxt);
 }
-


-- 
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 536e2faaaf882d412bdb5bba649f184e672f2be5..f13972b9a5a01efefa5ae98d1eaab7138bf2c9f2 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -228,6 +228,10 @@ GIMPLE_MATCH_PD_SEQ_O = $(patsubst %, gimple-match-%.o, $(MATCH_SPLITS_SEQ))
 GENERIC_MATCH_PD_SEQ_SRC = $(patsubst %, generic-match-%.cc, $(MATCH_SPLITS_SEQ))
 GENERIC_MATCH_PD_SEQ_O = $(patsubst %, generic-match-%.o, $(MATCH_SPLITS_SEQ))
 
+# The number of splits to be made for the gimple-isel-match.pd files.
+GIMPLE_ISEL_MATCH_PD_SEQ_SRC = $(patsubst %, gimple-isel-match-%.cc, $(MATCH_SPLITS_SEQ))
+GIMPLE_ISEL_MATCH_PD_SEQ_O = $(patsubst %, gimple-isel-match-%.o, $(MATCH_SPLITS_SEQ))
+
 # The number of splits to be made for the insn-emit files.
 NUM_INSNEMIT_SPLITS = @DEFAULT_INSNEMIT_PARTITIONS@
 INSNEMIT_SPLITS_SEQ = $(wordlist 1,$(NUM_INSNEMIT_SPLITS),$(one_to_9999))
@@ -1401,6 +1405,7 @@ ANALYZER_OBJS = \
 # the last objects to finish building.
 OBJS = \
 	$(GIMPLE_MATCH_PD_SEQ_O) \
+	$(GIMPLE_ISEL_MATCH_PD_SEQ_O) \
 	gimple-match-exports.o \
 	$(GENERIC_MATCH_PD_SEQ_O) \
 	insn-attrtab.o \
@@ -1988,7 +1993,8 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
  insn-attr.h insn-attr-common.h insn-attrtab.cc insn-dfatab.cc \
  insn-latencytab.cc insn-opinit.cc insn-opinit.h insn-preds.cc insn-constants.h \
  tm-preds.h tm-constrs.h checksum-options $(GIMPLE_MATCH_PD_SEQ_SRC) \
- $(GENERIC_MATCH_PD_SEQ_SRC) gimple-match-auto.h generic-match-auto.h \
+ $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
+ gimple-match-auto.h generic-match-auto.h \
  tree-check.h min-insn-modes.cc insn-modes.cc insn-modes.h insn-modes-inline.h \
  genrtl.h gt-*.h gtype-*.h gtype-desc.cc gtyp-input.list \
  case-cfn-macros.h cfn-operators.pd \
@@ -2763,6 +2769,7 @@ $(common_out_object_file): $(common_out_file)
   insn-extract.cc insn-output.cc \
   insn-peep.cc insn-attr.h insn-attr-common.h insn-attrtab.cc \
   insn-dfatab.cc insn-latencytab.cc insn-preds.cc \
+  $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC) \
   $(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
   gimple-match-auto.h generic-match-auto.h insn-target-def.h
 
@@ -3078,6 +3085,23 @@ s-generic-match: build/genmatch$(build_exeext) \
 						generic-match-auto.h
 	$(STAMP) s-generic-match
 
+# Add gimple-isel-match.pd
+$(GIMPLE_ISEL_MATCH_PD_SEQ_SRC): s-gimple-isel-match gimple-match-head.cc; @true
+gimple-isel-match-auto.h: s-gimple-isel-match; @true
+
+s-gimple-isel-match: build/genmatch$(build_exeext) \
+	    $(srcdir)/gimple-isel-match.pd cfn-operators.pd
+	$(RUN_GEN) build/genmatch$(build_exeext) --gimple \
+	    --header=tmp-gimple-isel-match-auto.h \
+	    --include=gimple-isel-match-auto.h --namespace=isel \
+	    $(srcdir)/gimple-isel-match.pd $(patsubst %, tmp-%, $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC))
+	$(foreach id, $(MATCH_SPLITS_SEQ), \
+	  $(SHELL) $(srcdir)/../move-if-change tmp-gimple-isel-match-$(id).cc \
+	    gimple-isel-match-$(id).cc;)
+	$(SHELL) $(srcdir)/../move-if-change tmp-gimple-isel-match-auto.h \
+						gimple-isel-match-auto.h
+	$(STAMP) s-gimple-isel-match
+
 GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(host_xm_file_list) \
   $(OPTIONS_H_EXTRA) \
@@ -3217,6 +3241,7 @@ generated_files = config.h tm.h $(TM_P_H) $(TM_D_H) $(TM_JIT_H) $(TM_H) \
        $(ALL_GTFILES_H) gtype-desc.cc gtype-desc.h version.h \
        options.h target-hooks-def.h insn-opinit.h \
        common/common-target-hooks-def.h pass-instances.def \
+       $(GIMPLE_ISEL_MATCH_PD_SEQ_SRC) \
        $(GIMPLE_MATCH_PD_SEQ_SRC) $(GENERIC_MATCH_PD_SEQ_SRC) \
        gimple-match-auto.h generic-match-auto.h \
        c-family/c-target-hooks-def.h d/d-target-hooks-def.h \
diff --git a/gcc/gimple-isel-match.pd b/gcc/gimple-isel-match.pd
new file mode 100644
index 0000000000000000000000000000000000000000..9e2a2044ba5866389067cfff529b064d1885ea36
--- /dev/null
+++ b/gcc/gimple-isel-match.pd
@@ -0,0 +1,46 @@
+/* Match-and-simplify patterns for GIMPLE folding during instruction selection.
+   This file is consumed by genmatch which produces gimple-isel-match.cc.
+
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+/* Generic tree predicates we inherit.  */
+(define_predicates
+   integer_onep integer_zerop integer_all_onesp integer_minus_onep
+   integer_each_onep integer_truep integer_nonzerop
+   real_zerop real_onep real_minus_onep
+   zerop
+   initializer_each_zero_or_onep
+   CONSTANT_CLASS_P
+   poly_int_tree_p
+   tree_expr_nonnegative_p
+   tree_expr_nonzero_p
+   integer_valued_real_p
+   integer_pow2p
+   uniform_integer_cst_p
+   HONOR_NANS
+   uniform_vector_p
+   expand_vec_cmp_expr_p
+   bitmask_inv_cst_vector_p)
+
+/* Operator lists.  */
+(define_operator_list tcc_comparison
+  lt   le   eq ne ge   gt   unordered ordered   unlt unle ungt unge uneq ltgt)
+
+#include "cfn-operators.pd"
diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index b193e27b183e1a83d73369b629c81ea0d7db43cd..b834c05d65eab82b06e6b0be00b73d50384a734e 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -40,6 +40,39 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 #include "internal-fn.h"
 #include "fold-const.h"
+#include "gimple-match.h"
+
+extern bool gimple_isel_simplify (gimple_match_op *, gimple_seq *,
+				  tree (*) (tree));
+
+/* Try to apply the instruction-selection-specific match.pd rules to *GSI.  */
+
+static bool
+gimple_isel_match_stmt (gimple_stmt_iterator *gsi)
+{
+  gimple *stmt = gsi_stmt (*gsi);
+  if (!gimple_has_lhs (stmt))
+    return false;
+
+  gimple_seq seq = NULL;
+  gimple_match_op res_op;
+  if (!gimple_simplify (stmt, &res_op, &seq, NULL, NULL,
+			gimple_isel_simplify))
+    {
+      gimple_seq_discard (seq);
+      return false;
+    }
+
+  tree lhs = gimple_get_lhs (stmt);
+  if (!maybe_push_res_to_seq (&res_op, &seq, lhs))
+    {
+      gimple_seq_discard (seq);
+      return false;
+    }
+
+  gsi_replace_with_seq_vops (gsi, seq);
+  return true;
+}
 
 /* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to
    internal function based on vector type of selected expansion.
@@ -1360,6 +1393,9 @@ pass_gimple_isel::execute (struct function *fun)
 	  /* Give the target first try at replacing the instruction.  */
 	  cfg_changed |= targetm.instruction_selection (fun, &gsi);
 
+	  /* Apply gimple-isel-match.pd patterns.  */
+	  gimple_isel_match_stmt (&gsi);
+
 	  /* Pre-expand VEC_COND_EXPRs to .VCOND* internal function
 	     calls mapping to supported optabs.  */
 	  gimple *g = gimple_expand_vec_cond_expr (&gsi);
@@ -1400,4 +1436,3 @@ make_pass_gimple_isel (gcc::context *ctxt)
 {
   return new pass_gimple_isel (ctxt);
 }
-

Reply via email to