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 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 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 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"; }