Skip to content

Commit a10773c

Browse files
authored
[TableGen][DecoderEmitter] Remove EncodingIDAndOpcode struct (NFC) (#154028)
Most of the time we don't need instruction opcode. There is no need to carry it around all the time, we can easily get it by other means. Rename affected variables accordingly. Part of an effort to simplify DecoderEmitter code.
1 parent 6cfedea commit a10773c

File tree

1 file changed

+55
-68
lines changed

1 file changed

+55
-68
lines changed

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 55 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -215,16 +215,6 @@ struct EncodingAndInst {
215215
: EncodingDef(EncodingDef), Inst(Inst), HwModeName(HwModeName) {}
216216
};
217217

218-
struct EncodingIDAndOpcode {
219-
unsigned EncodingID;
220-
unsigned Opcode;
221-
222-
EncodingIDAndOpcode() : EncodingID(0), Opcode(0) {}
223-
EncodingIDAndOpcode(unsigned EncodingID, unsigned Opcode)
224-
: EncodingID(EncodingID), Opcode(Opcode) {}
225-
};
226-
227-
using EncodingIDsVec = std::vector<EncodingIDAndOpcode>;
228218
using NamespacesHwModesMap = std::map<std::string, std::set<StringRef>>;
229219

230220
class DecoderEmitter {
@@ -235,11 +225,13 @@ class DecoderEmitter {
235225
DecoderEmitter(const RecordKeeper &R, StringRef PredicateNamespace)
236226
: RK(R), Target(R), PredicateNamespace(PredicateNamespace) {}
237227

228+
const CodeGenTarget &getTarget() const { return Target; }
229+
238230
// Emit the decoder state machine table. Returns a mask of MCD decoder ops
239231
// that were emitted.
240232
unsigned emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
241233
unsigned BitWidth, StringRef Namespace,
242-
const EncodingIDsVec &EncodingIDs) const;
234+
ArrayRef<unsigned> EncodingIDs) const;
243235
void emitInstrLenTable(formatted_raw_ostream &OS,
244236
ArrayRef<unsigned> InstrLen) const;
245237
void emitPredicateFunction(formatted_raw_ostream &OS,
@@ -416,10 +408,10 @@ class Filter {
416408
unsigned NumBits; // number of bits to filter
417409

418410
// Map of well-known segment value to the set of uid's with that value.
419-
std::map<uint64_t, std::vector<EncodingIDAndOpcode>> FilteredInstructions;
411+
std::map<uint64_t, std::vector<unsigned>> FilteredIDs;
420412

421413
// Set of uid's with non-constant segment values.
422-
std::vector<EncodingIDAndOpcode> VariableInstructions;
414+
std::vector<unsigned> VariableIDs;
423415

424416
// Map of well-known segment value to its delegate.
425417
std::map<uint64_t, std::unique_ptr<const FilterChooser>> FilterChooserMap;
@@ -435,9 +427,9 @@ class Filter {
435427

436428
unsigned getNumFiltered() const { return NumFiltered; }
437429

438-
EncodingIDAndOpcode getSingletonOpc() const {
430+
unsigned getSingletonEncodingID() const {
439431
assert(NumFiltered == 1);
440-
return FilteredInstructions.begin()->second.front();
432+
return FilteredIDs.begin()->second.front();
441433
}
442434

443435
// Return the filter chooser for the group of instructions without constant
@@ -498,9 +490,7 @@ class FilterChooser {
498490
ArrayRef<EncodingAndInst> AllInstructions;
499491

500492
// Vector of uid's for this filter chooser to work on.
501-
// The first member of the pair is the opcode id being decoded, the second is
502-
// the opcode id that should be emitted.
503-
ArrayRef<EncodingIDAndOpcode> Opcodes;
493+
ArrayRef<unsigned> EncodingIDs;
504494

505495
// Lookup table for the operand decoding of instructions.
506496
const std::map<unsigned, std::vector<OperandInfo>> &Operands;
@@ -528,22 +518,20 @@ class FilterChooser {
528518
};
529519

530520
public:
531-
FilterChooser(ArrayRef<EncodingAndInst> Insts,
532-
ArrayRef<EncodingIDAndOpcode> IDs,
521+
FilterChooser(ArrayRef<EncodingAndInst> Insts, ArrayRef<unsigned> EncodingIDs,
533522
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
534523
unsigned BW, const DecoderEmitter *E)
535-
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
524+
: AllInstructions(Insts), EncodingIDs(EncodingIDs), Operands(Ops),
536525
FilterBitValues(BW, BitValue::BIT_UNFILTERED), Parent(nullptr),
537526
BitWidth(BW), Emitter(E) {
538527
doFilter();
539528
}
540529

541-
FilterChooser(ArrayRef<EncodingAndInst> Insts,
542-
ArrayRef<EncodingIDAndOpcode> IDs,
530+
FilterChooser(ArrayRef<EncodingAndInst> Insts, ArrayRef<unsigned> EncodingIDs,
543531
const std::map<unsigned, std::vector<OperandInfo>> &Ops,
544532
const std::vector<BitValue> &ParentFilterBitValues,
545533
const FilterChooser &parent)
546-
: AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
534+
: AllInstructions(Insts), EncodingIDs(EncodingIDs), Operands(Ops),
547535
FilterBitValues(ParentFilterBitValues), Parent(&parent),
548536
BitWidth(parent.BitWidth), Emitter(parent.Emitter) {
549537
doFilter();
@@ -608,7 +596,7 @@ class FilterChooser {
608596

609597
// Emits table entries to decode the singleton.
610598
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
611-
EncodingIDAndOpcode Opc) const;
599+
unsigned EncodingID) const;
612600

613601
// Emits code to decode the singleton, and then to decode the rest.
614602
void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
@@ -656,8 +644,8 @@ class FilterChooser {
656644

657645
Filter::Filter(Filter &&f)
658646
: Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits),
659-
FilteredInstructions(std::move(f.FilteredInstructions)),
660-
VariableInstructions(std::move(f.VariableInstructions)),
647+
FilteredIDs(std::move(f.FilteredIDs)),
648+
VariableIDs(std::move(f.VariableIDs)),
661649
FilterChooserMap(std::move(f.FilterChooserMap)),
662650
NumFiltered(f.NumFiltered) {}
663651

@@ -667,26 +655,26 @@ Filter::Filter(const FilterChooser &owner, unsigned startBit, unsigned numBits)
667655

668656
NumFiltered = 0;
669657

670-
for (const auto &OpcPair : Owner.Opcodes) {
658+
for (unsigned EncodingID : Owner.EncodingIDs) {
671659
// Populates the insn given the uid.
672-
insn_t Insn = Owner.insnWithID(OpcPair.EncodingID);
660+
insn_t Insn = Owner.insnWithID(EncodingID);
673661

674662
// Scans the segment for possibly well-specified encoding bits.
675663
std::optional<uint64_t> Field = fieldFromInsn(Insn, StartBit, NumBits);
676664

677665
if (Field) {
678666
// The encoding bits are well-known. Lets add the uid of the
679667
// instruction into the bucket keyed off the constant field value.
680-
FilteredInstructions[*Field].push_back(OpcPair);
668+
FilteredIDs[*Field].push_back(EncodingID);
681669
++NumFiltered;
682670
} else {
683671
// Some of the encoding bit(s) are unspecified. This contributes to
684672
// one additional member of "Variable" instructions.
685-
VariableInstructions.push_back(OpcPair);
673+
VariableIDs.push_back(EncodingID);
686674
}
687675
}
688676

689-
assert((FilteredInstructions.size() + VariableInstructions.size() > 0) &&
677+
assert((FilteredIDs.size() + VariableIDs.size() > 0) &&
690678
"Filter returns no instruction categories");
691679
}
692680

@@ -700,17 +688,16 @@ void Filter::recurse() {
700688
// Starts by inheriting our parent filter chooser's filter bit values.
701689
std::vector<BitValue> BitValueArray(Owner.FilterBitValues);
702690

703-
if (!VariableInstructions.empty()) {
691+
if (!VariableIDs.empty()) {
704692
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
705693
BitValueArray[StartBit + bitIndex] = BitValue::BIT_UNFILTERED;
706694

707695
// Delegates to an inferior filter chooser for further processing on this
708696
// group of instructions whose segment values are variable.
709697
FilterChooserMap.try_emplace(
710698
NO_FIXED_SEGMENTS_SENTINEL,
711-
std::make_unique<FilterChooser>(Owner.AllInstructions,
712-
VariableInstructions, Owner.Operands,
713-
BitValueArray, Owner));
699+
std::make_unique<FilterChooser>(Owner.AllInstructions, VariableIDs,
700+
Owner.Operands, BitValueArray, Owner));
714701
}
715702

716703
// No need to recurse for a singleton filtered instruction.
@@ -721,7 +708,7 @@ void Filter::recurse() {
721708
}
722709

723710
// Otherwise, create sub choosers.
724-
for (const auto &Inst : FilteredInstructions) {
711+
for (const auto &Inst : FilteredIDs) {
725712
// Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
726713
for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
727714
BitValueArray[StartBit + bitIndex] = Inst.first & (1ULL << bitIndex)
@@ -810,7 +797,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
810797
// Returns the number of fanout produced by the filter. More fanout implies
811798
// the filter distinguishes more categories of instructions.
812799
unsigned Filter::usefulness() const {
813-
return FilteredInstructions.size() + VariableInstructions.empty();
800+
return FilteredIDs.size() + VariableIDs.empty();
814801
}
815802

816803
//////////////////////////////////
@@ -824,14 +811,16 @@ unsigned Filter::usefulness() const {
824811
unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
825812
DecoderTable &Table, unsigned BitWidth,
826813
StringRef Namespace,
827-
const EncodingIDsVec &EncodingIDs) const {
814+
ArrayRef<unsigned> EncodingIDs) const {
828815
// We'll need to be able to map from a decoded opcode into the corresponding
829816
// EncodingID for this specific combination of BitWidth and Namespace. This
830817
// is used below to index into NumberedEncodings.
831818
DenseMap<unsigned, unsigned> OpcodeToEncodingID;
832819
OpcodeToEncodingID.reserve(EncodingIDs.size());
833-
for (const auto &EI : EncodingIDs)
834-
OpcodeToEncodingID[EI.Opcode] = EI.EncodingID;
820+
for (unsigned EncodingID : EncodingIDs) {
821+
const Record *InstDef = NumberedEncodings[EncodingID].Inst->TheDef;
822+
OpcodeToEncodingID[Target.getInstrIntValue(InstDef)] = EncodingID;
823+
}
835824

836825
OS << "static const uint8_t DecoderTable" << Namespace << BitWidth
837826
<< "[] = {\n";
@@ -1419,14 +1408,14 @@ void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
14191408

14201409
// Emits table entries to decode the singleton.
14211410
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
1422-
EncodingIDAndOpcode Opc) const {
1423-
insn_t Insn = insnWithID(Opc.EncodingID);
1411+
unsigned EncodingID) const {
1412+
insn_t Insn = insnWithID(EncodingID);
14241413

14251414
// Look for islands of undecoded bits of the singleton.
14261415
std::vector<Island> Islands = getIslands(Insn);
14271416

14281417
// Emit the predicate table entry if one is needed.
1429-
emitPredicateTableEntry(TableInfo, Opc.EncodingID);
1418+
emitPredicateTableEntry(TableInfo, EncodingID);
14301419

14311420
// Check any additional encoding fields needed.
14321421
for (const Island &Ilnd : reverse(Islands)) {
@@ -1451,10 +1440,10 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14511440
}
14521441

14531442
// Check for soft failure of the match.
1454-
emitSoftFailTableEntry(TableInfo, Opc.EncodingID);
1443+
emitSoftFailTableEntry(TableInfo, EncodingID);
14551444

14561445
auto [DIdx, HasCompleteDecoder] =
1457-
getDecoderIndex(TableInfo.Decoders, Opc.EncodingID);
1446+
getDecoderIndex(TableInfo.Decoders, EncodingID);
14581447

14591448
// Produce OPC_Decode or OPC_TryDecode opcode based on the information
14601449
// whether the instruction decoder is complete or not. If it is complete
@@ -1471,7 +1460,8 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14711460
: MCD::OPC_TryDecode);
14721461
TableInfo.Table.push_back(DecoderOp);
14731462
NumEncodingsSupported++;
1474-
TableInfo.Table.insertULEB128(Opc.Opcode);
1463+
const Record *InstDef = AllInstructions[EncodingID].Inst->TheDef;
1464+
TableInfo.Table.insertULEB128(Emitter->getTarget().getInstrIntValue(InstDef));
14751465
TableInfo.Table.insertULEB128(DIdx);
14761466

14771467
if (DecoderOp == MCD::OPC_TryDecode) {
@@ -1483,12 +1473,10 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14831473
// Emits table entries to decode the singleton, and then to decode the rest.
14841474
void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14851475
const Filter &Best) const {
1486-
EncodingIDAndOpcode Opc = Best.getSingletonOpc();
1487-
14881476
// complex singletons need predicate checks from the first singleton
14891477
// to refer forward to the variable filterchooser that follows.
14901478
TableInfo.pushScope();
1491-
emitSingletonTableEntry(TableInfo, Opc);
1479+
emitSingletonTableEntry(TableInfo, Best.getSingletonEncodingID());
14921480
TableInfo.popScope();
14931481

14941482
Best.getVariableFC().emitTableEntries(TableInfo);
@@ -1516,15 +1504,15 @@ void FilterChooser::reportRegion(std::vector<std::unique_ptr<Filter>> &Filters,
15161504
// recursively descends down the decoding tree.
15171505
bool FilterChooser::filterProcessor(ArrayRef<bitAttr_t> BitAttrs,
15181506
bool AllowMixed, bool Greedy) {
1519-
assert(Opcodes.size() >= 2 && "Nothing to filter");
1507+
assert(EncodingIDs.size() >= 2 && "Nothing to filter");
15201508

15211509
// Heuristics. See also doFilter()'s "Heuristics" comment when num of
15221510
// instructions is 3.
15231511
if (AllowMixed && !Greedy) {
1524-
assert(Opcodes.size() == 3);
1512+
assert(EncodingIDs.size() == 3);
15251513

1526-
for (const auto &Opcode : Opcodes) {
1527-
insn_t Insn = insnWithID(Opcode.EncodingID);
1514+
for (unsigned EncodingID : EncodingIDs) {
1515+
insn_t Insn = insnWithID(EncodingID);
15281516

15291517
// Look for islands of undecoded bits of any instruction.
15301518
std::vector<Island> Islands = getIslands(Insn);
@@ -1681,10 +1669,10 @@ bool FilterChooser::filterProcessor(ArrayRef<bitAttr_t> BitAttrs,
16811669
// the instructions. A conflict of instructions may occur, in which case we
16821670
// dump the conflict set to the standard error.
16831671
void FilterChooser::doFilter() {
1684-
assert(!Opcodes.empty() && "FilterChooser created with no instructions");
1672+
assert(!EncodingIDs.empty() && "FilterChooser created with no instructions");
16851673

16861674
// No filter needed.
1687-
if (Opcodes.size() < 2)
1675+
if (EncodingIDs.size() < 2)
16881676
return;
16891677

16901678
// We maintain BIT_WIDTH copies of the bitAttrs automaton.
@@ -1712,8 +1700,8 @@ void FilterChooser::doFilter() {
17121700
if (FilterBitValues[BitIndex].isSet())
17131701
BitAttrs[BitIndex] = ATTR_FILTERED;
17141702

1715-
for (const EncodingIDAndOpcode &OpcPair : Opcodes) {
1716-
insn_t EncodingBits = insnWithID(OpcPair.EncodingID);
1703+
for (unsigned EncodingID : EncodingIDs) {
1704+
insn_t EncodingBits = insnWithID(EncodingID);
17171705

17181706
for (unsigned BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
17191707
switch (BitAttrs[BitIndex]) {
@@ -1750,7 +1738,7 @@ void FilterChooser::doFilter() {
17501738
// no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a
17511739
// well-known encoding pattern. In such case, we backtrack and scan for the
17521740
// the very first consecutive ATTR_ALL_SET region and assign a filter to it.
1753-
if (Opcodes.size() == 3 &&
1741+
if (EncodingIDs.size() == 3 &&
17541742
filterProcessor(BitAttrs, /*AllowMixed=*/true, /*Greedy=*/false))
17551743
return;
17561744

@@ -1766,8 +1754,8 @@ void FilterChooser::doFilter() {
17661754
dumpStack(errs(), Indent);
17671755

17681756
// Dump encodings.
1769-
for (EncodingIDAndOpcode Opcode : Opcodes) {
1770-
const EncodingAndInst &Enc = AllInstructions[Opcode.EncodingID];
1757+
for (unsigned EncodingID : EncodingIDs) {
1758+
const EncodingAndInst &Enc = AllInstructions[EncodingID];
17711759
errs() << Indent;
17721760
dumpBits(errs(), getBitsField(*Enc.EncodingDef, "Inst"), BitWidth);
17731761
errs() << " " << Enc << '\n';
@@ -1778,11 +1766,11 @@ void FilterChooser::doFilter() {
17781766
// emitTableEntries - Emit state machine entries to decode our share of
17791767
// instructions.
17801768
void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
1781-
if (Opcodes.size() == 1) {
1769+
if (EncodingIDs.size() == 1) {
17821770
// There is only one instruction in the set, which is great!
17831771
// Call emitSingletonDecoder() to see whether there are any remaining
17841772
// encodings bits.
1785-
emitSingletonTableEntry(TableInfo, Opcodes[0]);
1773+
emitSingletonTableEntry(TableInfo, EncodingIDs[0]);
17861774
return;
17871775
}
17881776

@@ -2528,8 +2516,8 @@ namespace {
25282516
NumberedAlias,
25292517
&Target.getInstruction(NumberedAlias->getValueAsDef("AliasOf")));
25302518

2531-
std::map<std::pair<std::string, unsigned>, std::vector<EncodingIDAndOpcode>>
2532-
OpcMap;
2519+
// Map of (namespace, size) tuple to encoding IDs.
2520+
std::map<std::pair<std::string, unsigned>, std::vector<unsigned>> EncMap;
25332521
std::map<unsigned, std::vector<OperandInfo>> Operands;
25342522
std::vector<unsigned> InstrLen;
25352523
bool IsVarLenInst = Target.hasVariableLengthEncodings();
@@ -2568,16 +2556,15 @@ namespace {
25682556
EncodingDef->getValueAsString("DecoderNamespace").str();
25692557
if (!NumberedEncoding.HwModeName.empty())
25702558
DecoderNamespace += "_" + NumberedEncoding.HwModeName.str();
2571-
OpcMap[{DecoderNamespace, Size}].emplace_back(
2572-
NEI, Target.getInstrIntValue(Def));
2559+
EncMap[{DecoderNamespace, Size}].push_back(NEI);
25732560
} else {
25742561
NumEncodingsOmitted++;
25752562
}
25762563
}
25772564

25782565
DecoderTableInfo TableInfo;
25792566
unsigned OpcodeMask = 0;
2580-
for (const auto &[NSAndByteSize, EncodingIDs] : OpcMap) {
2567+
for (const auto &[NSAndByteSize, EncodingIDs] : EncMap) {
25812568
const std::string &DecoderNamespace = NSAndByteSize.first;
25822569
const unsigned BitWidth = 8 * NSAndByteSize.second;
25832570
// Emit the decoder for this namespace+width combination.

0 commit comments

Comments
 (0)