[llvm] [TableGen] Rework `EmitIntrinsicToBuiltinMap` (PR #104681)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 19 00:27:04 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;
----------------
arsenm wrote:
what happens if LHS.size() < RHS.size()? This is assuming null terminated StringRef?
https://github.com/llvm/llvm-project/pull/104681
More information about the llvm-commits
mailing list