@@ -83,6 +83,14 @@ static cl::opt<bool> LargeTable(
83
83
" in the table instead of the default 16 bits." ),
84
84
cl::init(false ), cl::cat(DisassemblerEmitterCat));
85
85
86
+ static cl::opt<bool > UseFnTableInDecodetoMCInst (
87
+ " use-fn-table-in-decode-to-mcinst" ,
88
+ cl::desc (
89
+ " Use a table of function pointers instead of a switch case in the\n "
90
+ " generated `decodeToMCInst` function. Helps improve compile time\n "
91
+ " of the generated code." ),
92
+ cl::init(false ), cl::cat(DisassemblerEmitterCat));
93
+
86
94
STATISTIC (NumEncodings, " Number of encodings considered" );
87
95
STATISTIC (NumEncodingsLackingDisasm,
88
96
" Number of encodings without disassembler info" );
@@ -1066,31 +1074,67 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
1066
1074
void DecoderEmitter::emitDecoderFunction (formatted_raw_ostream &OS,
1067
1075
DecoderSet &Decoders,
1068
1076
indent Indent) const {
1069
- // The decoder function is just a big switch statement based on the
1070
- // input decoder index.
1071
- OS << Indent << " template <typename InsnType>\n " ;
1072
- OS << Indent << " static DecodeStatus decodeToMCInst(DecodeStatus S,"
1073
- << " unsigned Idx, InsnType insn, MCInst &MI,\n " ;
1074
- OS << Indent << " uint64_t "
1075
- << " Address, const MCDisassembler *Decoder, bool &DecodeComplete) {\n " ;
1076
- Indent += 2 ;
1077
- OS << Indent << " DecodeComplete = true;\n " ;
1077
+ // The decoder function is just a big switch statement or a table of function
1078
+ // pointers based on the input decoder index.
1079
+
1078
1080
// TODO: When InsnType is large, using uint64_t limits all fields to 64 bits
1079
1081
// It would be better for emitBinaryParser to use a 64-bit tmp whenever
1080
1082
// possible but fall back to an InsnType-sized tmp for truly large fields.
1081
- OS << Indent
1082
- << " using TmpType = "
1083
- " std::conditional_t<std::is_integral<InsnType>::"
1084
- " value, InsnType, uint64_t>;\n " ;
1085
- OS << Indent << " TmpType tmp;\n " ;
1086
- OS << Indent << " switch (Idx) {\n " ;
1087
- OS << Indent << " default: llvm_unreachable(\" Invalid index!\" );\n " ;
1088
- for (const auto &[Index, Decoder] : enumerate(Decoders)) {
1089
- OS << Indent << " case " << Index << " :\n " ;
1090
- OS << Decoder;
1091
- OS << Indent + 2 << " return S;\n " ;
1083
+ StringRef TmpTypeDecl =
1084
+ " using TmpType = std::conditional_t<std::is_integral<InsnType>::value, "
1085
+ " InsnType, uint64_t>;\n " ;
1086
+ StringRef DecodeParams =
1087
+ " DecodeStatus S, InsnType insn, MCInst &MI, uint64_t Address, const "
1088
+ " MCDisassembler *Decoder, bool &DecodeComplete" ;
1089
+
1090
+ if (UseFnTableInDecodetoMCInst) {
1091
+ // Emit a function for each case first.
1092
+ for (const auto &[Index, Decoder] : enumerate(Decoders)) {
1093
+ OS << Indent << " template <typename InsnType>\n " ;
1094
+ OS << Indent << " DecodeStatus decodeFn" << Index << " (" << DecodeParams
1095
+ << " ) {\n " ;
1096
+ Indent += 2 ;
1097
+ OS << Indent << TmpTypeDecl;
1098
+ OS << Indent << " [[maybe_unused]] TmpType tmp;\n " ;
1099
+ OS << Decoder;
1100
+ OS << Indent << " return S;\n " ;
1101
+ Indent -= 2 ;
1102
+ OS << Indent << " }\n\n " ;
1103
+ }
1104
+ }
1105
+
1106
+ OS << Indent << " // Handling " << Decoders.size () << " cases.\n " ;
1107
+ OS << Indent << " template <typename InsnType>\n " ;
1108
+ OS << Indent << " static DecodeStatus decodeToMCInst(unsigned Idx, "
1109
+ << DecodeParams << " ) {\n " ;
1110
+ Indent += 2 ;
1111
+ OS << Indent << " DecodeComplete = true;\n " ;
1112
+
1113
+ if (UseFnTableInDecodetoMCInst) {
1114
+ // Build a table of function pointers.
1115
+ OS << Indent << " using DecodeFnTy = DecodeStatus (*)(" << DecodeParams
1116
+ << " );\n " ;
1117
+ OS << Indent << " static constexpr DecodeFnTy decodeFnTable[] = {\n " ;
1118
+ for (size_t Index : llvm::seq (Decoders.size ()))
1119
+ OS << Indent + 2 << " decodeFn" << Index << " ,\n " ;
1120
+ OS << Indent << " };\n " ;
1121
+ OS << Indent << " if (Idx >= " << Decoders.size () << " )\n " ;
1122
+ OS << Indent + 2 << " llvm_unreachable(\" Invalid index!\" );\n " ;
1123
+ OS << Indent
1124
+ << " return decodeFnTable[Idx](S, insn, MI, Address, Decoder, "
1125
+ " DecodeComplete);\n " ;
1126
+ } else {
1127
+ OS << Indent << TmpTypeDecl;
1128
+ OS << Indent << " TmpType tmp;\n " ;
1129
+ OS << Indent << " switch (Idx) {\n " ;
1130
+ OS << Indent << " default: llvm_unreachable(\" Invalid index!\" );\n " ;
1131
+ for (const auto &[Index, Decoder] : enumerate(Decoders)) {
1132
+ OS << Indent << " case " << Index << " :\n " ;
1133
+ OS << Decoder;
1134
+ OS << Indent + 2 << " return S;\n " ;
1135
+ }
1136
+ OS << Indent << " }\n " ;
1092
1137
}
1093
- OS << Indent << " }\n " ;
1094
1138
Indent -= 2 ;
1095
1139
OS << Indent << " }\n " ;
1096
1140
}
@@ -1267,7 +1311,8 @@ std::pair<unsigned, bool> FilterChooser::getDecoderIndex(DecoderSet &Decoders,
1267
1311
// FIXME: emitDecoder() function can take a buffer directly rather than
1268
1312
// a stream.
1269
1313
raw_svector_ostream S (Decoder);
1270
- bool HasCompleteDecoder = emitDecoder (S, indent (4 ), Opc);
1314
+ indent Indent (UseFnTableInDecodetoMCInst ? 2 : 4 );
1315
+ bool HasCompleteDecoder = emitDecoder (S, Indent, Opc);
1271
1316
1272
1317
// Using the full decoder string as the key value here is a bit
1273
1318
// heavyweight, but is effective. If the string comparisons become a
@@ -2371,7 +2416,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
2371
2416
<< " makeUp(insn, Len);" ;
2372
2417
}
2373
2418
OS << R"(
2374
- S = decodeToMCInst(S, DecodeIdx , insn, MI, Address, DisAsm, DecodeComplete);
2419
+ S = decodeToMCInst(DecodeIdx, S , insn, MI, Address, DisAsm, DecodeComplete);
2375
2420
assert(DecodeComplete);
2376
2421
2377
2422
LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
@@ -2393,7 +2438,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
2393
2438
MCInst TmpMI;
2394
2439
TmpMI.setOpcode(Opc);
2395
2440
bool DecodeComplete;
2396
- S = decodeToMCInst(S, DecodeIdx , insn, TmpMI, Address, DisAsm, DecodeComplete);
2441
+ S = decodeToMCInst(DecodeIdx, S , insn, TmpMI, Address, DisAsm, DecodeComplete);
2397
2442
LLVM_DEBUG(dbgs() << Loc << ": OPC_TryDecode: opcode " << Opc
2398
2443
<< ", using decoder " << DecodeIdx << ": ");
2399
2444
0 commit comments