Skip to content

Commit e49946b

Browse files
authored
[TableGen][DecoderEmitter] Factor out DecoderTableBuilder (#155220)
Extract the table building methods from FilterChooser into a separate class to relieve it of one of its responsibilities.
1 parent 3134e69 commit e49946b

File tree

1 file changed

+84
-67
lines changed

1 file changed

+84
-67
lines changed

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 84 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ enum bitAttr_t {
466466
/// decide what further remaining bits to look at.
467467

468468
class FilterChooser {
469+
// TODO: Unfriend by providing the necessary accessors.
470+
friend class DecoderTableBuilder;
471+
469472
// Vector of encodings to choose our filter.
470473
ArrayRef<InstructionEncoding> Encodings;
471474

@@ -578,30 +581,6 @@ class FilterChooser {
578581
// decoded bits in order to verify that the instruction matches the Opcode.
579582
std::vector<Island> getIslands(const KnownBits &EncodingBits) const;
580583

581-
// Emits code to check the Predicates member of an instruction are true.
582-
// Returns true if predicate matches were emitted, false otherwise.
583-
bool emitPredicateMatch(raw_ostream &OS, unsigned EncodingID) const;
584-
bool emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp,
585-
raw_ostream &OS) const;
586-
587-
bool doesOpcodeNeedPredicate(unsigned EncodingID) const;
588-
unsigned getPredicateIndex(DecoderTableInfo &TableInfo, StringRef P) const;
589-
void emitPredicateTableEntry(DecoderTableInfo &TableInfo,
590-
unsigned EncodingID) const;
591-
592-
void emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
593-
unsigned EncodingID) const;
594-
595-
// Emits table entries to decode the singleton.
596-
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
597-
unsigned EncodingID) const;
598-
599-
void emitBinaryParser(raw_ostream &OS, indent Indent,
600-
const OperandInfo &OpInfo) const;
601-
602-
void emitDecoder(raw_ostream &OS, indent Indent, unsigned EncodingID) const;
603-
unsigned getDecoderIndex(DecoderSet &Decoders, unsigned EncodingID) const;
604-
605584
// reportRegion is a helper function for filterProcessor to mark a region as
606585
// eligible for use as a filter region.
607586
void reportRegion(std::vector<std::unique_ptr<Filter>> &Filters, bitAttr_t RA,
@@ -622,12 +601,51 @@ class FilterChooser {
622601
void doFilter();
623602

624603
public:
625-
/// Emits state machine entries to decode our share of instructions.
626-
void emitTableEntries(DecoderTableInfo &TableInfo) const;
627-
628604
void dump() const;
629605
};
630606

607+
class DecoderTableBuilder {
608+
const CodeGenTarget &Target;
609+
ArrayRef<InstructionEncoding> Encodings;
610+
DecoderTableInfo &TableInfo;
611+
612+
public:
613+
DecoderTableBuilder(const CodeGenTarget &Target,
614+
ArrayRef<InstructionEncoding> Encodings,
615+
DecoderTableInfo &TableInfo)
616+
: Target(Target), Encodings(Encodings), TableInfo(TableInfo) {}
617+
618+
void buildTable(const FilterChooser &FC) const {
619+
emitTableEntries(FC);
620+
assert(TableInfo.FixupStack.empty() && "Fixup stack phasing error!");
621+
}
622+
623+
private:
624+
void emitBinaryParser(raw_ostream &OS, indent Indent,
625+
const OperandInfo &OpInfo) const;
626+
627+
void emitDecoder(raw_ostream &OS, indent Indent, unsigned EncodingID) const;
628+
629+
unsigned getDecoderIndex(unsigned EncodingID) const;
630+
631+
unsigned getPredicateIndex(StringRef P) const;
632+
633+
bool emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp,
634+
raw_ostream &OS) const;
635+
636+
bool emitPredicateMatch(raw_ostream &OS, unsigned EncodingID) const;
637+
638+
bool doesOpcodeNeedPredicate(unsigned EncodingID) const;
639+
640+
void emitPredicateTableEntry(unsigned EncodingID) const;
641+
642+
void emitSoftFailTableEntry(unsigned EncodingID) const;
643+
644+
void emitSingletonTableEntry(const FilterChooser &FC) const;
645+
646+
void emitTableEntries(const FilterChooser &FC) const;
647+
};
648+
631649
} // end anonymous namespace
632650

