[llvm] [TableGen] Rework `EmitIntrinsicToBuiltinMap` (PR #104681)

Artem Belevich via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 17:02:10 PDT 2024


================
@@ -615,70 +617,171 @@ void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
       PrintFatalError(Int.TheDef->getLoc(),
                       "Intrinsic '" + Int.TheDef->getName() + "': duplicate " +
                           CompilerName + " builtin name!");
-    Table.GetOrAddStringOffset(BuiltinName);
-  }
 
-  OS << "// Get the LLVM intrinsic that corresponds to a builtin.\n";
-  OS << "// This is used by the C front-end.  The builtin name is passed\n";
-  OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
-  OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
-  OS << "#ifdef GET_LLVM_INTRINSIC_FOR_" << UpperCompilerName << "_BUILTIN\n";
+    OldTable.GetOrAddStringOffset(BuiltinName);
+  }
 
-  OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
-     << "Builtin(const char "
-     << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
+  // For each target, determine the common prefix for all the builtins for that
+  // target. Populate the string table with the names of all the builtins after
+  // removing this common prefix.
+  DenseMap<StringRef, StringRef> CommonPrefixMap;
+  StringToOffsetTable Table;
+  for (const auto &[TargetPrefix, Map] : BuiltinMap) {
+    // The Map is guaranteed to be non-empty here.
+    StringRef CommonPrefix = Map.begin()->first;
+    for (auto &[BuiltinName, EnumName] : Map) {
+      // Update the common prefix.
+      const char *Mismatch = mismatch(CommonPrefix, BuiltinName).first;
+      CommonPrefix = CommonPrefix.take_front(Mismatch - CommonPrefix.begin());
+      if (CommonPrefix.empty())
+        break;
+    }
+    CommonPrefixMap[TargetPrefix] = CommonPrefix;
+    for (auto &[BuiltinName, EnumName] : Map) {
+      StringRef Suffix = BuiltinName.substr(CommonPrefix.size());
+      if (!Suffix.empty())
+        Table.GetOrAddStringOffset(Suffix);
+    }
+  }
 
-  if (Table.Empty()) {
-    OS << "  return Intrinsic::not_intrinsic;\n";
-    OS << "}\n";
-    OS << "#endif\n\n";
+  std::string PreprocessorGuard =
+      "GET_LLVM_INTRINSIC_FOR_" + CompilerName.upper() + "_BUILTIN";
+
+  OS << formatv(R"(
+// Get the LLVM intrinsic that corresponds to a builtin. This is used by the
+// C front-end. The builtin name is passed in as BuiltinName, and a target
+// prefix (e.g. 'ppc') is passed in as TargetPrefix.
+#ifdef {0}
+
+Intrinsic::ID
+Intrinsic::getIntrinsicFor{1}Builtin(StringRef TargetPrefix, 
+                                      StringRef BuiltinName) {{
+  using namespace Intrinsic;
+)",
+                PreprocessorGuard, CompilerName);
+
+  if (BuiltinMap.empty()) {
+    OS << formatv(R"(
+  return not_intrinsic;
+  }
+#endif  // {0}
+)",
+                  PreprocessorGuard);
     return;
   }
 
-  OS << "  static constexpr char BuiltinNames[] = {\n";
-  Table.EmitCharArray(OS);
-  OS << "  };\n\n";
+  if (!Table.empty()) {
+    OS << "  static constexpr char BuiltinNames[] = {\n";
+    Table.EmitCharArray(OS);
+    OS << "  };\n\n";
+
+    OS << R"(
+  struct BuiltinEntry {
+    ID IntrinsicID;
+    unsigned StrTabOffset;
+    const char *getName() const { return &BuiltinNames[StrTabOffset]; }
+     bool operator<(StringRef RHS) const {
+       return strncmp(getName(), RHS.data(), RHS.size()) < 0;
----------------
Artem-B wrote:

Can we make `getString` return StringRef, and just `return getName() < RHS` ?

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


More information about the llvm-commits mailing list