[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