[llvm] [TableGen] Introduce a less aggressive suppression for HwMode Decoder… (PR #86060)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 29 20:04:14 PDT 2024
https://github.com/superZWT123 updated https://github.com/llvm/llvm-project/pull/86060
>From add5fe9fe1d7c1945894b3ae69a735b75ec6e89d Mon Sep 17 00:00:00 2001
From: z30050559 <zhengwentao3 at huawei.com>
Date: Wed, 20 Mar 2024 19:55:13 +0800
Subject: [PATCH 1/2] [TableGen] Introduce a less aggressive suppression for
HwMode DecoderTable
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.
---
llvm/test/TableGen/HwModeEncodeDecode2.td | 9 +-
llvm/test/TableGen/HwModeEncodeDecode3.td | 71 +++++++++-----
llvm/utils/TableGen/DecoderEmitter.cpp | 107 ++++++++++++++++++----
3 files changed, 140 insertions(+), 47 deletions(-)
diff --git a/llvm/test/TableGen/HwModeEncodeDecode2.td b/llvm/test/TableGen/HwModeEncodeDecode2.td
index 5159501d8148eb..cf96dda6c8bf3b 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 406e52d25be706..8e0266b2c55af9 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 494dc93faacef8..c1ccbb1eea9d88 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,8 @@ struct EncodingIDAndOpcode {
};
using EncodingIDsVec = std::vector<EncodingIDAndOpcode>;
+using NamespacesHwModesMap =
+ std::map<std::string, std::map<StringRef, unsigned>>;
raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
if (Value.EncodingDef != Value.Inst->TheDef)
@@ -2417,21 +2436,67 @@ 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][""] = 1;
+ } else {
+ NamespacesWithHwModes[DecoderNamespace][HWM.getMode(P.first).Name] =
+ 1;
+ }
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"));
+ for (StringRef HwModeName : HwModeNames) {
+ if (NamespacesWithHwModes.count(DecoderNamespace) > 0) {
+ if (NamespacesWithHwModes[DecoderNamespace].count(HwModeName) > 0)
+ 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;
+ }
+ }
+ 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 +2522,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 +2538,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"))
>From fd93753257034c4ddd7a2af5ed91fe1b7712cb6c Mon Sep 17 00:00:00 2001
From: z30050559 <zhengwentao3 at huawei.com>
Date: Fri, 29 Mar 2024 16:27:22 +0800
Subject: [PATCH 2/2] [TableGen] Use set to collect HwModes for
DecoderNamespace
Use std::set to collect HwModes for DecoderNamespace, simplifying
code logic.
---
llvm/utils/TableGen/DecoderEmitter.cpp | 27 ++++++++++++--------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index c1ccbb1eea9d88..3bd7f432ff9ad6 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -145,8 +145,7 @@ struct EncodingIDAndOpcode {
};
using EncodingIDsVec = std::vector<EncodingIDAndOpcode>;
-using NamespacesHwModesMap =
- std::map<std::string, std::map<StringRef, unsigned>>;
+using NamespacesHwModesMap = std::map<std::string, std::set<StringRef>>;
raw_ostream &operator<<(raw_ostream &OS, const EncodingAndInst &Value) {
if (Value.EncodingDef != Value.Inst->TheDef)
@@ -2446,10 +2445,10 @@ static void collectHwModesReferencedForEncodings(
std::string DecoderNamespace =
std::string(P.second->getValueAsString("DecoderNamespace"));
if (P.first == DefaultMode) {
- NamespacesWithHwModes[DecoderNamespace][""] = 1;
+ NamespacesWithHwModes[DecoderNamespace].insert("");
} else {
- NamespacesWithHwModes[DecoderNamespace][HWM.getMode(P.first).Name] =
- 1;
+ NamespacesWithHwModes[DecoderNamespace].insert(
+ HWM.getMode(P.first).Name);
}
BV.set(P.first);
}
@@ -2478,16 +2477,14 @@ handleHwModesUnrelatedEncodings(const CodeGenInstruction *Instr,
case SUPPRESSION_LEVEL1: {
std::string DecoderNamespace =
std::string(InstDef->getValueAsString("DecoderNamespace"));
- for (StringRef HwModeName : HwModeNames) {
- if (NamespacesWithHwModes.count(DecoderNamespace) > 0) {
- if (NamespacesWithHwModes[DecoderNamespace].count(HwModeName) > 0)
- 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;
- }
+ 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;
}
More information about the llvm-commits
mailing list