diff options
| author | David Green <david.green@arm.com> | 2022-07-13 12:53:32 +0100 |
|---|---|---|
| committer | David Green <david.green@arm.com> | 2022-07-13 12:53:32 +0100 |
| commit | e2fb8c0f4b940e0285ee36c112469fa75d4b60ff (patch) | |
| tree | 9ddad5979a2ef957f57ef996caa3a953089305fd /llvm/utils/TableGen/CodeEmitterGen.cpp | |
| parent | 35efe1d806358df6e45dde8218a143138dd8f0a8 (diff) | |
Move instruction predicate verification to emitInstruction
D25618 added a method to verify the instruction predicates for an
emitted instruction, through verifyInstructionPredicates added into
<Target>MCCodeEmitter::encodeInstruction. This is a very useful idea,
but the implementation inside MCCodeEmitter made it only fire for object
files, not assembly which most of the llvm test suite uses.
This patch moves the code into the <Target>_MC::verifyInstructionPredicates
method, inside the InstrInfo. The allows it to be called from other
places, such as in this patch where it is called from the
<Target>AsmPrinter::emitInstruction methods which should trigger for
both assembly and object files. It can also be called from other places
such as verifyInstruction, but that is not done here (it tends to catch
errors earlier, but in reality just shows all the mir tests that have
incorrect feature predicates). The interface was also simplified
slightly, moving computeAvailableFeatures into the function so that it
does not need to be called externally.
The ARM, AMDGPU (but not R600), AVR, Mips and X86 backends all currently
show errors in the test-suite, so have been disabled with FIXME
comments.
Differential Revision: https://reviews.llvm.org/D129506
Diffstat (limited to 'llvm/utils/TableGen/CodeEmitterGen.cpp')
| -rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 133 |
1 files changed, 0 insertions, 133 deletions
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index 2b9931b23c11..1d00c3cfd069 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -332,14 +332,6 @@ std::string CodeEmitterGen::getInstructionCaseForEncoding(Record *R, Record *Enc return Case; } -static std::string -getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) { - std::string Name = "CEFBS"; - for (const auto &Feature : FeatureBitset) - Name += ("_" + Feature->getName()).str(); - return Name; -} - static void emitInstBits(raw_ostream &OS, const APInt &Bits) { for (unsigned I = 0; I < Bits.getNumWords(); ++I) OS << ((I > 0) ? ", " : "") << "UINT64_C(" << utostr(Bits.getRawData()[I]) @@ -530,131 +522,6 @@ void CodeEmitterGen::run(raw_ostream &o) { o << " return Value;\n"; o << "}\n\n"; } - - const auto &All = SubtargetFeatureInfo::getAll(Records); - std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures; - SubtargetFeatures.insert(All.begin(), All.end()); - - o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n" - << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n" - << "#include <sstream>\n\n"; - - // Emit the subtarget feature enumeration. - SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, - o); - - // Emit the name table for error messages. - o << "#ifndef NDEBUG\n"; - SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o); - o << "#endif // NDEBUG\n"; - - // Emit the available features compute function. - SubtargetFeatureInfo::emitComputeAssemblerAvailableFeatures( - Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", - SubtargetFeatures, o); - - std::vector<std::vector<Record *>> FeatureBitsets; - for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - FeatureBitsets.emplace_back(); - for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { - const auto &I = SubtargetFeatures.find(Predicate); - if (I != SubtargetFeatures.end()) - FeatureBitsets.back().push_back(I->second.TheDef); - } - } - - llvm::sort(FeatureBitsets, [&](const std::vector<Record *> &A, - const std::vector<Record *> &B) { - if (A.size() < B.size()) - return true; - if (A.size() > B.size()) - return false; - for (auto Pair : zip(A, B)) { - if (std::get<0>(Pair)->getName() < std::get<1>(Pair)->getName()) - return true; - if (std::get<0>(Pair)->getName() > std::get<1>(Pair)->getName()) - return false; - } - return false; - }); - FeatureBitsets.erase( - std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), - FeatureBitsets.end()); - o << "#ifndef NDEBUG\n" - << "// Feature bitsets.\n" - << "enum : " << getMinimalTypeForRange(FeatureBitsets.size()) << " {\n" - << " CEFBS_None,\n"; - for (const auto &FeatureBitset : FeatureBitsets) { - if (FeatureBitset.empty()) - continue; - o << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; - } - o << "};\n\n" - << "static constexpr FeatureBitset FeatureBitsets[] = {\n" - << " {}, // CEFBS_None\n"; - for (const auto &FeatureBitset : FeatureBitsets) { - if (FeatureBitset.empty()) - continue; - o << " {"; - for (const auto &Feature : FeatureBitset) { - const auto &I = SubtargetFeatures.find(Feature); - assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); - o << I->second.getEnumBitName() << ", "; - } - o << "},\n"; - } - o << "};\n" - << "#endif // NDEBUG\n\n"; - - - // Emit the predicate verifier. - o << "void " << Target.getName() - << "MCCodeEmitter::verifyInstructionPredicates(\n" - << " const MCInst &Inst, const FeatureBitset &AvailableFeatures) const {\n" - << "#ifndef NDEBUG\n" - << " static " << getMinimalTypeForRange(FeatureBitsets.size()) - << " RequiredFeaturesRefs[] = {\n"; - unsigned InstIdx = 0; - for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - o << " CEFBS"; - unsigned NumPredicates = 0; - for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { - const auto &I = SubtargetFeatures.find(Predicate); - if (I != SubtargetFeatures.end()) { - o << '_' << I->second.TheDef->getName(); - NumPredicates++; - } - } - if (!NumPredicates) - o << "_None"; - o << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; - InstIdx++; - } - o << " };\n\n"; - o << " assert(Inst.getOpcode() < " << InstIdx << ");\n"; - o << " const FeatureBitset &RequiredFeatures = " - "FeatureBitsets[RequiredFeaturesRefs[Inst.getOpcode()]];\n"; - o << " FeatureBitset MissingFeatures =\n" - << " (AvailableFeatures & RequiredFeatures) ^\n" - << " RequiredFeatures;\n" - << " if (MissingFeatures.any()) {\n" - << " std::ostringstream Msg;\n" - << " Msg << \"Attempting to emit \" << " - "MCII.getName(Inst.getOpcode()).str()\n" - << " << \" instruction but the \";\n" - << " for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i)\n" - << " if (MissingFeatures.test(i))\n" - << " Msg << SubtargetFeatureNames[i] << \" \";\n" - << " Msg << \"predicate(s) are not met\";\n" - << " report_fatal_error(Msg.str().c_str());\n" - << " }\n" - << "#else\n" - << " // Silence unused variable warning on targets that don't use MCII for " - "other purposes (e.g. BPF).\n" - << " (void)MCII;\n" - << "#endif // NDEBUG\n"; - o << "}\n"; - o << "#endif\n"; } } // end anonymous namespace |
