[llvm] [TableGen][DecoderEmitter] Compute bit attribute once (NFC) (PR #153530)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 13 20:32:45 PDT 2025
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/153530
>From 0e0ae58cab2ff69a9f6d90da42be5191ef94a03b Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Thu, 14 Aug 2025 06:18:02 +0300
Subject: [PATCH] [TableGen][DecoderEmitter] Compute bit attribute once (NFC)
Pull the logic to compute bit attributes from `filterProcessor()`
to its caller to avoid recomputing them on the second call.
---
llvm/utils/TableGen/DecoderEmitter.cpp | 130 +++++++++++++------------
1 file changed, 66 insertions(+), 64 deletions(-)
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 997f9a585d3ad..59ad70d1a7002 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -623,7 +623,8 @@ class FilterChooser {
// FilterProcessor scans the well-known encoding bits of the instructions and
// builds up a list of candidate filters. It chooses the best filter and
// recursively descends down the decoding tree.
- bool filterProcessor(bool AllowMixed, bool Greedy = true);
+ bool filterProcessor(ArrayRef<bitAttr_t> BitAttrs, bool AllowMixed,
+ bool Greedy = true);
// Decides on the best configuration of filter(s) to use in order to decode
// the instructions. A conflict of instructions may occur, in which case we
@@ -1550,21 +1551,17 @@ void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
// FilterProcessor scans the well-known encoding bits of the instructions and
// builds up a list of candidate filters. It chooses the best filter and
// recursively descends down the decoding tree.
-bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
+bool FilterChooser::filterProcessor(ArrayRef<bitAttr_t> BitAttrs,
+ bool AllowMixed, bool Greedy) {
Filters.clear();
BestIndex = -1;
- unsigned numInstructions = Opcodes.size();
- assert(numInstructions && "Filter created with no instructions");
-
- // No further filtering is necessary.
- if (numInstructions == 1)
- return true;
+ assert(Opcodes.size() >= 2 && "Nothing to filter");
// Heuristics. See also doFilter()'s "Heuristics" comment when num of
// instructions is 3.
if (AllowMixed && !Greedy) {
- assert(numInstructions == 3);
+ assert(Opcodes.size() == 3);
for (const auto &Opcode : Opcodes) {
insn_t Insn = insnWithID(Opcode.EncodingID);
@@ -1579,57 +1576,6 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
}
}
- // We maintain BIT_WIDTH copies of the bitAttrs automaton.
- // The automaton consumes the corresponding bit from each
- // instruction.
- //
- // Input symbols: 0, 1, and _ (unset).
- // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED.
- // Initial state: NONE.
- //
- // (NONE) ------- [01] -> (ALL_SET)
- // (NONE) ------- _ ----> (ALL_UNSET)
- // (ALL_SET) ---- [01] -> (ALL_SET)
- // (ALL_SET) ---- _ ----> (MIXED)
- // (ALL_UNSET) -- [01] -> (MIXED)
- // (ALL_UNSET) -- _ ----> (ALL_UNSET)
- // (MIXED) ------ . ----> (MIXED)
- // (FILTERED)---- . ----> (FILTERED)
-
- std::vector<bitAttr_t> bitAttrs(BitWidth, ATTR_NONE);
-
- // FILTERED bit positions provide no entropy and are not worthy of pursuing.
- // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
- for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
- if (FilterBitValues[BitIndex].isSet())
- bitAttrs[BitIndex] = ATTR_FILTERED;
-
- for (const auto &OpcPair : Opcodes) {
- insn_t insn = insnWithID(OpcPair.EncodingID);
-
- for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
- switch (bitAttrs[BitIndex]) {
- case ATTR_NONE:
- if (insn[BitIndex] == BitValue::BIT_UNSET)
- bitAttrs[BitIndex] = ATTR_ALL_UNSET;
- else
- bitAttrs[BitIndex] = ATTR_ALL_SET;
- break;
- case ATTR_ALL_SET:
- if (insn[BitIndex] == BitValue::BIT_UNSET)
- bitAttrs[BitIndex] = ATTR_MIXED;
- break;
- case ATTR_ALL_UNSET:
- if (insn[BitIndex] != BitValue::BIT_UNSET)
- bitAttrs[BitIndex] = ATTR_MIXED;
- break;
- case ATTR_MIXED:
- case ATTR_FILTERED:
- break;
- }
- }
- }
-
// The regionAttr automaton consumes the bitAttrs automatons' state,
// lowest-to-highest.
//
@@ -1654,7 +1600,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
unsigned StartBit = 0;
for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
- bitAttr_t bitAttr = bitAttrs[BitIndex];
+ bitAttr_t bitAttr = BitAttrs[BitIndex];
assert(bitAttr != ATTR_NONE && "Bit without attributes");
@@ -1774,19 +1720,75 @@ void FilterChooser::doFilter() {
unsigned Num = Opcodes.size();
assert(Num && "FilterChooser created with no instructions");
+ // No filter needed.
+ if (Opcodes.size() < 2)
+ return;
+
+ // We maintain BIT_WIDTH copies of the bitAttrs automaton.
+ // The automaton consumes the corresponding bit from each
+ // instruction.
+ //
+ // Input symbols: 0, 1, _ (unset), and . (any of the above).
+ // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED.
+ // Initial state: NONE.
+ //
+ // (NONE) ------- [01] -> (ALL_SET)
+ // (NONE) ------- _ ----> (ALL_UNSET)
+ // (ALL_SET) ---- [01] -> (ALL_SET)
+ // (ALL_SET) ---- _ ----> (MIXED)
+ // (ALL_UNSET) -- [01] -> (MIXED)
+ // (ALL_UNSET) -- _ ----> (ALL_UNSET)
+ // (MIXED) ------ . ----> (MIXED)
+ // (FILTERED)---- . ----> (FILTERED)
+
+ SmallVector<bitAttr_t, 128> BitAttrs(BitWidth, ATTR_NONE);
+
+ // FILTERED bit positions provide no entropy and are not worthy of pursuing.
+ // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
+ for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
+ if (FilterBitValues[BitIndex].isSet())
+ BitAttrs[BitIndex] = ATTR_FILTERED;
+
+ for (const EncodingIDAndOpcode &OpcPair : Opcodes) {
+ insn_t EncodingBits = insnWithID(OpcPair.EncodingID);
+
+ for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
+ switch (BitAttrs[BitIndex]) {
+ case ATTR_NONE:
+ if (EncodingBits[BitIndex] == BitValue::BIT_UNSET)
+ BitAttrs[BitIndex] = ATTR_ALL_UNSET;
+ else
+ BitAttrs[BitIndex] = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_SET:
+ if (EncodingBits[BitIndex] == BitValue::BIT_UNSET)
+ BitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_ALL_UNSET:
+ if (EncodingBits[BitIndex] != BitValue::BIT_UNSET)
+ BitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_MIXED:
+ case ATTR_FILTERED:
+ break;
+ }
+ }
+ }
+
// Try regions of consecutive known bit values first.
- if (filterProcessor(false))
+ if (filterProcessor(BitAttrs, /*AllowMixed=*/false))
return;
// Then regions of mixed bits (both known and unitialized bit values allowed).
- if (filterProcessor(true))
+ if (filterProcessor(BitAttrs, /*AllowMixed=*/true))
return;
// Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where
// no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a
// well-known encoding pattern. In such case, we backtrack and scan for the
// the very first consecutive ATTR_ALL_SET region and assign a filter to it.
- if (Num == 3 && filterProcessor(true, false))
+ if (Num == 3 &&
+ filterProcessor(BitAttrs, /*AllowMixed=*/true, /*Greedy=*/false))
return;
// If we come to here, the instruction decoding has failed.
More information about the llvm-commits
mailing list