[llvm] 89b08c8 - [TableGen] Simplify generated code for isSubclass (#117351)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 28 00:52:05 PST 2024
Author: Jay Foad
Date: 2024-11-28T08:52:02Z
New Revision: 89b08c8ee7b5184f8cfb0d356f2762173fb87d42
URL: https://github.com/llvm/llvm-project/commit/89b08c8ee7b5184f8cfb0d356f2762173fb87d42
DIFF: https://github.com/llvm/llvm-project/commit/89b08c8ee7b5184f8cfb0d356f2762173fb87d42.diff
LOG: [TableGen] Simplify generated code for isSubclass (#117351)
Implement isSubclass with direct lookup into some tables instead of
nested switches.
Part of the motivation for this is improving compile time when clang-18
is used as a host compiler, since it seems to have trouble with very
large switch statements.
Added:
Modified:
llvm/utils/TableGen/AsmMatcherEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index eb80bea3cfb0fe..28efd780c5c615 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -2547,53 +2547,58 @@ static void emitIsSubclass(CodeGenTarget &Target,
OS << " if (A == B)\n";
OS << " return true;\n\n";
- bool EmittedSwitch = false;
+ // TODO: Use something like SequenceToOffsetTable to allow sequences to
+ // overlap in this table.
+ SmallVector<bool> SuperClassData;
+
+ OS << " [[maybe_unused]] static constexpr struct {\n";
+ OS << " uint32_t Offset;\n";
+ OS << " uint16_t Start;\n";
+ OS << " uint16_t Length;\n";
+ OS << " } Table[] = {\n";
+ OS << " {0, 0, 0},\n"; // InvalidMatchClass
+ OS << " {0, 0, 0},\n"; // OptionalMatchClass
for (const auto &A : Infos) {
- std::vector<StringRef> SuperClasses;
- if (A.IsOptional)
- SuperClasses.push_back("OptionalMatchClass");
- for (const auto &B : Infos) {
- if (&A != &B && A.isSubsetOf(B))
- SuperClasses.push_back(B.Name);
- }
-
- if (SuperClasses.empty())
- continue;
-
- // If this is the first SuperClass, emit the switch header.
- if (!EmittedSwitch) {
- OS << " switch (A) {\n";
- OS << " default:\n";
- OS << " return false;\n";
- EmittedSwitch = true;
- }
-
- OS << "\n case " << A.Name << ":\n";
-
- if (SuperClasses.size() == 1) {
- OS << " return B == " << SuperClasses.back() << ";\n";
- continue;
- }
-
- if (!SuperClasses.empty()) {
- OS << " switch (B) {\n";
- OS << " default: return false;\n";
- for (StringRef SC : SuperClasses)
- OS << " case " << SC << ": return true;\n";
- OS << " }\n";
- } else {
- // No case statement to emit
- OS << " return false;\n";
- }
+ SmallVector<bool> SuperClasses;
+ SuperClasses.push_back(false); // InvalidMatchClass
+ SuperClasses.push_back(A.IsOptional); // OptionalMatchClass
+ for (const auto &B : Infos)
+ SuperClasses.push_back(&A != &B && A.isSubsetOf(B));
+
+ // Trim leading and trailing zeros.
+ auto End = find_if(reverse(SuperClasses), [](bool B) { return B; }).base();
+ auto Start =
+ std::find_if(SuperClasses.begin(), End, [](bool B) { return B; });
+
+ unsigned Offset = SuperClassData.size();
+ SuperClassData.append(Start, End);
+
+ OS << " {" << Offset << ", " << (Start - SuperClasses.begin()) << ", "
+ << (End - Start) << "},\n";
}
+ OS << " };\n\n";
- // If there were case statements emitted into the string stream write the
- // default.
- if (EmittedSwitch)
- OS << " }\n";
- else
+ if (SuperClassData.empty()) {
OS << " return false;\n";
-
+ } else {
+ // Dump the boolean data packed into bytes.
+ SuperClassData.append(-SuperClassData.size() % 8, false);
+ OS << " static constexpr uint8_t Data[] = {\n";
+ for (unsigned I = 0, E = SuperClassData.size(); I < E; I += 8) {
+ unsigned Byte = 0;
+ for (unsigned J = 0; J < 8; ++J)
+ Byte |= (unsigned)SuperClassData[I + J] << J;
+ OS << formatv(" {:X2},\n", Byte);
+ }
+ OS << " };\n\n";
+
+ OS << " auto &Entry = Table[A];\n";
+ OS << " unsigned Idx = B - Entry.Start;\n";
+ OS << " if (Idx >= Entry.Length)\n";
+ OS << " return false;\n";
+ OS << " Idx += Entry.Offset;\n";
+ OS << " return (Data[Idx / 8] >> (Idx % 8)) & 1;\n";
+ }
OS << "}\n\n";
}
More information about the llvm-commits
mailing list