[llvm] [TableGen] Use bitwise operations to access HwMode ID. (PR #88377)

Jason Eckhardt via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 17 20:43:51 PDT 2024


================
@@ -1781,13 +1781,68 @@ void SubtargetEmitter::EmitHwModeCheck(const std::string &ClassName,
   if (CGH.getNumModeIds() == 1)
     return;
 
-  OS << "unsigned " << ClassName << "::getHwMode() const {\n";
+  // Collect all HwModes and related features defined in the TD files,
+  // and store them in bit format.
+  unsigned ValueTypeModes = 0;
+  unsigned RegInfoModes = 0;
+  unsigned EncodingInfoModes = 0;
+  for (const auto &MS : CGH.getHwModeSelects()) {
+    for (const HwModeSelect::PairType &P : MS.second.Items) {
+      if (P.first == DefaultMode)
+        continue;
+      if (P.second->isSubClassOf("ValueType")) {
+        ValueTypeModes |= (1 << (P.first - 1));
+      } else if (P.second->isSubClassOf("RegInfo") ||
+                 P.second->isSubClassOf("SubRegRange")) {
+        RegInfoModes |= (1 << (P.first - 1));
+      } else if (P.second->isSubClassOf("InstructionEncoding")) {
+        EncodingInfoModes |= (1 << (P.first - 1));
+      }
+    }
+  }
+
+  // Start emitting for getHwModeSet().
+  OS << "unsigned " << ClassName << "::getHwModeSet() const {\n";
+  OS << "  // Collect HwModes and store them in bits\n";
+  OS << "  unsigned Modes = 0;\n";
   for (unsigned M = 1, NumModes = CGH.getNumModeIds(); M != NumModes; ++M) {
     const HwMode &HM = CGH.getMode(M);
-    OS << "  if (checkFeatures(\"" << HM.Features << "\")) return " << M
-       << ";\n";
+    OS << "  if (checkFeatures(\"" << HM.Features << "\")) Modes |= (1 << "
+       << (M - 1) << ");\n";
   }
-  OS << "  return 0;\n}\n";
+  OS << "  return Modes;\n}\n";
+  // End emitting for getHwModeSet().
+
+  // Start emitting for getHwMode().
+  OS << "unsigned " << ClassName
+     << "::getHwMode(enum HwModeType type) const {\n";
+  OS << "  unsigned Modes = getHwModeSet();\n";
+  OS << "\n  if(!Modes)\n    return Modes;\n\n";
+  OS << "  switch (type) {\n";
+  OS << "  case HwMode_Default:\n    return llvm::countr_zero(Modes) + 1;\n"
+     << "    break;\n";
+  OS << "  case HwMode_ValueType: {\n    Modes &= " << ValueTypeModes << ";\n"
+     << "    if (!Modes)\n      return Modes;\n"
+     << "    if (!llvm::has_single_bit<unsigned>(Modes))\n"
+     << "      llvm_unreachable(\"Two or more HwModes for ValueType were "
+        "found!\");\n"
+     << "    return llvm::countr_zero(Modes) + 1;\n  }\n";
+  OS << "  case HwMode_RegInfo: {\n    Modes &= " << RegInfoModes << ";\n"
+     << "    if (!Modes)\n      return Modes;\n"
+     << "    if (!llvm::has_single_bit<unsigned>(Modes))\n"
+     << "      llvm_unreachable(\"Two or more HwModes for RegInfo were "
+        "found!\");\n"
+     << "    return llvm::countr_zero(Modes) + 1;\n  }\n";
+  OS << "  case HwMode_EncodingInfo: {\n    Modes &= " << EncodingInfoModes
+     << ";\n"
+     << "    if (!Modes)\n      return Modes;\n"
+     << "    if (!llvm::has_single_bit<unsigned>(Modes))\n"
+     << "      llvm_unreachable(\"Two or more HwModes for Encoding were "
+        "found!\");\n"
+     << "    return llvm::countr_zero(Modes) + 1;\n  }\n";
----------------
nvjle wrote:

All three of the non-Default cases are essentially identical other than the mask value. We should collapse this into ~1/3 the code.

https://github.com/llvm/llvm-project/pull/88377


More information about the llvm-commits mailing list