Skip to content

Commit 803edce

Browse files
authored
[TableGen][DecoderEmitter] Analyze encodings once (#154309)
Follow-up to #154288. With HwModes involved, we used to analyze the same encoding multiple times (unless `-suppress-per-hwmode-duplicates=O2` is specified). This affected the build time and made the statistics inaccurate. From the point of view of the generated code, this is an NFC.
1 parent 7cd6179 commit 803edce

File tree

1 file changed

+86
-34
lines changed

1 file changed

+86
-34
lines changed

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 86 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,7 +1489,6 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
14891489
? MCD::OPC_TryDecodeOrFail
14901490
: MCD::OPC_TryDecode);
14911491
TableInfo.Table.push_back(DecoderOp);
1492-
NumEncodingsSupported++;
14931492
const Record *InstDef = Encodings[EncodingID].getInstruction()->TheDef;
14941493
TableInfo.Table.insertULEB128(Emitter->getTarget().getInstrIntValue(InstDef));
14951494
TableInfo.Table.insertULEB128(DIdx);
@@ -2474,6 +2473,41 @@ void DecoderEmitter::handleHwModesUnrelatedEncodings(
24742473
}
24752474
}
24762475

2476+
/// Checks if the given target-specific non-pseudo instruction
2477+
/// is a candidate for decoding.
2478+
static bool isDecodableInstruction(const Record *InstDef) {
2479+
return !InstDef->getValueAsBit("isAsmParserOnly") &&
2480+
!InstDef->getValueAsBit("isCodeGenOnly");
2481+
}
2482+
2483+
/// Checks if the given encoding is valid.
2484+
static bool isValidEncoding(const Record *EncodingDef) {
2485+
const RecordVal *InstField = EncodingDef->getValue("Inst");
2486+
if (!InstField)
2487+
return false;
2488+
2489+
if (const auto *InstInit = dyn_cast<BitsInit>(InstField->getValue())) {
2490+
// Fixed-length encoding. Size must be non-zero.
2491+
if (!EncodingDef->getValueAsInt("Size"))
2492+
return false;
2493+
2494+
// At least one of the encoding bits must be complete (not '?').
2495+
return !InstInit->allInComplete();
2496+
}
2497+
2498+
if (const auto *InstInit = dyn_cast<DagInit>(InstField->getValue())) {
2499+
// Variable-length encoding.
2500+
// At least one of the encoding bits must be complete (not '?').
2501+
VarLenInst VLI(InstInit, InstField);
2502+
return !all_of(VLI, [](const EncodingSegment &Segment) {
2503+
return isa<UnsetInit>(Segment.Value);
2504+
});
2505+
}
2506+
2507+
// Inst field is neither BitsInit nor DagInit. This is something unsupported.
2508+
return false;
2509+
}
2510+
24772511
/// Parses all InstructionEncoding instances and fills internal data structures.
24782512
void DecoderEmitter::parseInstructionEncodings() {
24792513
// First, collect all encoding-related HwModes referenced by the target.
@@ -2485,19 +2519,34 @@ void DecoderEmitter::parseInstructionEncodings() {
24852519
if (HwModeIDs.empty())
24862520
HwModeIDs.push_back(DefaultMode);
24872521

2488-
ArrayRef<const CodeGenInstruction *> Instructions = Target.getInstructions();
2522+
ArrayRef<const CodeGenInstruction *> Instructions =
2523+
Target.getTargetNonPseudoInstructions();
24892524
Encodings.reserve(Instructions.size());
2490-
NumInstructions = Instructions.size();
24912525

24922526
for (const CodeGenInstruction *Inst : Instructions) {
24932527
const Record *InstDef = Inst->TheDef;
2528+
if (!isDecodableInstruction(InstDef)) {
2529+
++NumEncodingsLackingDisasm;
2530+
continue;
2531+
}
2532+
24942533
if (const Record *RV = InstDef->getValueAsOptionalDef("EncodingInfos")) {
24952534
EncodingInfoByHwMode EBM(RV, CGH);
24962535
for (auto [HwModeID, EncodingDef] : EBM) {
2536+
if (!isValidEncoding(EncodingDef)) {
2537+
// TODO: Should probably give a warning.
2538+
++NumEncodingsOmitted;
2539+
continue;
2540+
}
24972541
unsigned EncodingID = Encodings.size();
24982542
Encodings.emplace_back(EncodingDef, Inst);
24992543
EncodingIDsByHwMode[HwModeID].push_back(EncodingID);
25002544
}
2545+
continue; // Ignore encoding specified by Instruction itself.
2546+
}
2547+
2548+
if (!isValidEncoding(InstDef)) {
2549+
++NumEncodingsOmitted;
25012550
continue;
25022551
}
25032552

@@ -2513,8 +2562,24 @@ void DecoderEmitter::parseInstructionEncodings() {
25132562
for (const Record *EncodingDef :
25142563
RK.getAllDerivedDefinitions("AdditionalEncoding")) {
25152564
const Record *InstDef = EncodingDef->getValueAsDef("AliasOf");
2565+
// TODO: Should probably give a warning in these cases.
2566+
// What's the point of specifying an additional encoding
2567+
// if it is invalid or if the instruction is not decodable?
2568+
if (!isDecodableInstruction(InstDef)) {
2569+
++NumEncodingsLackingDisasm;
2570+
continue;
2571+
}
2572+
if (!isValidEncoding(EncodingDef)) {
2573+
++NumEncodingsOmitted;
2574+
continue;
2575+
}
25162576
Encodings.emplace_back(EncodingDef, &Target.getInstruction(InstDef));
25172577
}
2578+
2579+
// Do some statistics.
2580+
NumInstructions = Instructions.size();
2581+
NumEncodingsSupported = Encodings.size();
2582+
NumEncodings = NumEncodingsSupported + NumEncodingsOmitted;
25182583
}
25192584

25202585
DecoderEmitter::DecoderEmitter(const RecordKeeper &RK,
@@ -2545,49 +2610,36 @@ namespace {
25452610
emitInsertBits(OS);
25462611
emitCheck(OS);
25472612

2548-
// Map of (namespace, hwmode, size) tuple to encoding IDs.
2549-
std::map<std::tuple<StringRef, unsigned, unsigned>, std::vector<unsigned>>
2550-
EncMap;
25512613
std::map<unsigned, std::vector<OperandInfo>> Operands;
25522614
std::vector<unsigned> InstrLen;
25532615
bool IsVarLenInst = Target.hasVariableLengthEncodings();
25542616
if (IsVarLenInst)
25552617
InstrLen.resize(Target.getInstructions().size(), 0);
25562618
unsigned MaxInstLen = 0;
25572619

2620+
for (auto [EncodingID, Encoding] : enumerate(Encodings)) {
2621+
const Record *EncodingDef = Encoding.getRecord();
2622+
const CodeGenInstruction *Inst = Encoding.getInstruction();
2623+
unsigned BitWidth = populateInstruction(Target, *EncodingDef, *Inst,
2624+
EncodingID, Operands, IsVarLenInst);
2625+
assert(BitWidth && "Invalid encodings should have been filtered out");
2626+
if (IsVarLenInst) {
2627+
MaxInstLen = std::max(MaxInstLen, BitWidth);
2628+
InstrLen[Target.getInstrIntValue(Inst->TheDef)] = BitWidth;
2629+
}
2630+
}
2631+
2632+
// Map of (namespace, hwmode, size) tuple to encoding IDs.
2633+
std::map<std::tuple<StringRef, unsigned, unsigned>, std::vector<unsigned>>
2634+
EncMap;
25582635
for (const auto &[HwModeID, EncodingIDs] : EncodingIDsByHwMode) {
25592636
for (unsigned EncodingID : EncodingIDs) {
25602637
const InstructionEncoding &Encoding = Encodings[EncodingID];
25612638
const Record *EncodingDef = Encoding.getRecord();
2562-
const CodeGenInstruction *Inst = Encoding.getInstruction();
2563-
const Record *Def = Inst->TheDef;
25642639
unsigned Size = EncodingDef->getValueAsInt("Size");
2565-
if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
2566-
Def->getValueAsBit("isPseudo") ||
2567-
Def->getValueAsBit("isAsmParserOnly") ||
2568-
Def->getValueAsBit("isCodeGenOnly")) {
2569-
NumEncodingsLackingDisasm++;
2570-
continue;
2571-
}
2572-
2573-
NumEncodings++;
2574-
2575-
if (!Size && !IsVarLenInst)
2576-
continue;
2577-
2578-
if (unsigned Len =
2579-
populateInstruction(Target, *EncodingDef, *Inst, EncodingID,
2580-
Operands, IsVarLenInst)) {
2581-
if (IsVarLenInst) {
2582-
MaxInstLen = std::max(MaxInstLen, Len);
2583-
InstrLen[EncodingID] = Len;
2584-
}
2585-
StringRef DecoderNamespace =
2586-
EncodingDef->getValueAsString("DecoderNamespace");
2587-
EncMap[{DecoderNamespace, HwModeID, Size}].push_back(EncodingID);
2588-
} else {
2589-
NumEncodingsOmitted++;
2590-
}
2640+
StringRef DecoderNamespace =
2641+
EncodingDef->getValueAsString("DecoderNamespace");
2642+
EncMap[{DecoderNamespace, HwModeID, Size}].push_back(EncodingID);
25912643
}
25922644
}
25932645

0 commit comments

Comments
 (0)