Skip to content

Commit ec860d1

Browse files
authored
[TableGen][DecoderEmitter] Refactor emitTableEntries (NFCI) (llvm#155100)
* Inline two small functions so that `emitTableEntries()` calls itself directly rather than through other functions. * Peel the last iteration of the loop as it is special. This should make the code easier to follow.
1 parent 4ce5506 commit ec860d1

File tree

1 file changed

+52
-98
lines changed

1 file changed

+52
-98
lines changed

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 52 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ class FilterChooser {
490490
/// If the selected filter matches multiple encodings, and there is
491491
/// *exactly one* encoding in which all bits are known in the filtered range,
492492
/// then this is the ID of that encoding.
493+
/// Also used when there is only one encoding.
493494
std::optional<unsigned> SingletonEncodingID;
494495

495496
/// If the selected filter matches multiple encodings, and there is
@@ -591,13 +592,6 @@ class FilterChooser {
591592
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
592593
unsigned EncodingID) const;
593594

594-
// Emits code to decode the singleton, and then to decode the rest.
595-
void emitSingletonTableEntry(DecoderTableInfo &TableInfo) const;
596-
597-
// Emit table entries to decode instructions given a segment or segments of
598-
// bits.
599-
void emitTableEntry(DecoderTableInfo &TableInfo) const;
600-
601595
void emitBinaryParser(raw_ostream &OS, indent Indent,
602596
const OperandInfo &OpInfo) const;
603597

@@ -624,8 +618,7 @@ class FilterChooser {
624618
void doFilter();
625619

626620
public:
627-
// emitTableEntries - Emit state machine entries to decode our share of
628-
// instructions.
621+
/// Emits state machine entries to decode our share of instructions.
629622
void emitTableEntries(DecoderTableInfo &TableInfo) const;
630623

631624
void dump() const;
@@ -700,70 +693,6 @@ void FilterChooser::applyFilter(const Filter &F) {
700693
}
701694
}
702695

703-
// Emit table entries to decode instructions given a segment or segments
704-
// of bits.
705-
void FilterChooser::emitTableEntry(DecoderTableInfo &TableInfo) const {
706-
assert(isUInt<8>(NumBits) && "NumBits overflowed uint8 table entry!");
707-
TableInfo.Table.push_back(MCD::OPC_ExtractField);
708-
709-
TableInfo.Table.insertULEB128(StartBit);
710-
TableInfo.Table.push_back(NumBits);
711-
712-
// If VariableFC is present, we need to add a new scope for this filter.
713-
// Otherwise, we can skip adding a new scope and any patching added will
714-
// automatically be added to the enclosing scope.
715-
const uint64_t LastFilter = FilterChooserMap.rbegin()->first;
716-
if (VariableFC)
717-
TableInfo.FixupStack.emplace_back();
718-
719-
DecoderTable &Table = TableInfo.Table;
720-
721-
size_t PrevFilter = 0;
722-
for (const auto &[FilterVal, Delegate] : FilterChooserMap) {
723-
// The last filtervalue emitted can be OPC_FilterValue if we are at
724-
// outermost scope.
725-
const uint8_t DecoderOp =
726-
FilterVal == LastFilter && TableInfo.isOutermostScope()
727-
? MCD::OPC_FilterValueOrFail
728-
: MCD::OPC_FilterValue;
729-
Table.push_back(DecoderOp);
730-
Table.insertULEB128(FilterVal);
731-
if (DecoderOp == MCD::OPC_FilterValue) {
732-
// Reserve space for the NumToSkip entry. We'll backpatch the value later.
733-
PrevFilter = Table.insertNumToSkip();
734-
} else {
735-
PrevFilter = 0;
736-
}
737-
738-
// We arrive at a category of instructions with the same segment value.
739-
// Now delegate to the sub filter chooser for further decodings.
740-
// The case may fallthrough, which happens if the remaining well-known
741-
// encoding bits do not match exactly.
742-
Delegate->emitTableEntries(TableInfo);
743-
744-
// Now that we've emitted the body of the handler, update the NumToSkip
745-
// of the filter itself to be able to skip forward when false.
746-
if (PrevFilter)
747-
Table.patchNumToSkip(PrevFilter, Table.size());
748-
}
749-
750-
if (VariableFC) {
751-
// Each scope should always have at least one filter value to check for.
752-
assert(PrevFilter != 0 && "empty filter set!");
753-
TableInfo.popScope();
754-
PrevFilter = 0; // Don't re-process the filter's fallthrough.
755-
756-
// Delegate to the sub filter chooser for further decoding.
757-
VariableFC->emitTableEntries(TableInfo);
758-
}
759-
760-
// If there is no fallthrough and the final filter was not in the outermost
761-
// scope, then it must be fixed up according to the enclosing scope rather
762-
// than the current position.
763-
if (PrevFilter)
764-
TableInfo.FixupStack.back().push_back(PrevFilter);
765-
}
766-
767696
// Returns the number of fanout produced by the filter. More fanout implies
768697
// the filter distinguishes more categories of instructions.
769698
unsigned Filter::usefulness() const {
@@ -1425,17 +1354,6 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14251354
}
14261355
}
14271356

1428-
// Emits table entries to decode the singleton, and then to decode the rest.
1429-
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo) const {
1430-
// complex singletons need predicate checks from the first singleton
1431-
// to refer forward to the variable filterchooser that follows.
1432-
TableInfo.pushScope();
1433-
emitSingletonTableEntry(TableInfo, *SingletonEncodingID);
1434-
TableInfo.popScope();
1435-
1436-
VariableFC->emitTableEntries(TableInfo);
1437-
}
1438-
14391357
// reportRegion is a helper function for filterProcessor to mark a region as
14401358
// eligible for use as a filter region.
14411359
void FilterChooser::reportRegion(std::vector<std::unique_ptr<Filter>> &Filters,
@@ -1694,8 +1612,10 @@ void FilterChooser::doFilter() {
16941612
assert(!EncodingIDs.empty() && "FilterChooser created with no instructions");
16951613

16961614
// No filter needed.
1697-
if (EncodingIDs.size() < 2)
1615+
if (EncodingIDs.size() == 1) {
1616+
SingletonEncodingID = EncodingIDs.front();
16981617
return;
1618+
}
16991619

17001620
std::unique_ptr<Filter> BestFilter = findBestFilter();
17011621
if (BestFilter) {
@@ -1726,22 +1646,56 @@ void FilterChooser::dump() const {
17261646
}
17271647
}
17281648

1729-
// emitTableEntries - Emit state machine entries to decode our share of
1730-
// instructions.
17311649
void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
1732-
if (EncodingIDs.size() == 1) {
1733-
// There is only one instruction in the set, which is great!
1734-
// Call emitSingletonDecoder() to see whether there are any remaining
1735-
// encodings bits.
1736-
emitSingletonTableEntry(TableInfo, EncodingIDs[0]);
1737-
return;
1650+
// If there are other encodings that could match if those with all bits
1651+
// known don't, enter a scope so that they have a chance.
1652+
if (VariableFC)
1653+
TableInfo.pushScope();
1654+
1655+
if (SingletonEncodingID) {
1656+
assert(FilterChooserMap.empty());
1657+
// There is only one encoding in which all bits in the filtered range are
1658+
// fully defined, but we still need to check if the remaining (unfiltered)
1659+
// bits are valid for this encoding. We also need to check predicates etc.
1660+
emitSingletonTableEntry(TableInfo, *SingletonEncodingID);
1661+
} else {
1662+
// The general case: emit a switch over the field value.
1663+
DecoderTable &Table = TableInfo.Table;
1664+
Table.push_back(MCD::OPC_ExtractField);
1665+
Table.insertULEB128(StartBit);
1666+
assert(isUInt<8>(NumBits) && "NumBits overflowed uint8 table entry!");
1667+
Table.push_back(NumBits);
1668+
1669+
// Emit switch cases for all but the last element.
1670+
for (const auto &[FilterVal, Delegate] : drop_end(FilterChooserMap)) {
1671+
Table.push_back(MCD::OPC_FilterValue);
1672+
Table.insertULEB128(FilterVal);
1673+
size_t FixupPos = Table.insertNumToSkip();
1674+
1675+
// Emit table entries for this case.
1676+
Delegate->emitTableEntries(TableInfo);
1677+
1678+
// Patch the previous OPC_FilterValue to fall through to the next case.
1679+
Table.patchNumToSkip(FixupPos, Table.size());
1680+
}
1681+
1682+
// Emit a switch case for the last element. It never falls through;
1683+
// if it doesn't match, we leave the current scope.
1684+
const auto &[FilterVal, Delegate] = *FilterChooserMap.rbegin();
1685+
Table.push_back(!TableInfo.isOutermostScope() ? MCD::OPC_FilterValue
1686+
: MCD::OPC_FilterValueOrFail);
1687+
Table.insertULEB128(FilterVal);
1688+
if (!TableInfo.isOutermostScope())
1689+
TableInfo.FixupStack.back().push_back(Table.insertNumToSkip());
1690+
1691+
// Emit table entries for the last case.
1692+
Delegate->emitTableEntries(TableInfo);
17381693
}
17391694

1740-
// Use the best filter to do the decoding!
1741-
if (SingletonEncodingID)
1742-
emitSingletonTableEntry(TableInfo);
1743-
else
1744-
emitTableEntry(TableInfo);
1695+
if (VariableFC) {
1696+
TableInfo.popScope();
1697+
VariableFC->emitTableEntries(TableInfo);
1698+
}
17451699
}
17461700

17471701
static std::string findOperandDecoderMethod(const Record *Record) {

0 commit comments

Comments
 (0)