@@ -83,6 +83,14 @@ static cl::opt<bool> LargeTable(
8383 " in the table instead of the default 16 bits." ),
8484 cl::init(false ), cl::cat(DisassemblerEmitterCat));
8585
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+
8694STATISTIC (NumEncodings, " Number of encodings considered" );
8795STATISTIC (NumEncodingsLackingDisasm,
8896 " Number of encodings without disassembler info" );
@@ -1066,31 +1074,67 @@ void DecoderEmitter::emitPredicateFunction(formatted_raw_ostream &OS,
10661074void DecoderEmitter::emitDecoderFunction (formatted_raw_ostream &OS,
10671075 DecoderSet &Decoders,
10681076 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+
10781080 // TODO: When InsnType is large, using uint64_t limits all fields to 64 bits
10791081 // It would be better for emitBinaryParser to use a 64-bit tmp whenever
10801082 // 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 " ;
10921137 }
1093- OS << Indent << " }\n " ;
10941138 Indent -= 2 ;
10951139 OS << Indent << " }\n " ;
10961140}
@@ -1267,7 +1311,8 @@ std::pair<unsigned, bool> FilterChooser::getDecoderIndex(DecoderSet &Decoders,
12671311 // FIXME: emitDecoder() function can take a buffer directly rather than
12681312 // a stream.
12691313 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);
12711316
12721317 // Using the full decoder string as the key value here is a bit
12731318 // heavyweight, but is effective. If the string comparisons become a
@@ -2371,7 +2416,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23712416 << " makeUp(insn, Len);" ;
23722417 }
23732418 OS << R"(
2374- S = decodeToMCInst(S, DecodeIdx , insn, MI, Address, DisAsm, DecodeComplete);
2419+ S = decodeToMCInst(DecodeIdx, S , insn, MI, Address, DisAsm, DecodeComplete);
23752420 assert(DecodeComplete);
23762421
23772422 LLVM_DEBUG(dbgs() << Loc << ": OPC_Decode: opcode " << Opc
@@ -2393,7 +2438,7 @@ static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,
23932438 MCInst TmpMI;
23942439 TmpMI.setOpcode(Opc);
23952440 bool DecodeComplete;
2396- S = decodeToMCInst(S, DecodeIdx , insn, TmpMI, Address, DisAsm, DecodeComplete);
2441+ S = decodeToMCInst(DecodeIdx, S , insn, TmpMI, Address, DisAsm, DecodeComplete);
23972442 LLVM_DEBUG(dbgs() << Loc << ": OPC_TryDecode: opcode " << Opc
23982443 << ", using decoder " << DecodeIdx << ": ");
23992444
0 commit comments