Skip to content

Commit

Permalink
[TableGen] Introduce a less aggressive suppression for HwMode Decoder… (
Browse files Browse the repository at this point in the history
#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.
  • Loading branch information
superZWT123 committed Apr 1, 2024
1 parent ef0291e commit da1d3d8
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 47 deletions.
9 changes: 4 additions & 5 deletions llvm/test/TableGen/HwModeEncodeDecode2.td
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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
Expand Down
71 changes: 49 additions & 22 deletions llvm/test/TableGen/HwModeEncodeDecode3.td
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
104 changes: 84 additions & 20 deletions llvm/utils/TableGen/DecoderEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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("");

Expand All @@ -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"))
Expand Down

0 comments on commit da1d3d8

Please sign in to comment.