https://gcc.gnu.org/g:4756a4c0cfaeb18e7fff9108cd9c5d1e1e116690

commit r17-4221-g4756a4c0cfaeb18e7fff9108cd9c5d1e1e116690
Author: Kyrylo Tkachov <[email protected]>
Date:   Fri Aug 7 13:31:42 2026 +0200

    genrecog: write each .md condition out once
    
    The decision tree that genrecog builds tests a pattern's .md condition on
    every path that can accept that pattern, and the same condition guards
    many patterns.  So a condition is emitted once per decision that needs
    it, in full, inline.  On aarch64 that is 27344 emissions of 1059 distinct
    conditions, and `(TARGET_SVE)' alone accounts for 5269 of them.  Together
    with the #line directive that read-md.cc puts in front of each one, they
    are about a third of insn-recog-*.cc.
    
    Give each condition a helper function in the header that every partition
    already includes, and call it:
    
      static inline bool
      insn_condition_408 (rtx *operands ATTRIBUTE_UNUSED,
                       rtx_insn *insn ATTRIBUTE_UNUSED)
      {
        return
      #line 1172 ".../config/aarch64/aarch64-sve2.md"
      (TARGET_SVE2);
      }
    
    so that
    
        if (rtx_equal_p (x5, operands[2])
            &&
      #line 1172 ".../config/aarch64/aarch64-sve2.md"
      (TARGET_SVE2))
          return 13383; /* *cond_urshlvnx4si_2 */
    
    becomes
    
        if (rtx_equal_p (x5, operands[2])
            && insn_condition_408 (operands, insn))
          return 13383; /* *cond_urshlvnx4si_2 */
    
    The helpers take the operands and the insn because that is everything a
    condition may read, so no condition has to be classified and none is
    treated specially.  Nothing moves: each condition is still evaluated at
    exactly the decision that evaluated it before, so the change cannot alter
    what recog matches or in what order.  The helpers are inline, so the host
    compiler folds them back into their callers and the emitted code is the
    same as before.
    
    On aarch64, insn-recog-*.cc goes from 8994833 bytes in 292736 lines to
    6362888 bytes in 228402 lines, and compiles in 50% less time,
    with peak memory 387MB against 479MB.  cc1 itself drops from 533MB to
    512MB.
    
    Compiling a 39-file C corpus with -mcpu=generic, cortex-a57, cortex-a53,
    exynos-m1, tsv110, neoverse-v2 and neoverse-n1 gives identical
    assembly over all 273 compilations, and the built compiler takes the same
    time as before.
    
    Bootstrapped on aarch64-none-linux-gnu.
    
    gcc/ChangeLog:
    
            * genrecog.cc (md_conditions, md_condition_ids): New variables.
            (md_condition_id, print_md_conditions): New functions.
            (print_test): Call a helper for a C test rather than emitting the
            condition.
            (main): Write the helpers to the header.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>

Diff:
---
 gcc/genrecog.cc | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/gcc/genrecog.cc b/gcc/genrecog.cc
index 663620224abd..04fc23300185 100644
--- a/gcc/genrecog.cc
+++ b/gcc/genrecog.cc
@@ -113,6 +113,7 @@
 #include "errors.h"
 #include "read-md.h"
 #include "gensupport.h"
+#include "hash-map.h"
 
 #undef GENERATOR_FILE
 enum true_rtx_doe {
@@ -1788,6 +1789,54 @@ public:
   int peep2_count;
 };
 
+/* The distinct .md conditions, in the order they were first printed, and a
+   map from the condition text to that position.  A condition is written out
+   once as a helper function and called wherever it is needed, rather than
+   inlined at each of the decisions that test it.  */
+
+static auto_vec<const char *> md_conditions;
+static hash_map<nofree_string_hash, unsigned int> md_condition_ids;
+
+/* Return the index of COND's helper function, registering it if this is the
+   first time it has been seen.  */
+
+static unsigned int
+md_condition_id (const char *cond)
+{
+  bool existed;
+  unsigned int &id = md_condition_ids.get_or_insert (cond, &existed);
+  if (!existed)
+    {
+      id = md_conditions.length ();
+      md_conditions.safe_push (cond);
+    }
+  return id;
+}
+
+/* Write a helper function for each condition to F.  They go in the header,
+   which every generated file includes after the target headers, so that a
+   condition is compiled once however many decisions test it.
+
+   The helpers take the operands and the insn, which is everything a
+   condition may read, and are declared inline so that the host compiler can
+   fold them back into their callers.  */
+
+static void
+print_md_conditions (FILE *f)
+{
+  unsigned int i;
+  const char *cond;
+
+  FOR_EACH_VEC_ELT (md_conditions, i, cond)
+    {
+      fprintf (f, "\nstatic inline bool\ninsn_condition_%d "
+              "(rtx *operands ATTRIBUTE_UNUSED,\n"
+              "\t\t   rtx_insn *insn ATTRIBUTE_UNUSED)\n{\n  return ", i);
+      rtx_reader_ptr->print_c_condition (f, cond);
+      fprintf (f, ";\n}\n");
+    }
+}
+
 /* Return true if TEST can safely be performed at D, where
    the conditions in KC hold.  TEST is known to occur along the
    first path from D (i.e. always following the first transition
@@ -4762,10 +4811,13 @@ print_test (FILE *f, output_state *os, const rtx_test 
&test, bool is_param,
       break;
 
     case rtx_test::C_TEST:
+      /* Pattern routines take no insn, and pattern_c_test_p keeps C tests
+        out of them for that reason.  */
       gcc_assert (!is_param && value == 1);
       if (invert_p)
        fprintf (f, "!");
-      rtx_reader_ptr->print_c_condition (f, test.u.string);
+      fprintf (f, "insn_condition_%d (operands, insn)",
+              md_condition_id (test.u.string));
       break;
 
     case rtx_test::ACCEPT:
@@ -5533,6 +5585,9 @@ main (int argc, const char **argv)
   print_subroutine_group (output_files, header, &os, SPLIT, &split_root);
   print_subroutine_group (output_files, header, &os, PEEPHOLE2, 
&peephole2_root);
 
+  /* Every test has been printed, so the set of conditions is complete.  */
+  print_md_conditions (header);
+
   fclose (header);
 
   int ret = SUCCESS_EXIT_CODE;

Reply via email to