[llvm] 816ab1a - [NFCI][TableGen][DecoderEmitter] Cull Op handling when possible (#142974)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 17 06:21:24 PDT 2025
Author: Rahul Joshi
Date: 2025-06-17T06:21:21-07:00
New Revision: 816ab1af0da1dc833f487933e7d6fb470d844001
URL: https://github.com/llvm/llvm-project/commit/816ab1af0da1dc833f487933e7d6fb470d844001
DIFF: https://github.com/llvm/llvm-project/commit/816ab1af0da1dc833f487933e7d6fb470d844001.diff
LOG: [NFCI][TableGen][DecoderEmitter] Cull Op handling when possible (#142974)
TryDecode/CheckPredicate/SoftFail MCD ops are not used by many targets.
Track the set of opcodes that were emitted and emit code for handling
TryDecode/CheckPredicate/SoftFail ops when decoding only if there were
emitted. This is purely eliminating dead code in the generated
`decodeInstruction` function.
This results in the following reduction in the size of the Disassembler
.so files with a release x86_64 release build on Linux:
```
Target Old Size New Size % reduction
build/lib/libLLVMAArch64Disassembler.so.21.0git 256656 256656 0.00
build/lib/libLLVMAMDGPUDisassembler.so.21.0git 813000 808168 0.59
build/lib/libLLVMARCDisassembler.so.21.0git 44816 43536 2.86
build/lib/libLLVMARMDisassembler.so.21.0git 281744 278808 1.04
build/lib/libLLVMAVRDisassembler.so.21.0git 36040 34496 4.28
build/lib/libLLVMBPFDisassembler.so.21.0git 26248 23168 11.73
build/lib/libLLVMCSKYDisassembler.so.21.0git 55960 53632 4.16
build/lib/libLLVMHexagonDisassembler.so.21.0git 115952 113416 2.19
build/lib/libLLVMLanaiDisassembler.so.21.0git 24360 21008 13.76
build/lib/libLLVMLoongArchDisassembler.so.21.0git 58584 56168 4.12
build/lib/libLLVMM68kDisassembler.so.21.0git 57264 53880 5.91
build/lib/libLLVMMSP430Disassembler.so.21.0git 28896 28440 1.58
build/lib/libLLVMMipsDisassembler.so.21.0git 123128 120568 2.08
build/lib/libLLVMPowerPCDisassembler.so.21.0git 80656 78096 3.17
build/lib/libLLVMRISCVDisassembler.so.21.0git 154080 150200 2.52
build/lib/libLLVMSparcDisassembler.so.21.0git 42040 39568 5.88
build/lib/libLLVMSystemZDisassembler.so.21.0git 97056 94552 2.58
build/lib/libLLVMVEDisassembler.so.21.0git 83944 81352 3.09
build/lib/libLLVMWebAssemblyDisassembler.so.21.0git 25280 25280 0.00
build/lib/libLLVMX86Disassembler.so.21.0git 2920624 2920624 0.00
build/lib/libLLVMXCoreDisassembler.so.21.0git 48320 44288 8.34
build/lib/libLLVMXtensaDisassembler.so.21.0git 42248 35840 15.17
```
Added:
Modified:
llvm/utils/TableGen/DecoderEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp
index 7489d369c9932..37814113b467a 100644
--- a/llvm/utils/TableGen/DecoderEmitter.cpp
+++ b/llvm/utils/TableGen/DecoderEmitter.cpp
@@ -222,10 +222,11 @@ class DecoderEmitter {
DecoderEmitter(const RecordKeeper &R, StringRef PredicateNamespace)
: RK(R), Target(R), PredicateNamespace(PredicateNamespace) {}
- // Emit the decoder state machine table.
- void emitTable(formatted_raw_ostream &OS, DecoderTable &Table, indent Indent,
- unsigned BitWidth, StringRef Namespace,
- const EncodingIDsVec &EncodingIDs) const;
+ // Emit the decoder state machine table. Returns a mask of MCD decoder ops
+ // that were emitted.
+ unsigned emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
+ indent Indent, unsigned BitWidth, StringRef Namespace,
+ const EncodingIDsVec &EncodingIDs) const;
void emitInstrLenTable(formatted_raw_ostream &OS,
ArrayRef<unsigned> InstrLen) const;
void emitPredicateFunction(formatted_raw_ostream &OS,
@@ -826,11 +827,12 @@ unsigned Filter::usefulness() const {
// //
//////////////////////////////////
-// Emit the decoder state machine table.
-void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
- indent Indent, unsigned BitWidth,
- StringRef Namespace,
- const EncodingIDsVec &EncodingIDs) const {
+// Emit the decoder state machine table. Returns a mask of MCD decoder ops
+// that were emitted.
+unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
+ DecoderTable &Table, indent Indent,
+ unsigned BitWidth, StringRef Namespace,
+ const EncodingIDsVec &EncodingIDs) const {
// We'll need to be able to map from a decoded opcode into the corresponding
// EncodingID for this specific combination of BitWidth and Namespace. This
// is used below to index into NumberedEncodings.
@@ -884,6 +886,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS << " (Fail)";
};
+ unsigned OpcodeMask = 0;
+
while (I != E) {
assert(I < E && "incomplete decode table entry!");
@@ -892,6 +896,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
OS.PadToColumn(12);
const uint8_t DecoderOp = *I++;
+ OpcodeMask |= (1 << DecoderOp);
switch (DecoderOp) {
default:
PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) +
@@ -1027,6 +1032,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
Indent -= 2;
OS << Indent << "};\n\n";
+
+ return OpcodeMask;
}
void DecoderEmitter::emitInstrLenTable(formatted_raw_ostream &OS,
@@ -1045,19 +1052,13 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
OS << Indent << "static bool checkDecoderPredicate(unsigned Idx, "
<< "const FeatureBitset &Bits) {\n";
Indent += 2;
- if (!Predicates.empty()) {
- OS << Indent << "switch (Idx) {\n";
- OS << Indent << "default: llvm_unreachable(\"Invalid index!\");\n";
- unsigned Index = 0;
- for (const auto &Predicate : Predicates) {
- OS << Indent << "case " << Index++ << ":\n";
- OS << Indent + 2 << "return (" << Predicate << ");\n";
- }
- OS << Indent << "}\n";
- } else {
- // No case statement to emit
- OS << Indent << "llvm_unreachable(\"Invalid index!\");\n";
+ OS << Indent << "switch (Idx) {\n";
+ OS << Indent << "default: llvm_unreachable(\"Invalid index!\");\n";
+ for (const auto &[Index, Predicate] : enumerate(Predicates)) {
+ OS << Indent << "case " << Index << ":\n";
+ OS << Indent + 2 << "return (" << Predicate << ");\n";
}
+ OS << Indent << "}\n";
Indent -= 2;
OS << Indent << "}\n\n";
}
@@ -2217,8 +2218,15 @@ static void insertBits(InsnType &field, InsnType bits, unsigned startBit,
// emitDecodeInstruction - Emit the templated helper function
// decodeInstruction().
-static void emitDecodeInstruction(formatted_raw_ostream &OS,
- bool IsVarLenInst) {
+static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst,
+ unsigned OpcodeMask) {
+ const bool HasTryDecode = OpcodeMask & ((1 << MCD::OPC_TryDecode) |
+ (1 << MCD::OPC_TryDecodeOrFail));
+ const bool HasCheckPredicate =
+ OpcodeMask &
+ ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
+ const bool HasSoftFail = OpcodeMask & (1 << MCD::OPC_SoftFail);
+
OS << R"(
static unsigned decodeNumToSkip(const uint8_t *&Ptr) {
unsigned NumToSkip = *Ptr++;
@@ -2238,9 +2246,11 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
OS << ",\n "
"llvm::function_ref<void(APInt &, uint64_t)> makeUp";
}
- OS << R"() {
- const FeatureBitset &Bits = STI.getFeatureBits();
+ OS << ") {\n";
+ if (HasCheckPredicate)
+ OS << " const FeatureBitset &Bits = STI.getFeatureBits();\n";
+ OS << R"(
const uint8_t *Ptr = DecodeTable;
uint64_t CurFieldValue = 0;
DecodeStatus S = MCDisassembler::Success;
@@ -2321,7 +2331,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
Ptr += NumToSkip;
}
break;
- }
+ })";
+ if (HasCheckPredicate) {
+ OS << R"(
case MCD::OPC_CheckPredicate:
case MCD::OPC_CheckPredicateOrFail: {
bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
@@ -2343,7 +2355,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
Ptr += NumToSkip;
}
break;
- }
+ })";
+ }
+ OS << R"(
case MCD::OPC_Decode: {
// Decode the Opcode value.
unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
@@ -2364,7 +2378,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
<< ", using decoder " << DecodeIdx << ": "
<< (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
return S;
- }
+ })";
+ if (HasTryDecode) {
+ OS << R"(
case MCD::OPC_TryDecode:
case MCD::OPC_TryDecodeOrFail: {
bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
@@ -2399,17 +2415,22 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
// set before the decode attempt.
S = MCDisassembler::Success;
break;
- }
- case MCD::OPC_SoftFail: {
- // Decode the mask values.
- uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
- uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
- bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
- if (Failed)
- S = MCDisassembler::SoftFail;
- LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
- break;
- }
+ })";
+ }
+ if (HasSoftFail) {
+ OS << R"(
+ case MCD::OPC_SoftFail: {
+ // Decode the mask values.
+ uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
+ uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
+ bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
+ if (Failed)
+ S = MCDisassembler::SoftFail;
+ LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
+ break;
+ })";
+ }
+ OS << R"(
case MCD::OPC_Fail: {
LLVM_DEBUG(dbgs() << Loc << ": OPC_Fail\n");
return MCDisassembler::Fail;
@@ -2609,6 +2630,7 @@ namespace {
}
DecoderTableInfo TableInfo;
+ unsigned OpcodeMask = 0;
for (const auto &Opc : OpcMap) {
// Emit the decoder for this namespace+width combination.
ArrayRef<EncodingAndInst> NumberedEncodingsRef(NumberedEncodings.data(),
@@ -2634,8 +2656,8 @@ namespace {
TableInfo.Table.push_back(MCD::OPC_Fail);
// Print the table to the output stream.
- emitTable(OS, TableInfo.Table, indent(0), FC.getBitWidth(), Opc.first.first,
- Opc.second);
+ OpcodeMask |= emitTable(OS, TableInfo.Table, indent(0), FC.getBitWidth(),
+ Opc.first.first, Opc.second);
}
// For variable instruction, we emit a instruction length table
@@ -2643,14 +2665,20 @@ namespace {
// You can see example usage in M68k's disassembler.
if (IsVarLenInst)
emitInstrLenTable(OS, InstrLen);
+
+ const bool HasCheckPredicate =
+ OpcodeMask &
+ ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
+
// Emit the predicate function.
- emitPredicateFunction(OS, TableInfo.Predicates, indent(0));
+ if (HasCheckPredicate)
+ emitPredicateFunction(OS, TableInfo.Predicates, indent(0));
// Emit the decoder function.
emitDecoderFunction(OS, TableInfo.Decoders, indent(0));
// Emit the main entry point for the decoder, decodeInstruction().
- emitDecodeInstruction(OS, IsVarLenInst);
+ emitDecodeInstruction(OS, IsVarLenInst, OpcodeMask);
OS << "\n} // namespace\n";
}
More information about the llvm-commits
mailing list