diff options
| author | Stanislav Mekhanoshin <Stanislav.Mekhanoshin@amd.com> | 2019-03-11 17:04:35 +0000 |
|---|---|---|
| committer | Stanislav Mekhanoshin <Stanislav.Mekhanoshin@amd.com> | 2019-03-11 17:04:35 +0000 |
| commit | e98944ed47acd04279184343017aa2bf34999111 (patch) | |
| tree | 2cc1367f23c408db49c2c5d03aa5151d809ebdf3 /llvm/utils/TableGen/CodeEmitterGen.cpp | |
| parent | b94c24e2acc748b47f029f66b0e806472fffffbe (diff) | |
| download | bcm5719-llvm-e98944ed47acd04279184343017aa2bf34999111.tar.gz bcm5719-llvm-e98944ed47acd04279184343017aa2bf34999111.zip | |
Use bitset for assembler predicates
AMDGPU target run out of Subtarget feature flags hitting the limit of 64.
AssemblerPredicates uses at most uint64_t for their representation.
At the same time CodeGen has exhausted this a long time ago and switched
to a FeatureBitset with the current limit of 192 bits.
This patch completes transition to the bitset for feature bits extending
it to asm matcher and MC code emitter.
Differential Revision: https://reviews.llvm.org/D59002
llvm-svn: 355839
Diffstat (limited to 'llvm/utils/TableGen/CodeEmitterGen.cpp')
| -rw-r--r-- | llvm/utils/TableGen/CodeEmitterGen.cpp | 99 |
1 files changed, 85 insertions, 14 deletions
diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp index ec16be14c6a..da65763905a 100644 --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -15,6 +15,7 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" #include "SubtargetFeatureInfo.h" +#include "Types.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" @@ -228,6 +229,14 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, 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; +} + void CodeEmitterGen::run(raw_ostream &o) { CodeGenTarget Target(Records); std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); @@ -326,8 +335,8 @@ void CodeEmitterGen::run(raw_ostream &o) { << "#include <sstream>\n\n"; // Emit the subtarget feature enumeration. - SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures, - o); + SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, + o); // Emit the name table for error messages. o << "#ifndef NDEBUG\n"; @@ -339,35 +348,97 @@ void CodeEmitterGen::run(raw_ostream &o) { 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 (const 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" + << "const static 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, uint64_t AvailableFeatures) const {\n" + << " const MCInst &Inst, const FeatureBitset &AvailableFeatures) const {\n" << "#ifndef NDEBUG\n" - << " static uint64_t RequiredFeatures[] = {\n"; + << " static " << getMinimalTypeForRange(FeatureBitsets.size()) + << " RequiredFeaturesRefs[] = {\n"; unsigned InstIdx = 0; for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { - o << " "; + 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.getEnumName() << " | "; + if (I != SubtargetFeatures.end()) { + o << '_' << I->second.TheDef->getName(); + NumPredicates++; + } } - o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; + if (!NumPredicates) + o << "_None"; + o << ", // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; InstIdx++; } o << " };\n\n"; o << " assert(Inst.getOpcode() < " << InstIdx << ");\n"; - o << " uint64_t MissingFeatures =\n" - << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n" - << " RequiredFeatures[Inst.getOpcode()];\n" - << " if (MissingFeatures) {\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; i < 8 * sizeof(MissingFeatures); ++i)\n" - << " if (MissingFeatures & (1ULL << i))\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());\n" |

