Skip to content

Commit 816ab1a

Browse files
authored
[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 ```
1 parent 977d8a4 commit 816ab1a

File tree

1 file changed

+71
-43
lines changed

1 file changed

+71
-43
lines changed

llvm/utils/TableGen/DecoderEmitter.cpp

Lines changed: 71 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,11 @@ class DecoderEmitter {
222222
DecoderEmitter(const RecordKeeper &R, StringRef PredicateNamespace)
223223
: RK(R), Target(R), PredicateNamespace(PredicateNamespace) {}
224224

225-
// Emit the decoder state machine table.
226-
void emitTable(formatted_raw_ostream &OS, DecoderTable &Table, indent Indent,
227-
unsigned BitWidth, StringRef Namespace,
228-
const EncodingIDsVec &EncodingIDs) const;
225+
// Emit the decoder state machine table. Returns a mask of MCD decoder ops
226+
// that were emitted.
227+
unsigned emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
228+
indent Indent, unsigned BitWidth, StringRef Namespace,
229+
const EncodingIDsVec &EncodingIDs) const;
229230
void emitInstrLenTable(formatted_raw_ostream &OS,
230231
ArrayRef<unsigned> InstrLen) const;
231232
void emitPredicateFunction(formatted_raw_ostream &OS,
@@ -826,11 +827,12 @@ unsigned Filter::usefulness() const {
826827
// //
827828
//////////////////////////////////
828829

829-
// Emit the decoder state machine table.
830-
void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
831-
indent Indent, unsigned BitWidth,
832-
StringRef Namespace,
833-
const EncodingIDsVec &EncodingIDs) const {
830+
// Emit the decoder state machine table. Returns a mask of MCD decoder ops
831+
// that were emitted.
832+
unsigned DecoderEmitter::emitTable(formatted_raw_ostream &OS,
833+
DecoderTable &Table, indent Indent,
834+
unsigned BitWidth, StringRef Namespace,
835+
const EncodingIDsVec &EncodingIDs) const {
834836
// We'll need to be able to map from a decoded opcode into the corresponding
835837
// EncodingID for this specific combination of BitWidth and Namespace. This
836838
// is used below to index into NumberedEncodings.
@@ -884,6 +886,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
884886
OS << " (Fail)";
885887
};
886888

889+
unsigned OpcodeMask = 0;
890+
887891
while (I != E) {
888892
assert(I < E && "incomplete decode table entry!");
889893

@@ -892,6 +896,7 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
892896
OS.PadToColumn(12);
893897

894898
const uint8_t DecoderOp = *I++;
899+
OpcodeMask |= (1 << DecoderOp);
895900
switch (DecoderOp) {
896901
default:
897902
PrintFatalError("Invalid decode table opcode: " + Twine((int)DecoderOp) +
@@ -1027,6 +1032,8 @@ void DecoderEmitter::emitTable(formatted_raw_ostream &OS, DecoderTable &Table,
10271032
Indent -= 2;
10281033

10291034
OS << Indent << "};\n\n";
1035+
1036+
return OpcodeMask;
10301037
}
10311038

10321039
void DecoderEmitter::emitInstrLenTable(formatted_raw_ostream &OS,
@@ -1045,19 +1052,13 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
10451052
OS << Indent << "static bool checkDecoderPredicate(unsigned Idx, "
10461053
<< "const FeatureBitset &Bits) {\n";
10471054
Indent += 2;
1048-
if (!Predicates.empty()) {
1049-
OS << Indent << "switch (Idx) {\n";
1050-
OS << Indent << "default: llvm_unreachable(\"Invalid index!\");\n";
1051-
unsigned Index = 0;
1052-
for (const auto &Predicate : Predicates) {
1053-
OS << Indent << "case " << Index++ << ":\n";
1054-
OS << Indent + 2 << "return (" << Predicate << ");\n";
1055-
}
1056-
OS << Indent << "}\n";
1057-
} else {
1058-
// No case statement to emit
1059-
OS << Indent << "llvm_unreachable(\"Invalid index!\");\n";
1055+
OS << Indent << "switch (Idx) {\n";
1056+
OS << Indent << "default: llvm_unreachable(\"Invalid index!\");\n";
1057+
for (const auto &[Index, Predicate] : enumerate(Predicates)) {
1058+
OS << Indent << "case " << Index << ":\n";
1059+
OS << Indent + 2 << "return (" << Predicate << ");\n";
10601060
}
1061+
OS << Indent << "}\n";
10611062
Indent -= 2;
10621063
OS << Indent << "}\n\n";
10631064
}
@@ -2217,8 +2218,15 @@ static void insertBits(InsnType &field, InsnType bits, unsigned startBit,
22172218

22182219
// emitDecodeInstruction - Emit the templated helper function
22192220
// decodeInstruction().
2220-
static void emitDecodeInstruction(formatted_raw_ostream &OS,
2221-
bool IsVarLenInst) {
2221+
static void emitDecodeInstruction(formatted_raw_ostream &OS, bool IsVarLenInst,
2222+
unsigned OpcodeMask) {
2223+
const bool HasTryDecode = OpcodeMask & ((1 << MCD::OPC_TryDecode) |
2224+
(1 << MCD::OPC_TryDecodeOrFail));
2225+
const bool HasCheckPredicate =
2226+
OpcodeMask &
2227+
((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
2228+
const bool HasSoftFail = OpcodeMask & (1 << MCD::OPC_SoftFail);
2229+
22222230
OS << R"(
22232231
static unsigned decodeNumToSkip(const uint8_t *&Ptr) {
22242232
unsigned NumToSkip = *Ptr++;
@@ -2238,9 +2246,11 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
22382246
OS << ",\n "
22392247
"llvm::function_ref<void(APInt &, uint64_t)> makeUp";
22402248
}
2241-
OS << R"() {
2242-
const FeatureBitset &Bits = STI.getFeatureBits();
2249+
OS << ") {\n";
2250+
if (HasCheckPredicate)
2251+
OS << " const FeatureBitset &Bits = STI.getFeatureBits();\n";
22432252

2253+
OS << R"(
22442254
const uint8_t *Ptr = DecodeTable;
22452255
uint64_t CurFieldValue = 0;
22462256
DecodeStatus S = MCDisassembler::Success;
@@ -2321,7 +2331,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23212331
Ptr += NumToSkip;
23222332
}
23232333
break;
2324-
}
2334+
})";
2335+
if (HasCheckPredicate) {
2336+
OS << R"(
23252337
case MCD::OPC_CheckPredicate:
23262338
case MCD::OPC_CheckPredicateOrFail: {
23272339
bool IsFail = DecoderOp == MCD::OPC_CheckPredicateOrFail;
@@ -2343,7 +2355,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23432355
Ptr += NumToSkip;
23442356
}
23452357
break;
2346-
}
2358+
})";
2359+
}
2360+
OS << R"(
23472361
case MCD::OPC_Decode: {
23482362
// Decode the Opcode value.
23492363
unsigned Opc = decodeULEB128AndIncUnsafe(Ptr);
@@ -2364,7 +2378,9 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23642378
<< ", using decoder " << DecodeIdx << ": "
23652379
<< (S != MCDisassembler::Fail ? "PASS\n" : "FAIL\n"));
23662380
return S;
2367-
}
2381+
})";
2382+
if (HasTryDecode) {
2383+
OS << R"(
23682384
case MCD::OPC_TryDecode:
23692385
case MCD::OPC_TryDecodeOrFail: {
23702386
bool IsFail = DecoderOp == MCD::OPC_TryDecodeOrFail;
@@ -2399,17 +2415,22 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23992415
// set before the decode attempt.
24002416
S = MCDisassembler::Success;
24012417
break;
2402-
}
2403-
case MCD::OPC_SoftFail: {
2404-
// Decode the mask values.
2405-
uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
2406-
uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
2407-
bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
2408-
if (Failed)
2409-
S = MCDisassembler::SoftFail;
2410-
LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
2411-
break;
2412-
}
2418+
})";
2419+
}
2420+
if (HasSoftFail) {
2421+
OS << R"(
2422+
case MCD::OPC_SoftFail: {
2423+
// Decode the mask values.
2424+
uint64_t PositiveMask = decodeULEB128AndIncUnsafe(Ptr);
2425+
uint64_t NegativeMask = decodeULEB128AndIncUnsafe(Ptr);
2426+
bool Failed = (insn & PositiveMask) != 0 || (~insn & NegativeMask) != 0;
2427+
if (Failed)
2428+
S = MCDisassembler::SoftFail;
2429+
LLVM_DEBUG(dbgs() << Loc << ": OPC_SoftFail: " << (Failed ? "FAIL\n" : "PASS\n"));
2430+
break;
2431+
})";
2432+
}
2433+
OS << R"(
24132434
case MCD::OPC_Fail: {
24142435
LLVM_DEBUG(dbgs() << Loc << ": OPC_Fail\n");
24152436
return MCDisassembler::Fail;
@@ -2609,6 +2630,7 @@ namespace {
26092630
}
26102631

26112632
DecoderTableInfo TableInfo;
2633+
unsigned OpcodeMask = 0;
26122634
for (const auto &Opc : OpcMap) {
26132635
// Emit the decoder for this namespace+width combination.
26142636
ArrayRef<EncodingAndInst> NumberedEncodingsRef(NumberedEncodings.data(),
@@ -2634,23 +2656,29 @@ namespace {
26342656
TableInfo.Table.push_back(MCD::OPC_Fail);
26352657

26362658
// Print the table to the output stream.
2637-
emitTable(OS, TableInfo.Table, indent(0), FC.getBitWidth(), Opc.first.first,
2638-
Opc.second);
2659+
OpcodeMask |= emitTable(OS, TableInfo.Table, indent(0), FC.getBitWidth(),
2660+
Opc.first.first, Opc.second);
26392661
}
26402662

26412663
// For variable instruction, we emit a instruction length table
26422664
// to let the decoder know how long the instructions are.
26432665
// You can see example usage in M68k's disassembler.
26442666
if (IsVarLenInst)
26452667
emitInstrLenTable(OS, InstrLen);
2668+
2669+
const bool HasCheckPredicate =
2670+
OpcodeMask &
2671+
((1 << MCD::OPC_CheckPredicate) | (1 << MCD::OPC_CheckPredicateOrFail));
2672+
26462673
// Emit the predicate function.
2647-
emitPredicateFunction(OS, TableInfo.Predicates, indent(0));
2674+
if (HasCheckPredicate)
2675+
emitPredicateFunction(OS, TableInfo.Predicates, indent(0));
26482676

26492677
// Emit the decoder function.
26502678
emitDecoderFunction(OS, TableInfo.Decoders, indent(0));
26512679

26522680
// Emit the main entry point for the decoder, decodeInstruction().
2653-
emitDecodeInstruction(OS, IsVarLenInst);
2681+
emitDecodeInstruction(OS, IsVarLenInst, OpcodeMask);
26542682

26552683
OS << "\n} // namespace\n";
26562684
}

0 commit comments

Comments
 (0)