diff --git a/llvm/include/llvm/MC/MCInstrInfo.h b/llvm/include/llvm/MC/MCInstrInfo.h --- a/llvm/include/llvm/MC/MCInstrInfo.h +++ b/llvm/include/llvm/MC/MCInstrInfo.h @@ -19,6 +19,7 @@ namespace llvm { +class FeatureBitset; class MCSubtargetInfo; //--------------------------------------------------------------------------- @@ -28,6 +29,8 @@ using ComplexDeprecationPredicate = bool (*)(MCInst &, const MCSubtargetInfo &, std::string &); + using OpcodeAvailabilityPredicate = bool (*)(unsigned Opcode, + const FeatureBitset &Features); private: const MCInstrDesc *LastDesc; // Raw array to allow static init'n @@ -41,19 +44,22 @@ // not, and return the reason for deprecation. const ComplexDeprecationPredicate *ComplexDeprecationInfos; unsigned NumOpcodes; // Number of entries in the desc array + OpcodeAvailabilityPredicate OpcodeAvailabilityInfo; public: /// Initialize MCInstrInfo, called by TableGen auto-generated routines. /// *DO NOT USE*. void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND, const uint8_t *DF, - const ComplexDeprecationPredicate *CDI, unsigned NO) { + const ComplexDeprecationPredicate *CDI, unsigned NO, + OpcodeAvailabilityPredicate OAI) { LastDesc = D + NO - 1; InstrNameIndices = NI; InstrNameData = ND; DeprecatedFeatures = DF; ComplexDeprecationInfos = CDI; NumOpcodes = NO; + OpcodeAvailabilityInfo = OAI; } unsigned getNumOpcodes() const { return NumOpcodes; } @@ -76,6 +82,11 @@ /// returns the reason in \p Info. bool getDeprecatedInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info) const; + + /// Returns true if all features required by opcode are provided. + bool isOpcodeAvailable(unsigned Opcode, const FeatureBitset &Features) const { + return OpcodeAvailabilityInfo(Opcode, Features); + } }; } // End llvm namespace diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.h b/llvm/tools/llvm-exegesis/lib/LlvmState.h --- a/llvm/tools/llvm-exegesis/lib/LlvmState.h +++ b/llvm/tools/llvm-exegesis/lib/LlvmState.h @@ -81,6 +81,11 @@ return *RegNameToRegNoMapping; } + bool isOpcodeAvailable(unsigned Opcode) const { + const auto &Features = getSubtargetInfo().getFeatureBits(); + return getInstrInfo().isOpcodeAvailable(Opcode, Features); + } + private: std::unique_ptr> createOpcodeNameToOpcodeIdxMapping() const; diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp --- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp +++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -46,6 +46,8 @@ std::vector AliasingInstructions; for (const unsigned OtherOpcode : Opcodes) { + if (!State.isOpcodeAvailable(OtherOpcode)) + continue; if (OtherOpcode == Instr->Description.getOpcode()) continue; const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -289,7 +289,8 @@ unsigned NumOpcodes = State.getInstrInfo().getNumOpcodes(); Result.reserve(NumOpcodes); for (unsigned I = 0, E = NumOpcodes; I < E; ++I) - Result.push_back(I); + if (State.isOpcodeAvailable(I)) + Result.push_back(I); return Result; } // Resolve opcode name -> opcode. diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -779,8 +779,7 @@ FeatureBitsets.erase( std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), FeatureBitsets.end()); - OS << "#ifndef NDEBUG\n" - << "// Feature bitsets.\n" + OS << "// Feature bitsets.\n" << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n" << " CEFBS_None,\n"; for (const auto &FeatureBitset : FeatureBitsets) { @@ -802,13 +801,9 @@ } OS << "},\n"; } - OS << "};\n" - << "#endif // NDEBUG\n\n"; + OS << "};\n\n"; - // Emit the predicate verifier. - OS << "void verifyInstructionPredicates(\n" - << " unsigned Opcode, const FeatureBitset &Features) {\n" - << "#ifndef NDEBUG\n" + OS << "const FeatureBitset &computeRequiredFeatures(unsigned Opcode) {\n" << " static " << getMinimalTypeForRange(FeatureBitsets.size()) << " RequiredFeaturesRefs[] = {\n"; unsigned InstIdx = 0; @@ -829,10 +824,27 @@ } OS << " };\n\n"; OS << " assert(Opcode < " << InstIdx << ");\n"; + OS << " return FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n"; + OS << "}\n\n"; + + // Emit the predicate verifiers. + OS << "bool isOpcodeAvailable(\n" + << " unsigned Opcode, const FeatureBitset &Features) {\n"; + OS << " FeatureBitset AvailableFeatures = " + "computeAvailableFeatures(Features);\n"; + OS << " const FeatureBitset &RequiredFeatures = " + "computeRequiredFeatures(Opcode);\n"; + OS << " return (AvailableFeatures & RequiredFeatures) == " + "RequiredFeatures;\n"; + OS << "}\n\n"; + + OS << "void verifyInstructionPredicates(\n" + << " unsigned Opcode, const FeatureBitset &Features) {\n" + << "#ifndef NDEBUG\n"; OS << " FeatureBitset AvailableFeatures = " "computeAvailableFeatures(Features);\n"; OS << " const FeatureBitset &RequiredFeatures = " - "FeatureBitsets[RequiredFeaturesRefs[Opcode]];\n"; + "computeRequiredFeatures(Opcode);\n"; OS << " FeatureBitset MissingFeatures =\n" << " (AvailableFeatures & RequiredFeatures) ^\n" << " RequiredFeatures;\n" @@ -1003,6 +1015,10 @@ // MCInstrInfo initialization routine. Records.startTimer("Emit initialization routine"); + OS << "namespace " << TargetName << "_MC {\n"; + OS << "bool isOpcodeAvailable(unsigned Opcode, const FeatureBitset " + "&Features);\n"; + OS << "} // end namespace " << TargetName << "_MC\n"; OS << "static inline void Init" << TargetName << "MCInstrInfo(MCInstrInfo *II) {\n"; OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " << TargetName @@ -1015,7 +1031,8 @@ OS << TargetName << "InstrComplexDeprecationInfos, "; else OS << "nullptr, "; - OS << NumberedInstructions.size() << ");\n}\n\n"; + OS << NumberedInstructions.size() << ", " + << "&" << TargetName << "_MC::isOpcodeAvailable);\n}\n\n"; OS << "} // end namespace llvm\n"; @@ -1062,6 +1079,12 @@ if (HasComplexDeprecationInfos) OS << "extern const MCInstrInfo::ComplexDeprecationPredicate " << TargetName << "InstrComplexDeprecationInfos[];\n"; + + OS << "namespace " << TargetName << "_MC {\n"; + OS << "bool isOpcodeAvailable(unsigned Opcode, const FeatureBitset " + "&Features);\n"; + OS << "} // end namespace " << TargetName << "_MC\n"; + OS << ClassName << "::" << ClassName << "(unsigned CFSetupOpcode, unsigned CFDestroyOpcode, unsigned " "CatchRetOpcode, unsigned ReturnOpcode)\n" @@ -1077,7 +1100,8 @@ OS << TargetName << "InstrComplexDeprecationInfos, "; else OS << "nullptr, "; - OS << NumberedInstructions.size() << ");\n}\n"; + OS << NumberedInstructions.size() << ", " + << "&" << TargetName << "_MC::isOpcodeAvailable);\n}\n"; OS << "} // end namespace llvm\n"; OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";