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;
