[llvm] 8b82ae0 - [GlobalISel][RISCV][TableGen] Teach GlobalISelEmitter about HwMode.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 23 21:16:00 PDT 2023
Author: Craig Topper
Date: 2023-08-23T21:14:16-07:00
New Revision: 8b82ae0b8d523f2de3a1dabad9d006b57917af71
URL: https://github.com/llvm/llvm-project/commit/8b82ae0b8d523f2de3a1dabad9d006b57917af71
DIFF: https://github.com/llvm/llvm-project/commit/8b82ae0b8d523f2de3a1dabad9d006b57917af71.diff
LOG: [GlobalISel][RISCV][TableGen] Teach GlobalISelEmitter about HwMode.
Similar to SelectionDAG, this patch treats HwMode as an additional
predicate that needs to be satisfied for GIM_CheckFeatures.
The existing predicate passes around Record * that point to predicate
records. While HwMode expansion creates a string that needs to be
checked.
Each HwMode predicate string is uniqued by a new map that assigns
it an index. Each Rule stores the index, or -1 if HwMode doesn't
apply.
The HwMode indices each create a new Predicate feature bit and the
check string from the HwMode is used to set the feature bit.
GIM_CheckFeatures is emitted when the rule has Predicates or the HwModeIdx
is not -1.
Reviewed By: arsenm
Differential Revision: https://reviews.llvm.org/D158660
Added:
Modified:
llvm/utils/TableGen/GlobalISelEmitter.cpp
llvm/utils/TableGen/GlobalISelMatchTable.cpp
llvm/utils/TableGen/GlobalISelMatchTable.h
llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp
llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h
llvm/utils/TableGen/SubtargetFeatureInfo.cpp
llvm/utils/TableGen/SubtargetFeatureInfo.h
Removed:
################################################################################
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 1c368606f47846..ef30e947a293ce 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -415,6 +415,8 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
void declareSubtargetFeature(Record *Predicate);
+ unsigned declareHwModeCheck(StringRef HwModeFeatures);
+
MatchTable buildMatchTable(MutableArrayRef<RuleMatcher> Rules, bool Optimize,
bool WithCoverage);
@@ -1917,6 +1919,9 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
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 @@ void GlobalISelEmitter::declareSubtargetFeature(Record *Predicate) {
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.cpp b/llvm/utils/TableGen/GlobalISelMatchTable.cpp
index b5c92cb8086e61..2049147d4057be 100644
--- a/llvm/utils/TableGen/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/GlobalISelMatchTable.cpp
@@ -43,11 +43,13 @@ std::string getMatchOpcodeForImmPredicate(const TreePredicateFn &Predicate) {
//===- Helpers ------------------------------------------------------------===//
-std::string
-getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset) {
+std::string getNameForFeatureBitset(const std::vector<Record *> &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 @@ void RuleMatcher::emit(MatchTable &Table) {
<< 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/GlobalISelMatchTable.h b/llvm/utils/TableGen/GlobalISelMatchTable.h
index 46490e8e3fb18c..bf86e60b36f7aa 100644
--- a/llvm/utils/TableGen/GlobalISelMatchTable.h
+++ b/llvm/utils/TableGen/GlobalISelMatchTable.h
@@ -59,7 +59,8 @@ using GISelFlags = std::uint16_t;
//===- Helper functions ---------------------------------------------------===//
-std::string getNameForFeatureBitset(const std::vector<Record *> &FeatureBitset);
+std::string getNameForFeatureBitset(const std::vector<Record *> &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 @@ class RuleMatcher : public Matcher {
/// 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 @@ class RuleMatcher : public Matcher {
void addRequiredFeature(Record *Feature);
const std::vector<Record *> &getRequiredFeatures() const;
+ void addHwModeIdx(unsigned Idx) { HwModeIdx = Idx; }
+ int getHwModeIdx() const { return HwModeIdx; }
+
void addRequiredSimplePredicate(StringRef PredName);
const std::vector<std::string> &getRequiredSimplePredicates();
diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp
index cf9c261cb0be23..c6cd3240a94e7b 100644
--- a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.cpp
@@ -15,7 +15,7 @@ using namespace llvm::gi;
void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
raw_ostream &OS, ArrayRef<RuleMatcher> Rules) {
SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(SubtargetFeatures,
- OS);
+ OS, &HwModes);
// Separate subtarget features by how often they must be recomputed.
SubtargetFeatureInfoMap ModuleFeatures;
@@ -33,7 +33,7 @@ void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
SubtargetFeatureInfo::emitComputeAvailableFeatures(
getTarget().getName(), getClassName(), "computeAvailableModuleFeatures",
- ModuleFeatures, OS);
+ ModuleFeatures, OS, "", &HwModes);
OS << "void " << getClassName()
<< "::setupGeneratedPerFunctionState(MachineFunction &MF) {\n"
@@ -49,24 +49,27 @@ void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
// Emit a table containing the PredicateBitsets objects needed by the matcher
// and an enum for the matcher to reference them with.
- std::vector<std::vector<Record *>> FeatureBitsets;
+ std::vector<std::pair<std::vector<Record *>, int>> FeatureBitsets;
FeatureBitsets.reserve(Rules.size());
for (auto &Rule : Rules)
- FeatureBitsets.push_back(Rule.getRequiredFeatures());
- 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 [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<std::vector<Record *>, int> &A,
+ const std::pair<std::vector<Record *>, 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 @@ void GlobalISelMatchTableExecutorEmitter::emitSubtargetFeatureBitsetImpl(
<< "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::emitExecutorImpl(
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<MAX_SUBTARGET_PREDICATES>;\n"
<< "#endif // ifdef " << IfDefName << "\n\n";
diff --git a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h
index 0cde21f5f7d9b2..13193ff8cc9fef 100644
--- a/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h
+++ b/llvm/utils/TableGen/GlobalISelMatchTableExecutorEmitter.h
@@ -223,6 +223,8 @@ class GlobalISelMatchTableExecutorEmitter {
// Map of predicates to their subtarget features.
SubtargetFeatureInfoMap SubtargetFeatures;
+
+ std::map<std::string, unsigned> HwModes;
};
} // namespace llvm
diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
index 15144e821965a8..52afb4d8916279 100644
--- a/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
+++ b/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
@@ -47,15 +47,29 @@ SubtargetFeatureInfo::getAll(const RecordKeeper &Records) {
}
void SubtargetFeatureInfo::emitSubtargetFeatureBitEnumeration(
- const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS) {
+ const SubtargetFeatureInfoMap &SubtargetFeatures, raw_ostream &OS,
+ const std::map<std::string, unsigned> *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::emitNameTable(
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<std::string, unsigned> *HwModes) {
OS << "PredicateBitset " << ClassName << "::\n"
<< FuncName << "(const " << TargetName << "Subtarget *Subtarget";
if (!ExtraParams.empty())
@@ -103,6 +117,14 @@ void SubtargetFeatureInfo::emitComputeAvailableFeatures(
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";
}
diff --git a/llvm/utils/TableGen/SubtargetFeatureInfo.h b/llvm/utils/TableGen/SubtargetFeatureInfo.h
index 6c9dd6c3ad228e..9401004484350a 100644
--- a/llvm/utils/TableGen/SubtargetFeatureInfo.h
+++ b/llvm/utils/TableGen/SubtargetFeatureInfo.h
@@ -55,7 +55,8 @@ struct SubtargetFeatureInfo {
/// 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<std::string, unsigned> *HwModes = nullptr);
static void emitNameTable(SubtargetFeatureInfoMap &SubtargetFeatures,
raw_ostream &OS);
@@ -74,11 +75,12 @@ struct SubtargetFeatureInfo {
/// \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<std::string, unsigned> *HwModes = nullptr);
/// Emit the function to compute the list of available features given a
/// subtarget.
More information about the llvm-commits
mailing list