diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -415,6 +415,8 @@ void declareSubtargetFeature(Record *Predicate); + unsigned declareHwModeCheck(StringRef HwModeFeatures); + MatchTable buildMatchTable(MutableArrayRef Rules, bool Optimize, bool WithCoverage); @@ -1917,6 +1919,9 @@ if (auto Error = importRulePredicates(M, Predicates)) return std::move(Error); + if (!P.getHwModeFeatures().empty()) + M.addHwModeIdx(declareHwModeCheck(P.getHwModeFeatures())); + // Next, analyze the pattern operators. TreePatternNode *Src = P.getSrcPattern(); TreePatternNode *Dst = P.getDstPattern(); @@ -2523,6 +2528,10 @@ SubtargetFeatures.try_emplace(Predicate, Predicate, SubtargetFeatures.size()); } +unsigned GlobalISelEmitter::declareHwModeCheck(StringRef HwModeFeatures) { + return HwModes.emplace(HwModeFeatures.str(), HwModes.size()).first->second; +} + } // end anonymous namespace //===----------------------------------------------------------------------===// diff --git a/llvm/utils/TableGen/GlobalISelMatchTable.h b/llvm/utils/TableGen/GlobalISelMatchTable.h --- a/llvm/utils/TableGen/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/GlobalISelMatchTable.h @@ -59,7 +59,8 @@ //===- Helper functions ---------------------------------------------------===// -std::string getNameForFeatureBitset(const std::vector &FeatureBitset); +std::string getNameForFeatureBitset(const std::vector &FeatureBitset, + int HwModeIdx); /// Takes a sequence of \p Rules and group them based on the predicates /// they share. \p MatcherStorage is used as a memory container @@ -458,6 +459,9 @@ /// ID for the next temporary register ID allocated with allocateTempRegID() unsigned NextTempRegID; + // HwMode predicate index for this rule. -1 if no HwMode. + int HwModeIdx = -1; + /// Current GISelFlags GISelFlags Flags = 0; @@ -498,6 +502,9 @@ void addRequiredFeature(Record *Feature); const std::vector &getRequiredFeatures() const; + void addHwModeIdx(unsigned Idx) { HwModeIdx = Idx; } + int getHwModeIdx() const { return HwModeIdx; } + void addRequiredSimplePredicate(StringRef PredName); const std::vector &getRequiredSimplePredicates(); diff --git a/llvm/utils/TableGen/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/GlobalISelMatchTable.cpp --- a/llvm/utils/TableGen/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/GlobalISelMatchTable.cpp @@ -43,11 +43,13 @@ //===- Helpers ------------------------------------------------------------===// -std::string -getNameForFeatureBitset(const std::vector &FeatureBitset) { +std::string getNameForFeatureBitset(const std::vector &FeatureBitset, + int HwModeIdx) { std::string Name = "GIFBS"; for (const auto &Feature : FeatureBitset) Name += ("_" + Feature->getName()).str(); + if (HwModeIdx >= 0) + Name += ("_HwMode" + std::to_string(HwModeIdx)); return Name; } @@ -851,9 +853,10 @@ << MatchTable::Comment(("Rule ID " + Twine(RuleID) + " //").str()) << MatchTable::LineBreak; - if (!RequiredFeatures.empty()) { + if (!RequiredFeatures.empty() || HwModeIdx >= 0) { Table << MatchTable::Opcode("GIM_CheckFeatures") - << MatchTable::NamedValue(getNameForFeatureBitset(RequiredFeatures)) + << MatchTable::NamedValue( + getNameForFeatureBitset(RequiredFeatures, HwModeIdx)) << MatchTable::LineBreak; } diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h --- a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h +++ b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h @@ -223,6 +223,8 @@ // Map of predicates to their subtarget features. SubtargetFeatureInfoMap SubtargetFeatures; + + std::map HwModes; }; } // namespace llvm diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp --- a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp @@ -15,7 +15,7 @@ void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl( raw_ostream &OS, ArrayRef Rules) { SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures, - OS); + OS, &HwModes); // Separate subtarget features by how often they must be recomputed. SubtargetFeatureInfoMap ModuleFeatures; @@ -33,7 +33,7 @@ SubtargetFeatureInfo::emitComputeAvailableFeatures( getTarget().getName(), getClassName(), "computeAvailableModuleFeatures", - ModuleFeatures, OS); + ModuleFeatures, OS, "", &HwModes); OS << "void " << getClassName() << "::setupGeneratedPerFunctionState(MachineFunction &MF) {\n" @@ -49,24 +49,27 @@ // Emit a table containing the PredicateBitsets objects needed by the matcher // and an enum for the matcher to reference them with. - std::vector> FeatureBitsets; + std::vector, int>> FeatureBitsets; FeatureBitsets.reserve(Rules.size()); for (auto &Rule : Rules) - FeatureBitsets.push_back(Rule.getRequiredFeatures()); - llvm::sort(FeatureBitsets, [&](const std::vector &A, - const std::vector &B) { - if (A.size() < B.size()) - return true; - if (A.size() > B.size()) - return false; - for (auto [First, Second] : zip(A, B)) { - if (First->getName() < Second->getName()) - return true; - if (First->getName() > Second->getName()) - return false; - } - return false; - }); + FeatureBitsets.emplace_back(Rule.getRequiredFeatures(), + Rule.getHwModeIdx()); + llvm::sort(FeatureBitsets, + [&](const std::pair, int> &A, + const std::pair, int> &B) { + if (A.first.size() < B.first.size()) + return true; + if (A.first.size() > B.first.size()) + return false; + for (auto [First, Second] : zip(A.first, B.first)) { + if (First->getName() < Second->getName()) + return true; + if (First->getName() > Second->getName()) + return false; + } + + return (A.second < B.second); + }); FeatureBitsets.erase( std::unique(FeatureBitsets.begin(), FeatureBitsets.end()), FeatureBitsets.end()); @@ -74,22 +77,28 @@ << "enum {\n" << " GIFBS_Invalid,\n"; for (const auto &FeatureBitset : FeatureBitsets) { - if (FeatureBitset.empty()) + if (FeatureBitset.first.empty() && FeatureBitset.second < 0) continue; - OS << " " << getNameForFeatureBitset(FeatureBitset) << ",\n"; + OS << " " + << getNameForFeatureBitset(FeatureBitset.first, FeatureBitset.second) + << ",\n"; } OS << "};\n" << "constexpr static PredicateBitset FeatureBitsets[] {\n" << " {}, // GIFBS_Invalid\n"; for (const auto &FeatureBitset : FeatureBitsets) { - if (FeatureBitset.empty()) + if (FeatureBitset.first.empty() && FeatureBitset.second < 0) continue; OS << " {"; - for (const auto &Feature : FeatureBitset) { + for (const auto &Feature : FeatureBitset.first) { const auto &I = SubtargetFeatures.find(Feature); assert(I != SubtargetFeatures.end() && "Didn't import predicate?"); OS << I->second.getEnumBitName() << ", "; } + // HwModeIdx + if (FeatureBitset.second >= 0) { + OS << "Feature_HwMode" << FeatureBitset.second << "Bit, "; + } OS << "},\n"; } OS << "};\n\n"; @@ -184,9 +193,9 @@ void GlobalISelMatchTableExecutorEmitter::emitPredicateBitset( raw_ostream &OS, StringRef IfDefName) { + unsigned Size = SubtargetFeatures.size() + HwModes.size(); OS << "#ifdef " << IfDefName << "\n" - << "const unsigned MAX_SUBTARGET_PREDICATES = " << SubtargetFeatures.size() - << ";\n" + << "const unsigned MAX_SUBTARGET_PREDICATES = " << Size << ";\n" << "using PredicateBitset = " "llvm::Bitset;\n" << "#endif // ifdef " << IfDefName << "\n\n"; diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.h b/llvm/utils/TableGen/SubtargetFeatureInfo.h --- a/llvm/utils/TableGen/SubtargetFeatureInfo.h +++ b/llvm/utils/TableGen/SubtargetFeatureInfo.h @@ -55,7 +55,8 @@ /// This version emits the bit index for the feature and can therefore support /// more than 64 feature bits. static void emitSubtargetFeatureBitEnumeration( - const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); + const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, + const std::map *HwModes = nullptr); static void emitNameTable(SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS); @@ -74,11 +75,12 @@ /// \param SubtargetFeatures A map of TableGen records to the /// SubtargetFeatureInfo equivalent. /// \param ExtraParams Additional arguments to the generated function. - static void - emitComputeAvailableFeatures(StringRef TargetName, StringRef ClassName, - StringRef FuncName, - SubtargetFeatureInfoMap &SubtargetFeatures, - raw_ostream &OS, StringRef ExtraParams = ""); + /// \param HwModes Map of HwMode conditions to check. + static void emitComputeAvailableFeatures( + StringRef TargetName, StringRef ClassName, StringRef FuncName, + const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, + StringRef ExtraParams = "", + const std::map *HwModes = nullptr); /// Emit the function to compute the list of available features given a /// subtarget. diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp --- a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp +++ b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp @@ -47,15 +47,29 @@ } void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration( - const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) { + const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, + const std::map *HwModes) { OS << "// Bits for subtarget features that participate in " << "instruction matching.\n"; - OS << "enum SubtargetFeatureBits : " - << getMinimalTypeForRange(SubtargetFeatures.size()) << " {\n"; + unsigned Size = SubtargetFeatures.size(); + if (HwModes) + Size += HwModes->size(); + + OS << "enum SubtargetFeatureBits : " << getMinimalTypeForRange(Size) + << " {\n"; for (const auto &SF : SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; OS << " " << SFI.getEnumBitName() << " = " << SFI.Index << ",\n"; } + + if (HwModes) { + unsigned Offset = SubtargetFeatures.size(); + for (const auto &M : *HwModes) { + OS << " Feature_HwMode" << M.second << "Bit = " << (M.second + Offset) + << ",\n"; + } + } + OS << "};\n\n"; } @@ -87,8 +101,8 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures( StringRef TargetName, StringRef ClassName, StringRef FuncName, - SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, - StringRef ExtraParams) { + const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS, + StringRef ExtraParams, const std::map *HwModes) { OS << "PredicateBitset " << ClassName << "::\n" << FuncName << "(const " << TargetName << "Subtarget *Subtarget"; if (!ExtraParams.empty()) @@ -103,6 +117,14 @@ OS << " if (" << CondStr << ")\n"; OS << " Features.set(" << SFI.getEnumBitName() << ");\n"; } + + if (HwModes) { + for (const auto &M : *HwModes) { + OS << " if (" << M.first << ")\n"; + OS << " Features.set(Feature_HwMode" << M.second << "Bit);\n"; + } + } + OS << " return Features;\n"; OS << "}\n\n"; }