https://gcc.gnu.org/g:fa1ff9dba46c29992d443e1a22a6a4a21fa0c493

commit r17-5252-gfa1ff9dba46c29992d443e1a22a6a4a21fa0c493
Author: Kyrylo Tkachov <[email protected]>
Date:   Tue Oct 13 17:59:15 2026 +0200

    genattrtab: simplify attribute values once for insns with equal values
    
    optimize_attrs simplifies each COND-valued attribute for each insn
    code, using the values of the other attributes for that insn.  Many
    insn codes have the same alternatives and the same value for every
    attribute as an earlier insn code.  Since the previous patch the
    simplification depends only on those, so it gives the same result for
    each of them.
    
    Before the main loop, put the insn codes in a hash table keyed by the
    alternatives and the list of attribute values in insn_code_values.
    Only the first insn code with each key is simplified.  Each later insn
    code moves to the values that the first one got.  The insn entries are
    removed and inserted in the same order as before, so the generated code
    is the same.
    
    The generated files do not change for 52 target configurations.
    genattrtab instructions, with genattrtab built at -O2, relative to the
    previous patch: aarch64 -85.9%, riscv64 -60.2%, x86_64 -59.6%, arm
    -44.5%, s390x -38.9%.  Built at -g without optimization, aarch64 -91.6%.
    
    gcc/ChangeLog:
    
            * genattrtab.cc (struct insn_values_hasher): New hash traits.
            (optimize_attrs): Simplify the attribute values only for the
            first insn code of each set of insn codes with the same
            attribute values and alternatives.  Give the other insn codes
            the same values.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>

Diff:
---
 gcc/genattrtab.cc | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/gcc/genattrtab.cc b/gcc/genattrtab.cc
index db6ff529478e..e1afe09c9ebb 100644
--- a/gcc/genattrtab.cc
+++ b/gcc/genattrtab.cc
@@ -3150,6 +3150,45 @@ write_derived_attr_get (FILE *outf, class attr_desc 
*attr)
           attr->cxx_type, attr->name, y->name, y->name);
 }
 
+/* Hash traits for the lists in INSN_CODE_VALUES.  Two lists are equal if
+   their insns have the same alternatives and the same value for each
+   attribute.  */
+
+struct insn_values_hasher : nofree_ptr_hash <attr_value_list>
+{
+  static inline hashval_t hash (const attr_value_list *);
+  static inline bool equal (const attr_value_list *, const attr_value_list *);
+};
+
+/* Return the hash of the insn alternatives and attribute values in the
+   non-empty list LIST.  */
+
+inline hashval_t
+insn_values_hasher::hash (const attr_value_list *list)
+{
+  inchash::hash h;
+  h.add_object (insn_alternatives[list->ie->def->insn_code]);
+  for (; list; list = list->next)
+    h.add_ptr (list->av);
+  return h.end ();
+}
+
+/* Return true if the non-empty lists LIST1 and LIST2 belong to insns with
+   the same alternatives and have the same attribute values.  */
+
+inline bool
+insn_values_hasher::equal (const attr_value_list *list1,
+                          const attr_value_list *list2)
+{
+  if (insn_alternatives[list1->ie->def->insn_code]
+      != insn_alternatives[list2->ie->def->insn_code])
+    return false;
+  for (; list1 && list2; list1 = list1->next, list2 = list2->next)
+    if (list1->av != list2->av)
+      return false;
+  return !list1 && !list2;
+}
+
 /* Optimize the attribute lists by seeing if we can determine conditional
    values from the known values of other attributes.  This will save subroutine
    calls during the compilation.  NUM_INSN_CODES is the number of unique
@@ -3202,9 +3241,52 @@ optimize_attrs (int num_insn_codes)
   /* Sanity check on num_insn_ents.  */
   gcc_assert (iv == ivbuf + num_insn_ents);
 
+  /* Insns that have the same values for all attributes and the same
+     alternatives simplify in the same way.  Record for each insn code the
+     first insn code with the same values, before the loop below changes
+     them.  */
+  int *same_as = XNEWVEC (int, num_insn_codes);
+  {
+    hash_table<insn_values_hasher> values_table (num_insn_codes);
+    for (i = 0; i < num_insn_codes; i++)
+      {
+       same_as[i] = i;
+       if (insn_code_values[i])
+         {
+           attr_value_list **slot
+             = values_table.find_slot (insn_code_values[i], INSERT);
+           if (*slot)
+             same_as[i] = (*slot)->ie->def->insn_code;
+           else
+             *slot = insn_code_values[i];
+         }
+      }
+  }
+
   /* Process one insn code at a time.  */
   for (i = -2; i < num_insn_codes; i++)
     {
+      if (i >= 0 && same_as[i] != i)
+       {
+         /* Move the insn to the values chosen for the first insn with the
+            same values.  Both lists have the attributes in the same
+            order.  */
+         struct attr_value_list *first_iv = insn_code_values[same_as[i]];
+         for (iv = insn_code_values[i]; iv;
+              iv = iv->next, first_iv = first_iv->next)
+           {
+             gcc_checking_assert (iv->attr == first_iv->attr);
+             if (iv->av != first_iv->av)
+               {
+                 remove_insn_ent (iv->av, iv->ie);
+                 iv->av = first_iv->av;
+                 insert_insn_ent (iv->av, iv->ie);
+               }
+           }
+         gcc_checking_assert (!first_iv);
+         continue;
+       }
+
       /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere.
         We use it to mean "already simplified for this insn".  */
       clear_curr_simplified ();
@@ -3251,6 +3333,7 @@ optimize_attrs (int num_insn_codes)
     }
 
   clear_curr_simplified ();
+  free (same_as);
   free (ivbuf);
   free (insn_code_values - 2);
   insn_code_values = NULL;

Reply via email to