633651
///////////////////////////
@@ -1062,8 +1080,8 @@ FilterChooser::getIslands(const KnownBits &EncodingBits) const {
10621080
return Islands;
10631081
}
10641082

1065-
void FilterChooser::emitBinaryParser(raw_ostream &OS, indent Indent,
1066-
const OperandInfo &OpInfo) const {
1083+
void DecoderTableBuilder::emitBinaryParser(raw_ostream &OS, indent Indent,
1084+
const OperandInfo &OpInfo) const {
10671085
const std::string &Decoder = OpInfo.Decoder;
10681086

10691087
bool UseInsertBits = OpInfo.numFields() != 1 || OpInfo.InitValue != 0;
@@ -1098,8 +1116,8 @@ void FilterChooser::emitBinaryParser(raw_ostream &OS, indent Indent,
10981116
}
10991117
}
11001118

1101-
void FilterChooser::emitDecoder(raw_ostream &OS, indent Indent,
1102-
unsigned EncodingID) const {
1119+
void DecoderTableBuilder::emitDecoder(raw_ostream &OS, indent Indent,
1120+
unsigned EncodingID) const {
11031121
const InstructionEncoding &Encoding = Encodings[EncodingID];
11041122

11051123
// If a custom instruction decoder was specified, use that.
@@ -1117,8 +1135,7 @@ void FilterChooser::emitDecoder(raw_ostream &OS, indent Indent,
11171135
emitBinaryParser(OS, Indent, Op);
11181136
}
11191137

1120-
unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
1121-
unsigned EncodingID) const {
1138+
unsigned DecoderTableBuilder::getDecoderIndex(unsigned EncodingID) const {
11221139
// Build up the predicate string.
11231140
SmallString<256> Decoder;
11241141
// FIXME: emitDecoder() function can take a buffer directly rather than
@@ -1134,15 +1151,17 @@ unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
11341151
// overkill for now, though.
11351152

11361153
// Make sure the predicate is in the table.
1154+
DecoderSet &Decoders = TableInfo.Decoders;
11371155
Decoders.insert(CachedHashString(Decoder));
11381156
// Now figure out the index for when we write out the table.
11391157
DecoderSet::const_iterator P = find(Decoders, Decoder.str());
11401158
return std::distance(Decoders.begin(), P);
11411159
}
11421160

11431161
// If ParenIfBinOp is true, print a surrounding () if Val uses && or ||.
1144-
bool FilterChooser::emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp,
1145-
raw_ostream &OS) const {
1162+
bool DecoderTableBuilder::emitPredicateMatchAux(const Init &Val,
1163+
bool ParenIfBinOp,
1164+
raw_ostream &OS) const {
11461165
if (const auto *D = dyn_cast<DefInit>(&Val)) {
11471166
if (!D->getDef()->isSubClassOf("SubtargetFeature"))
11481167
return true;
@@ -1173,8 +1192,8 @@ bool FilterChooser::emitPredicateMatchAux(const Init &Val, bool ParenIfBinOp,
11731192
return true;
11741193
}
11751194

1176-
bool FilterChooser::emitPredicateMatch(raw_ostream &OS,
1177-
unsigned EncodingID) const {
1195+
bool DecoderTableBuilder::emitPredicateMatch(raw_ostream &OS,
1196+
unsigned EncodingID) const {
11781197
const ListInit *Predicates =
11791198
Encodings[EncodingID].getRecord()->getValueAsListInit("Predicates");
11801199
bool IsFirstEmission = true;
@@ -1196,7 +1215,7 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &OS,
11961215
return !Predicates->empty();
11971216
}
11981217

1199-
bool FilterChooser::doesOpcodeNeedPredicate(unsigned EncodingID) const {
1218+
bool DecoderTableBuilder::doesOpcodeNeedPredicate(unsigned EncodingID) const {
12001219
const ListInit *Predicates =
12011220
Encodings[EncodingID].getRecord()->getValueAsListInit("Predicates");
12021221
for (unsigned i = 0; i < Predicates->size(); ++i) {
@@ -1210,8 +1229,7 @@ bool FilterChooser::doesOpcodeNeedPredicate(unsigned EncodingID) const {
12101229
return false;
12111230
}
12121231

1213-
unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo,
1214-
StringRef Predicate) const {
1232+
unsigned DecoderTableBuilder::getPredicateIndex(StringRef Predicate) const {
12151233
// Using the full predicate string as the key value here is a bit
12161234
// heavyweight, but is effective. If the string comparisons become a
12171235
// performance concern, we can implement a mangling of the predicate
@@ -1225,8 +1243,7 @@ unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo,
12251243
return (unsigned)(P - TableInfo.Predicates.begin());
12261244
}
12271245

1228-
void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
1229-
unsigned EncodingID) const {
1246+
void DecoderTableBuilder::emitPredicateTableEntry(unsigned EncodingID) const {
12301247
if (!doesOpcodeNeedPredicate(EncodingID))
12311248
return;
12321249

@@ -1239,7 +1256,7 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
12391256

12401257
// Figure out the index into the predicate table for the predicate just
12411258
// computed.
1242-
unsigned PIdx = getPredicateIndex(TableInfo, PS.str());
1259+
unsigned PIdx = getPredicateIndex(PS.str());
12431260

12441261
const MCD::DecoderOps DecoderOp = TableInfo.isOutermostScope()
12451262
? MCD::OPC_CheckPredicateOrFail
@@ -1253,8 +1270,7 @@ void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
12531270
}
12541271
}
12551272

1256-
void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
1257-
unsigned EncodingID) const {
1273+
void DecoderTableBuilder::emitSoftFailTableEntry(unsigned EncodingID) const {
12581274
const InstructionEncoding &Encoding = Encodings[EncodingID];
12591275
const KnownBits &InstBits = Encoding.getInstBits();
12601276
const APInt &SFBits = Encoding.getSoftFailBits();
@@ -1290,19 +1306,20 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
12901306
}
12911307

12921308
// Emits table entries to decode the singleton.
1293-
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
1294-
unsigned EncodingID) const {
1309+
void DecoderTableBuilder::emitSingletonTableEntry(
1310+
const FilterChooser &FC) const {
1311+
unsigned EncodingID = *FC.SingletonEncodingID;
12951312
const InstructionEncoding &Encoding = Encodings[EncodingID];
12961313
KnownBits EncodingBits = Encoding.getMandatoryBits();
12971314

12981315
// Look for islands of undecoded bits of the singleton.
1299-
std::vector<Island> Islands = getIslands(EncodingBits);
1316+
std::vector<FilterChooser::Island> Islands = FC.getIslands(EncodingBits);
13001317

13011318
// Emit the predicate table entry if one is needed.
1302-
emitPredicateTableEntry(TableInfo, EncodingID);
1319+
emitPredicateTableEntry(EncodingID);
13031320

13041321
// Check any additional encoding fields needed.
1305-
for (const Island &Ilnd : reverse(Islands)) {
1322+
for (const FilterChooser::Island &Ilnd : reverse(Islands)) {
13061323
const MCD::DecoderOps DecoderOp = TableInfo.isOutermostScope()
13071324
? MCD::OPC_CheckFieldOrFail
13081325
: MCD::OPC_CheckField;
@@ -1321,9 +1338,9 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
13211338
}
13221339

13231340
// Check for soft failure of the match.
1324-
emitSoftFailTableEntry(TableInfo, EncodingID);
1341+
emitSoftFailTableEntry(EncodingID);
13251342

1326-
unsigned DIdx = getDecoderIndex(TableInfo.Decoders, EncodingID);
1343+
unsigned DIdx = getDecoderIndex(EncodingID);
13271344

13281345
// Produce OPC_Decode or OPC_TryDecode opcode based on the information
13291346
// whether the instruction decoder is complete or not. If it is complete
@@ -1641,41 +1658,41 @@ void FilterChooser::dump() const {
16411658
}
16421659
}
16431660

1644-
void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
1661+
void DecoderTableBuilder::emitTableEntries(const FilterChooser &FC) const {
16451662
// If there are other encodings that could match if those with all bits
16461663
// known don't, enter a scope so that they have a chance.
1647-
if (VariableFC)
1664+
if (FC.VariableFC)
16481665
TableInfo.pushScope();
16491666

1650-
if (SingletonEncodingID) {
1651-
assert(FilterChooserMap.empty());
1667+
if (FC.SingletonEncodingID) {
1668+
assert(FC.FilterChooserMap.empty());
16521669
// There is only one encoding in which all bits in the filtered range are
16531670
// fully defined, but we still need to check if the remaining (unfiltered)
16541671
// bits are valid for this encoding. We also need to check predicates etc.
1655-
emitSingletonTableEntry(TableInfo, *SingletonEncodingID);
1672+
emitSingletonTableEntry(FC);
16561673
} else {
16571674
// The general case: emit a switch over the field value.
16581675
DecoderTable &Table = TableInfo.Table;
16591676
Table.insertOpcode(MCD::OPC_ExtractField);
1660-
Table.insertULEB128(StartBit);
1661-
Table.insertUInt8(NumBits);
1677+
Table.insertULEB128(FC.StartBit);
1678+
Table.insertUInt8(FC.NumBits);
16621679

16631680
// Emit switch cases for all but the last element.
1664-
for (const auto &[FilterVal, Delegate] : drop_end(FilterChooserMap)) {
1681+
for (const auto &[FilterVal, Delegate] : drop_end(FC.FilterChooserMap)) {
16651682
Table.insertOpcode(MCD::OPC_FilterValue);
16661683
Table.insertULEB128(FilterVal);
16671684
size_t FixupPos = Table.insertNumToSkip();
16681685

16691686
// Emit table entries for this case.
1670-
Delegate->emitTableEntries(TableInfo);
1687+
emitTableEntries(*Delegate);
16711688

16721689
// Patch the previous OPC_FilterValue to fall through to the next case.
16731690
Table.patchNumToSkip(FixupPos, Table.size());
16741691
}
16751692

16761693
// Emit a switch case for the last element. It never falls through;
16771694
// if it doesn't match, we leave the current scope.
1678-
const auto &[FilterVal, Delegate] = *FilterChooserMap.rbegin();
1695+
const auto &[FilterVal, Delegate] = *FC.FilterChooserMap.rbegin();
16791696
Table.insertOpcode(!TableInfo.isOutermostScope()
16801697
? MCD::OPC_FilterValue
16811698
: MCD::OPC_FilterValueOrFail);
@@ -1684,12 +1701,12 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
16841701
TableInfo.FixupStack.back().push_back(Table.insertNumToSkip());
16851702

16861703
// Emit table entries for the last case.
1687-
Delegate->emitTableEntries(TableInfo);
1704+
emitTableEntries(*Delegate);
16881705
}
16891706

1690-
if (VariableFC) {
1707+
if (FC.VariableFC) {
16911708
TableInfo.popScope();
1692-
VariableFC->emitTableEntries(TableInfo);
1709+
emitTableEntries(*FC.VariableFC);
16931710
}
16941711
}
16951712

@@ -2538,6 +2555,7 @@ namespace {
25382555
}
25392556

25402557
DecoderTableInfo TableInfo;
2558+
DecoderTableBuilder TableBuilder(Target, Encodings, TableInfo);
25412559
unsigned OpcodeMask = 0;
25422560

25432561
for (const auto &[Key, EncodingIDs] : EncMap) {
@@ -2550,8 +2568,7 @@ namespace {
25502568
// predicates and decoders themselves, however, are shared across all
25512569
// decoders to give more opportunities for uniqueing.
25522570
TableInfo.Table.clear();
2553-
FC.emitTableEntries(TableInfo);
2554-
assert(TableInfo.isOutermostScope() && "fixup stack phasing error!");
2571+
TableBuilder.buildTable(FC);
25552572

25562573
// Print the table to the output stream.
25572574
OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,

0 commit comments

Comments
 (0)