[llvm] [TableGen][DecoderEmitter] Add option to emit type-specialized code (PR #146593)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 19 04:52:56 PDT 2025
================
@@ -2574,52 +2776,140 @@ namespace {
}
}
+ bool GenerateTemplated =
+ Target.getInstructionSet()->getValueAsBit("GenerateTemplatedDecoder");
+
+ // For variable instruction, we emit a instruction length table to let the
+ // decoder know how long the instructions are. You can see example usage in
+ // M68k's disassembler.
+ if (IsVarLenInst) {
+ if (GenerateTemplated)
+ PrintFatalError(
+ "Templated decoder not needed for variable length instruction");
+ emitInstrLenTable(OS, InstrLen);
+ }
+
DecoderTableInfo TableInfo;
+ bool HasCheckPredicate = false;
unsigned OpcodeMask = 0;
- for (const auto &[Key, EncodingIDs] : EncMap) {
- auto [DecoderNamespace, HwModeID, Size] = Key;
- const unsigned BitWidth = IsVarLenInst ? MaxInstLen : 8 * Size;
- // Emit the decoder for this (namespace, hwmode, width) combination.
- FilterChooser FC(Encodings, EncodingIDs, Operands, BitWidth, this);
-
- // The decode table is cleared for each top level decoder function. The
- // predicates and decoders themselves, however, are shared across all
- // decoders to give more opportunities for uniqueing.
- TableInfo.Table.clear();
- TableInfo.pushScope();
- FC.emitTableEntries(TableInfo);
- // Any NumToSkip fixups in the top level scope can resolve to the
- // OPC_Fail at the end of the table.
- assert(TableInfo.isOutermostScope() && "fixup stack phasing error!");
- TableInfo.popScope();
- TableInfo.Table.push_back(MCD::OPC_Fail);
+ // Helper lambda to emit the decoder code for a given instruction Bitwidth
+ // and associated C++ type. If `Bitwidth` is 0 (and CPPType is empty) it will
+ // generate templated decoder code.
+ auto emitDecoder = [&](const CPPType &Type, StringRef Suffix) {
+ // Reset the Decoders for each non-templated type.
+ TableInfo.Decoders.clear();
+
+ const bool IsTemplate = Type.Kind == CPPType::TemplateTy;
+ if (!IsTemplate) {
+ OS << "// ------------------------------------------------------------\n";
+ OS << "// Decoder tables for " << Type.Bitwidth << "-bit instructions.\n";
+ OS << "// Using C++ type `" << Type.getName() << "` for payload.\n\n";
+ }
- // Print the table to the output stream.
- OpcodeMask |= emitTable(OS, TableInfo.Table, DecoderNamespace, HwModeID,
- BitWidth, EncodingIDs);
- }
+ for (const auto &[Key, EncodingIDs] : EncMap) {
+ auto [DecoderNamespace, HwModeID, Size] = Key;
+ const unsigned Bitwidth = IsVarLenInst ? MaxInstLen : 8 * Size;
- // For variable instruction, we emit a instruction length table
- // to let the decoder know how long the instructions are.
- // You can see example usage in M68k's disassembler.
- if (IsVarLenInst)
- emitInstrLenTable(OS, InstrLen);
+ if (!IsTemplate && Bitwidth != Type.Bitwidth)
+ continue;
- const bool HasCheckPredicate =
- OpcodeMask &
- ((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
+ // Emit the decoder table for this (namespace, hwmode, width) combination.
+ FilterChooser FC(Encodings, EncodingIDs, Operands, Bitwidth, this);
+
+ // The decode table is cleared for each top level decoder table generated.
+ //
+ // The decoders themselves are shared across all decoder tables for a
+ // given instuction bitwidth, to give more opporuninity for uniqueing.
----------------
s-barannikov wrote:
Typos "instuction" and "opporuninity"
https://github.com/llvm/llvm-project/pull/146593
More information about the llvm-commits
mailing list