diff options
author | superZWT123 <zhengwentao3@huawei.com> | 2024-04-01 17:19:46 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-01 17:19:46 +0800 |
commit | da1d3d8fb9e7dba1cc89327f5119fa7c0cadef81 (patch) | |
tree | 9c45c99bf8403ca70d932e3d88829ddd58e85ff1 | |
parent | ef0291e5f4451abbafab0c839bf51a6382f735f3 (diff) | |
download | llvm-da1d3d8fb9e7dba1cc89327f5119fa7c0cadef81.zip llvm-da1d3d8fb9e7dba1cc89327f5119fa7c0cadef81.tar.gz llvm-da1d3d8fb9e7dba1cc89327f5119fa7c0cadef81.tar.bz2 |
[TableGen] Introduce a less aggressive suppression for HwMode Decoder… (#86060)
1. Remove 'AllModes' and 'DefaultMode' suffixes for DecoderTables under
default HwMode.
2. Introduce a less aggressive suppression for HwMode DecoderTable, only
reduce necessary tables duplications. This allows encodings under
different HwModes to retain the original DecoderNamespace.
3. Change 'suppress-per-hwmode-duplicates' command option from bool type
to enum type, allowing users to choose what level of suppression to use.
-rw-r--r-- | llvm/test/TableGen/HwModeEncodeDecode2.td | 9 | ||||
-rw-r--r-- | llvm/test/TableGen/HwModeEncodeDecode3.td | 71 | ||||
-rw-r--r-- | llvm/utils/TableGen/DecoderEmitter.cpp | 104 |
3 files changed, 137 insertions, 47 deletions
diff --git a/llvm/test/TableGen/HwModeEncodeDecode2.td b/llvm/test/TableGen/HwModeEncodeDecode2.td index 5159501..cf96dda 100644 --- a/llvm/test/TableGen/HwModeEncodeDecode2.td +++ b/llvm/test/TableGen/HwModeEncodeDecode2.td @@ -1,6 +1,6 @@ // RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | \ // RUN: FileCheck %s --check-prefix=DECODER -// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates -I \ +// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates=O2 -I \ // RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS // Test duplicate table suppression for per-HwMode decoders. @@ -105,11 +105,10 @@ let OutOperandList = (outs) in { // DECODER-DAG: Opcode: fooTypeEncA:baz // DECODER-DAG: Opcode: bar - -// DECODER-SUPPRESS-LABEL: DecoderTableAlt_AllModes32[] = -// DECODER-SUPPRESS-DAG: Opcode: unrelated -// DECODER-SUPPRESS-LABEL: DecoderTable_AllModes32[] = +// DECODER-SUPPRESS-LABEL: DecoderTable32[] = // DECODER-SUPPRESS-DAG: Opcode: bar +// DECODER-SUPPRESS-LABEL: DecoderTableAlt32[] = +// DECODER-SUPPRESS-DAG: Opcode: unrelated // DECODER-SUPPRESS-LABEL: DecoderTable_ModeA32[] = // DECODER-SUPPRESS-DAG: Opcode: fooTypeEncA:foo // DECODER-SUPPRESS-NOT: Opcode: bar diff --git a/llvm/test/TableGen/HwModeEncodeDecode3.td b/llvm/test/TableGen/HwModeEncodeDecode3.td index 406e52d..8e0266b 100644 --- a/llvm/test/TableGen/HwModeEncodeDecode3.td +++ b/llvm/test/TableGen/HwModeEncodeDecode3.td @@ -2,8 +2,10 @@ // RUN: FileCheck %s --check-prefix=ENCODER // RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | \ // RUN: FileCheck %s --check-prefix=DECODER -// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates -I \ -// RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS +// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates=O1 -I \ +// RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS-O1 +// RUN: llvm-tblgen -gen-disassembler --suppress-per-hwmode-duplicates=O2 -I \ +// RUN: %p/../../include %s | FileCheck %s --check-prefix=DECODER-SUPPRESS-O2 include "llvm/Target/Target.td" @@ -99,16 +101,20 @@ def unrelated: Instruction { } -// DECODER-LABEL: DecoderTableAlt_DefaultMode32[] = +// Under default settings, using 'HwMode' to dictate instruction encodings results in +// significant duplication of DecoderTables. The three tables ‘DecoderTableAlt32’, +// ‘DecoderTableAlt_ModeA32’, and ‘DecoderTableAlt_ModeB32’ are exact duplicates and +// could effectively be merged into one. +// DECODER-LABEL: DecoderTable32[] = +// DECODER-DAG: Opcode: bar +// DECODER-LABEL: DecoderTable64[] = +// DECODER-DAG: Opcode: fooTypeEncDefault:foo +// DECODER-LABEL: DecoderTableAlt32[] = // DECODER-DAG: Opcode: unrelated // DECODER-LABEL: DecoderTableAlt_ModeA32[] = // DECODER-DAG: Opcode: unrelated // DECODER-LABEL: DecoderTableAlt_ModeB32[] = // DECODER-DAG: Opcode: unrelated -// DECODER-LABEL: DecoderTable_DefaultMode32[] = -// DECODER-DAG: Opcode: bar -// DECODER-LABEL: DecoderTable_DefaultMode64[] = -// DECODER-DAG: Opcode: fooTypeEncDefault:foo // DECODER-LABEL: DecoderTable_ModeA32[] = // DECODER-DAG: Opcode: fooTypeEncA:foo // DECODER-DAG: Opcode: bar @@ -117,21 +123,42 @@ def unrelated: Instruction { // DECODER-DAG: Opcode: fooTypeEncA:baz // DECODER-DAG: Opcode: bar - -// DECODER-SUPPRESS-LABEL: DecoderTableAlt_AllModes32[] = -// DECODER-SUPPRESS-DAG: Opcode: unrelated -// DECODER-SUPPRESS-LABEL: DecoderTable_AllModes32[] = -// DECODER-SUPPRESS-DAG: Opcode: bar -// DECODER-SUPPRESS-LABEL: DecoderTable_DefaultMode64[] = -// DECODER-SUPPRESS-NOT: Opcode: bar -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncDefault:foo -// DECODER-SUPPRESS-LABEL: DecoderTable_ModeA32[] = -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncA:foo -// DECODER-SUPPRESS-NOT: Opcode: bar -// DECODER-SUPPRESS-LABEL: DecoderTable_ModeB32[] = -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncB:foo -// DECODER-SUPPRESS-DAG: Opcode: fooTypeEncA:baz -// DECODER-SUPPRESS-NOT: Opcode: bar +// Under the 'O1' optimization level, unnecessary duplicate tables will be eliminated, +// reducing the three ‘Alt’ tables down to just one. +// DECODER-SUPPRESS-O1-LABEL: DecoderTable32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: bar +// DECODER-SUPPRESS-O1-LABEL: DecoderTable64[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncDefault:foo +// DECODER-SUPPRESS-O1-LABEL: DecoderTableAlt32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: unrelated +// DECODER-SUPPRESS-O1-LABEL: DecoderTable_ModeA32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncA:foo +// DECODER-SUPPRESS-O1-DAG: Opcode: bar +// DECODER-SUPPRESS-O1-LABEL: DecoderTable_ModeB32[] = +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncB:foo +// DECODER-SUPPRESS-O1-DAG: Opcode: fooTypeEncA:baz +// DECODER-SUPPRESS-O1-DAG: Opcode: bar + +// Under the 'O2' optimization condition, instructions possessing the 'EncodingByHwMode' +// attribute will be extracted from their original DecoderNamespace and placed into their +// respective HwMode tables. Meanwhile, other instructions that do not have the 'EncodingByHwMode' +// attribute but are within the same DecoderNamespace will be stored in the 'Default' table. This +// approach will significantly reduce instruction redundancy, but it necessitates users to thoroughly +// consider the interplay between HwMode and DecoderNamespace for their instructions. +// DECODER-SUPPRESS-O2-LABEL: DecoderTable32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: bar +// DECODER-SUPPRESS-O2-LABEL: DecoderTable64[] = +// DECODER-SUPPRESS-O2-NOT: Opcode: bar +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncDefault:foo +// DECODER-SUPPRESS-O2-LABEL: DecoderTableAlt32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: unrelated +// DECODER-SUPPRESS-O2-LABEL: DecoderTable_ModeA32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncA:foo +// DECODER-SUPPRESS-O2-NOT: Opcode: bar +// DECODER-SUPPRESS-O2-LABEL: DecoderTable_ModeB32[] = +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncB:foo +// DECODER-SUPPRESS-O2-DAG: Opcode: fooTypeEncA:baz +// DECODER-SUPPRESS-O2-NOT: Opcode: bar // ENCODER-LABEL: static const uint64_t InstBits_DefaultMode[] = { // ENCODER: UINT64_C(2), // bar diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 494dc93..3bd7f43 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -54,10 +54,27 @@ using namespace llvm; extern cl::OptionCategory DisassemblerEmitterCat; -cl::opt<bool> DecoderEmitterSuppressDuplicates( +enum SuppressLevel { + SUPPRESSION_DISABLE, + SUPPRESSION_LEVEL1, + SUPPRESSION_LEVEL2 +}; + +cl::opt<SuppressLevel> DecoderEmitterSuppressDuplicates( "suppress-per-hwmode-duplicates", cl::desc("Suppress duplication of instrs into per-HwMode decoder tables"), - cl::init(false), cl::cat(DisassemblerEmitterCat)); + cl::values( + clEnumValN( + SUPPRESSION_DISABLE, "O0", + "Do not prevent DecoderTable duplications caused by HwModes"), + clEnumValN( + SUPPRESSION_LEVEL1, "O1", + "Remove duplicate DecoderTable entries generated due to HwModes"), + clEnumValN( + SUPPRESSION_LEVEL2, "O2", + "Extract HwModes-specific instructions into new DecoderTables, " + "significantly reducing Table Duplications")), + cl::init(SUPPRESSION_DISABLE), cl::cat(DisassemblerEmitterCat)); namespace { @@ -128,6 +145,7 @@ struct EncodingIDAndOpcode { }; using EncodingIDsVec = std::vector<EncodingIDAndOpcode>; +using NamespacesHwModesMap = std::map<std::string, std::set<StringRef>>; raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) { if (Value.EncodingDef != Value.Inst->TheDef) @@ -2417,21 +2435,65 @@ static bool Check(DecodeStatus &Out, DecodeStatus In) { // Collect all HwModes referenced by the target for encoding purposes, // returning a vector of corresponding names. -static void -collectHwModesReferencedForEncodings(const CodeGenHwModes &HWM, - std::vector<StringRef> &Names) { +static void collectHwModesReferencedForEncodings( + const CodeGenHwModes &HWM, std::vector<StringRef> &Names, + NamespacesHwModesMap &NamespacesWithHwModes) { SmallBitVector BV(HWM.getNumModeIds()); for (const auto &MS : HWM.getHwModeSelects()) { for (const HwModeSelect::PairType &P : MS.second.Items) { - if (P.second->isSubClassOf("InstructionEncoding")) + if (P.second->isSubClassOf("InstructionEncoding")) { + std::string DecoderNamespace = + std::string(P.second->getValueAsString("DecoderNamespace")); + if (P.first == DefaultMode) { + NamespacesWithHwModes[DecoderNamespace].insert(""); + } else { + NamespacesWithHwModes[DecoderNamespace].insert( + HWM.getMode(P.first).Name); + } BV.set(P.first); + } } } transform(BV.set_bits(), std::back_inserter(Names), [&HWM](const int &M) { + if (M == DefaultMode) + return StringRef(""); return HWM.getModeName(M, /*IncludeDefault=*/true); }); } +static void +handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr, + const std::vector<StringRef> &HwModeNames, + NamespacesHwModesMap &NamespacesWithHwModes, + std::vector<EncodingAndInst> &GlobalEncodings) { + const Record *InstDef = Instr->TheDef; + + switch (DecoderEmitterSuppressDuplicates) { + case SUPPRESSION_DISABLE: { + for (StringRef HwModeName : HwModeNames) + GlobalEncodings.emplace_back(InstDef, Instr, HwModeName); + break; + } + case SUPPRESSION_LEVEL1: { + std::string DecoderNamespace = + std::string(InstDef->getValueAsString("DecoderNamespace")); + auto It = NamespacesWithHwModes.find(DecoderNamespace); + if (It != NamespacesWithHwModes.end()) { + for (StringRef HwModeName : It->second) + GlobalEncodings.emplace_back(InstDef, Instr, HwModeName); + } else { + // Only emit the encoding once, as it's DecoderNamespace doesn't + // contain any HwModes. + GlobalEncodings.emplace_back(InstDef, Instr, ""); + } + break; + } + case SUPPRESSION_LEVEL2: + GlobalEncodings.emplace_back(InstDef, Instr, ""); + break; + } +} + // Emits disassembler code for instruction decoding. void DecoderEmitter::run(raw_ostream &o) { formatted_raw_ostream OS(o); @@ -2457,10 +2519,12 @@ namespace llvm { // Parameterize the decoders based on namespace and instruction width. // First, collect all encoding-related HwModes referenced by the target. + // And establish a mapping table between DecoderNamespace and HwMode. // If HwModeNames is empty, add the empty string so we always have one HwMode. const CodeGenHwModes &HWM = Target.getHwModes(); std::vector<StringRef> HwModeNames; - collectHwModesReferencedForEncodings(HWM, HwModeNames); + NamespacesHwModesMap NamespacesWithHwModes; + collectHwModesReferencedForEncodings(HWM, HwModeNames, NamespacesWithHwModes); if (HwModeNames.empty()) HwModeNames.push_back(""); @@ -2471,22 +2535,22 @@ namespace llvm { if (const RecordVal *RV = InstDef->getValue("EncodingInfos")) { if (DefInit *DI = dyn_cast_or_null<DefInit>(RV->getValue())) { EncodingInfoByHwMode EBM(DI->getDef(), HWM); - for (auto &KV : EBM) - NumberedEncodings.emplace_back( - KV.second, NumberedInstruction, - HWM.getModeName(KV.first, /*IncludeDefault=*/true)); + for (auto &[ModeId, Encoding] : EBM) { + // DecoderTables with DefaultMode should not have any suffix. + if (ModeId == DefaultMode) { + NumberedEncodings.emplace_back(Encoding, NumberedInstruction, ""); + } else { + NumberedEncodings.emplace_back(Encoding, NumberedInstruction, + HWM.getMode(ModeId).Name); + } + } continue; } } - // This instruction is encoded the same on all HwModes. Emit it for all - // HwModes by default, otherwise leave it in a single common table. - if (DecoderEmitterSuppressDuplicates) { - NumberedEncodings.emplace_back(InstDef, NumberedInstruction, "AllModes"); - } else { - for (StringRef HwModeName : HwModeNames) - NumberedEncodings.emplace_back(InstDef, NumberedInstruction, - HwModeName); - } + // This instruction is encoded the same on all HwModes. + // According to user needs, provide varying degrees of suppression. + handleHwModesUnrelatedEncodings(NumberedInstruction, HwModeNames, + NamespacesWithHwModes, NumberedEncodings); } for (const auto &NumberedAlias : RK.getAllDerivedDefinitions("AdditionalEncoding")) |