diff options
author | Sergei Barannikov <barannikov88@gmail.com> | 2025-08-19 12:02:22 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-19 09:02:22 +0000 |
commit | 56ce40bc7378d8d8d94ec788a9d589b1ad990dc7 (patch) | |
tree | 5a9228544388aa9a4d07335c32eb5e324ebbb103 /llvm/utils/TableGen/DecoderEmitter.cpp | |
parent | eb764040bccc763afb2f6429baab63d1c73a5c85 (diff) | |
download | llvm-56ce40bc7378d8d8d94ec788a9d589b1ad990dc7.zip llvm-56ce40bc7378d8d8d94ec788a9d589b1ad990dc7.tar.gz llvm-56ce40bc7378d8d8d94ec788a9d589b1ad990dc7.tar.bz2 |
[TableGen][DecoderEmitter] Stop duplicating encodings (NFC) (#154288)
When HwModes are involved, we can duplicate an instruction encoding that
does not belong to any HwMode multiple times. We can do better by
mapping HwMode to a list of encoding IDs it contains. (That is,
duplicate IDs instead of encodings.)
The encodings that were duplicated are still processed multiple times
(e.g., we call an expensive populateInstruction() on each instance).
This is going to be fixed in subsequent patches.
Diffstat (limited to 'llvm/utils/TableGen/DecoderEmitter.cpp')
-rw-r--r-- | llvm/utils/TableGen/DecoderEmitter.cpp | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 0634fac..abf29f9 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -208,11 +208,9 @@ struct DecoderTableInfo { struct EncodingAndInst { const Record *EncodingDef; const CodeGenInstruction *Inst; - unsigned HwModeID; - EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst, - unsigned HwModeID = DefaultMode) - : EncodingDef(EncodingDef), Inst(Inst), HwModeID(HwModeID) {} + EncodingAndInst(const Record *EncodingDef, const CodeGenInstruction *Inst) + : EncodingDef(EncodingDef), Inst(Inst) {} }; using NamespacesHwModesMap = std::map<std::string, std::set<unsigned>>; @@ -221,8 +219,13 @@ class DecoderEmitter { const RecordKeeper &RK; CodeGenTarget Target; const CodeGenHwModes &CGH; + + /// All parsed encodings. std::vector<EncodingAndInst> Encodings; + /// Encodings IDs for each HwMode. An ID is an index into Encodings. + SmallDenseMap<unsigned, std::vector<unsigned>> EncodingIDsByHwMode; + public: DecoderEmitter(const RecordKeeper &RK, StringRef PredicateNamespace); @@ -249,7 +252,7 @@ private: NamespacesHwModesMap &NamespacesWithHwModes) const; void - handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr, + handleHwModesUnrelatedEncodings(unsigned EncodingID, ArrayRef<unsigned> HwModeIDs, NamespacesHwModesMap &NamespacesWithHwModes); @@ -2425,32 +2428,31 @@ void DecoderEmitter::collectHwModesReferencedForEncodings( } void DecoderEmitter::handleHwModesUnrelatedEncodings( - const CodeGenInstruction *Instr, ArrayRef<unsigned> HwModeIDs, + unsigned EncodingID, ArrayRef<unsigned> HwModeIDs, NamespacesHwModesMap &NamespacesWithHwModes) { - const Record *InstDef = Instr->TheDef; - switch (DecoderEmitterSuppressDuplicates) { case SUPPRESSION_DISABLE: { for (unsigned HwModeID : HwModeIDs) - Encodings.emplace_back(InstDef, Instr, HwModeID); + EncodingIDsByHwMode[HwModeID].push_back(EncodingID); break; } case SUPPRESSION_LEVEL1: { + const Record *InstDef = Encodings[EncodingID].Inst->TheDef; std::string DecoderNamespace = InstDef->getValueAsString("DecoderNamespace").str(); auto It = NamespacesWithHwModes.find(DecoderNamespace); if (It != NamespacesWithHwModes.end()) { for (unsigned HwModeID : It->second) - Encodings.emplace_back(InstDef, Instr, HwModeID); + EncodingIDsByHwMode[HwModeID].push_back(EncodingID); } else { // Only emit the encoding once, as it's DecoderNamespace doesn't // contain any HwModes. - Encodings.emplace_back(InstDef, Instr, DefaultMode); + EncodingIDsByHwMode[DefaultMode].push_back(EncodingID); } break; } case SUPPRESSION_LEVEL2: - Encodings.emplace_back(InstDef, Instr, DefaultMode); + EncodingIDsByHwMode[DefaultMode].push_back(EncodingID); break; } } @@ -2474,13 +2476,21 @@ void DecoderEmitter::parseInstructionEncodings() { const Record *InstDef = Inst->TheDef; if (const Record *RV = InstDef->getValueAsOptionalDef("EncodingInfos")) { EncodingInfoByHwMode EBM(RV, CGH); - for (auto [HwModeID, EncodingDef] : EBM) - Encodings.emplace_back(EncodingDef, Inst, HwModeID); + for (auto [HwModeID, EncodingDef] : EBM) { + unsigned EncodingID = Encodings.size(); + Encodings.emplace_back(EncodingDef, Inst); + EncodingIDsByHwMode[HwModeID].push_back(EncodingID); + } continue; } + + unsigned EncodingID = Encodings.size(); + Encodings.emplace_back(InstDef, Inst); + // This instruction is encoded the same on all HwModes. - // According to user needs, provide varying degrees of suppression. - handleHwModesUnrelatedEncodings(Inst, HwModeIDs, NamespacesWithHwModes); + // According to user needs, add it to all, some, or only the default HwMode. + handleHwModesUnrelatedEncodings(EncodingID, HwModeIDs, + NamespacesWithHwModes); } for (const Record *EncodingDef : @@ -2528,35 +2538,39 @@ namespace { InstrLen.resize(Target.getInstructions().size(), 0); unsigned MaxInstLen = 0; - for (const auto &[EncodingID, Encoding] : enumerate(Encodings)) { - const Record *EncodingDef = Encoding.EncodingDef; - const CodeGenInstruction *Inst = Encoding.Inst; - const Record *Def = Inst->TheDef; - unsigned Size = EncodingDef->getValueAsInt("Size"); - if (Def->getValueAsString("Namespace") == "TargetOpcode" || - Def->getValueAsBit("isPseudo") || - Def->getValueAsBit("isAsmParserOnly") || - Def->getValueAsBit("isCodeGenOnly")) { - NumEncodingsLackingDisasm++; - continue; - } + for (const auto &[HwModeID, EncodingIDs] : EncodingIDsByHwMode) { + for (unsigned EncodingID : EncodingIDs) { + const EncodingAndInst &Encoding = Encodings[EncodingID]; + const Record *EncodingDef = Encoding.EncodingDef; + const CodeGenInstruction *Inst = Encoding.Inst; + const Record *Def = Inst->TheDef; + unsigned Size = EncodingDef->getValueAsInt("Size"); + if (Def->getValueAsString("Namespace") == "TargetOpcode" || + Def->getValueAsBit("isPseudo") || + Def->getValueAsBit("isAsmParserOnly") || + Def->getValueAsBit("isCodeGenOnly")) { + NumEncodingsLackingDisasm++; + continue; + } - NumEncodings++; + NumEncodings++; - if (!Size && !IsVarLenInst) - continue; + if (!Size && !IsVarLenInst) + continue; - if (unsigned Len = populateInstruction( - Target, *EncodingDef, *Inst, EncodingID, Operands, IsVarLenInst)) { - if (IsVarLenInst) { - MaxInstLen = std::max(MaxInstLen, Len); - InstrLen[EncodingID] = Len; + if (unsigned Len = + populateInstruction(Target, *EncodingDef, *Inst, EncodingID, + Operands, IsVarLenInst)) { + if (IsVarLenInst) { + MaxInstLen = std::max(MaxInstLen, Len); + InstrLen[EncodingID] = Len; + } + StringRef DecoderNamespace = + EncodingDef->getValueAsString("DecoderNamespace"); + EncMap[{DecoderNamespace, HwModeID, Size}].push_back(EncodingID); + } else { + NumEncodingsOmitted++; } - StringRef DecoderNamespace = - EncodingDef->getValueAsString("DecoderNamespace"); - EncMap[{DecoderNamespace, Encoding.HwModeID, Size}].push_back(EncodingID); - } else { - NumEncodingsOmitted++; } } |