[llvm] [TableGen][DecoderEmitter] Avoid using a sentinel value (PR #153986)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Sat Aug 16 17:29:29 PDT 2025
https://github.com/s-barannikov created https://github.com/llvm/llvm-project/pull/153986
`NO_FIXED_SEGMENTS_SENTINEL` has a value that is actually a valid field encoding and so it cannot be used as a sentinel.
Replace the sentinel with a new member variable, `VariableFC`, that contains the value previously stored in `FilterChooserMap` with `NO_FIXED_SEGMENTS_SENTINEL` key.
>From 3ea4400ca4fa38fdeae810d0265206eb6cdd93a0 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 17 Aug 2025 03:29:00 +0300
Subject: [PATCH] [TableGen][DecoderEmitter] Avoid using a sentinel value
`NO_FIXED_SEGMENTS_SENTINEL` has a value that is actually a valid field
encoding and so it cannot be used as a sentinel.
Replace the sentinel with a new member variable, `VariableFC`, that
contains the value previously stored in `FilterChooserMap` with
`NO_FIXED_SEGMENTS_SENTINEL` key.
---
llvm/utils/TableGen/DecoderEmitter.cpp | 82 ++++++++++++--------------
1 file changed, 39 insertions(+), 43 deletions(-)
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index b22c60a00081d..ca0145d37c080 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -339,9 +339,6 @@ typedef std::vector<BitValue> insn_t;
namespace {
-static constexpr uint64_t NO_FIXED_SEGMENTS_SENTINEL =
- std::numeric_limits<uint64_t>::max();
-
class FilterChooser;
/// Filter - Filter works with FilterChooser to produce the decoding tree for
@@ -395,6 +392,9 @@ class Filter {
// Map of well-known segment value to its delegate.
std::map<uint64_t, std::unique_ptr<const FilterChooser>> FilterChooserMap;
+ // A filter chooser for encodings that contain some '?' in the filtered range.
+ std::unique_ptr<const FilterChooser> VariableFC;
+
// Number of instructions which fall under FilteredInstructions category.
unsigned NumFiltered;
@@ -417,8 +417,8 @@ class Filter {
// Return the filter chooser for the group of instructions without constant
// segment values.
const FilterChooser &getVariableFC() const {
- assert(NumFiltered == 1 && FilterChooserMap.size() == 1);
- return *(FilterChooserMap.find(NO_FIXED_SEGMENTS_SENTINEL)->second);
+ assert(NumFiltered == 1 && FilterChooserMap.empty());
+ return *VariableFC;
}
// Divides the decoding task into sub tasks and delegates them to the
@@ -650,7 +650,8 @@ Filter::Filter(Filter &&f)
FilteredInstructions(std::move(f.FilteredInstructions)),
VariableInstructions(std::move(f.VariableInstructions)),
FilterChooserMap(std::move(f.FilterChooserMap)),
- NumFiltered(f.NumFiltered), LastOpcFiltered(f.LastOpcFiltered) {}
+ VariableFC(std::move(f.VariableFC)), NumFiltered(f.NumFiltered),
+ LastOpcFiltered(f.LastOpcFiltered) {}
Filter::Filter(const FilterChooser &owner, unsigned startBit, unsigned numBits)
: Owner(owner), StartBit(startBit), NumBits(numBits) {
@@ -700,17 +701,15 @@ void Filter::recurse() {
// Delegates to an inferior filter chooser for further processing on this
// group of instructions whose segment values are variable.
- FilterChooserMap.try_emplace(
- NO_FIXED_SEGMENTS_SENTINEL,
- std::make_unique<FilterChooser>(Owner.AllInstructions,
- VariableInstructions, Owner.Operands,
- BitValueArray, Owner));
+ VariableFC = std::make_unique<FilterChooser>(
+ Owner.AllInstructions, VariableInstructions, Owner.Operands,
+ BitValueArray, Owner);
}
// No need to recurse for a singleton filtered instruction.
// See also Filter::emit*().
if (getNumFiltered() == 1) {
- assert(FilterChooserMap.size() == 1);
+ assert(VariableFC && "Shouldn't have created Filter for one encoding");
return;
}
@@ -756,44 +755,26 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
// FilterChooserMap.
const uint64_t LastFilter = FilterChooserMap.rbegin()->first;
- bool HasFallthrough = LastFilter == NO_FIXED_SEGMENTS_SENTINEL;
- if (HasFallthrough)
+ if (VariableFC)
TableInfo.FixupStack.emplace_back();
DecoderTable &Table = TableInfo.Table;
size_t PrevFilter = 0;
for (const auto &[FilterVal, Delegate] : FilterChooserMap) {
- // Field value NO_FIXED_SEGMENTS_SENTINEL implies a non-empty set of
- // variable instructions. See also recurse().
- if (FilterVal == NO_FIXED_SEGMENTS_SENTINEL) {
- // Each scope should always have at least one filter value to check
- // for.
- assert(PrevFilter != 0 && "empty filter set!");
- FixupList &CurScope = TableInfo.FixupStack.back();
- // Resolve any NumToSkip fixups in the current scope.
- resolveTableFixups(Table, CurScope, Table.size());
-
- // Delete the scope we have added here.
- TableInfo.FixupStack.pop_back();
-
- PrevFilter = 0; // Don't re-process the filter's fallthrough.
+ // The last filtervalue emitted can be OPC_FilterValue if we are at
+ // outermost scope.
+ const uint8_t DecoderOp =
+ FilterVal == LastFilter && TableInfo.isOutermostScope()
+ ? MCD::OPC_FilterValueOrFail
+ : MCD::OPC_FilterValue;
+ Table.push_back(DecoderOp);
+ Table.insertULEB128(FilterVal);
+ if (DecoderOp == MCD::OPC_FilterValue) {
+ // Reserve space for the NumToSkip entry. We'll backpatch the value later.
+ PrevFilter = Table.insertNumToSkip();
} else {
- // The last filtervalue emitted can be OPC_FilterValue if we are at
- // outermost scope.
- const uint8_t DecoderOp =
- FilterVal == LastFilter && TableInfo.isOutermostScope()
- ? MCD::OPC_FilterValueOrFail
- : MCD::OPC_FilterValue;
- Table.push_back(DecoderOp);
- Table.insertULEB128(FilterVal);
- if (DecoderOp == MCD::OPC_FilterValue) {
- // Reserve space for the NumToSkip entry. We'll backpatch the value
- // later.
- PrevFilter = Table.insertNumToSkip();
- } else {
- PrevFilter = 0;
- }
+ PrevFilter = 0;
}
// We arrive at a category of instructions with the same segment value.
@@ -808,6 +789,21 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
Table.patchNumToSkip(PrevFilter, Table.size());
}
+ if (VariableFC) {
+ // Each scope should always have at least one filter value to check for.
+ assert(PrevFilter != 0 && "empty filter set!");
+ // Resolve any NumToSkip fixups in the current scope.
+ resolveTableFixups(Table, TableInfo.FixupStack.back(), Table.size());
+
+ // Delete the scope we have added here.
+ TableInfo.FixupStack.pop_back();
+
+ PrevFilter = 0; // Don't re-process the filter's fallthrough.
+
+ // Delegate to the sub filter chooser for further decoding.
+ VariableFC->emitTableEntries(TableInfo);
+ }
+
// If there is no fallthrough and the final filter was not in the outermost
// scope, then it must be fixed up according to the enclosing scope rather
// than the current position.
More information about the llvm-commits
mailing list