Skip to content

Commit b717044

Browse files
authored
[TableGen] Simplify generated code for validateOperandClass (#117889)
Implement the register operand handling in validateOperandClass with a table lookup instead of a potentially huge switch. 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.
1 parent 8358437 commit b717044

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

llvm/utils/TableGen/AsmMatcherEmitter.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2466,7 +2466,8 @@ static void emitRegisterMatchErrorFunc(AsmMatcherInfo &Info, raw_ostream &OS) {
24662466
}
24672467

24682468
/// emitValidateOperandClass - Emit the function to validate an operand class.
2469-
static void emitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) {
2469+
static void emitValidateOperandClass(const CodeGenTarget &Target,
2470+
AsmMatcherInfo &Info, raw_ostream &OS) {
24702471
OS << "static unsigned validateOperandClass(MCParsedAsmOperand &GOp, "
24712472
<< "MatchClassKind Kind) {\n";
24722473
OS << " " << Info.Target.getName() << "Operand &Operand = ("
@@ -2508,15 +2509,21 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) {
25082509
OS << " } // end switch (Kind)\n\n";
25092510

25102511
// Check for register operands, including sub-classes.
2512+
const auto &Regs = Target.getRegBank().getRegisters();
2513+
StringRef Namespace = Regs.front().TheDef->getValueAsString("Namespace");
2514+
SmallVector<StringRef> Table(1 + Regs.size(), "InvalidMatchClass");
2515+
for (const auto &RC : Info.RegisterClasses) {
2516+
const auto &Reg = Target.getRegBank().getReg(RC.first);
2517+
Table[Reg->EnumValue] = RC.second->Name;
2518+
}
25112519
OS << " if (Operand.isReg()) {\n";
2512-
OS << " MatchClassKind OpKind;\n";
2513-
OS << " switch (Operand.getReg().id()) {\n";
2514-
OS << " default: OpKind = InvalidMatchClass; break;\n";
2515-
for (const auto &RC : Info.RegisterClasses)
2516-
OS << " case " << RC.first->getValueAsString("Namespace")
2517-
<< "::" << RC.first->getName() << ": OpKind = " << RC.second->Name
2518-
<< "; break;\n";
2519-
OS << " }\n";
2520+
OS << " static constexpr uint16_t Table[" << Namespace
2521+
<< "::NUM_TARGET_REGS] = {\n";
2522+
for (auto &MatchClassName : Table)
2523+
OS << " " << MatchClassName << ",\n";
2524+
OS << " };\n\n";
2525+
OS << " MatchClassKind OpKind = "
2526+
"(MatchClassKind)Table[Operand.getReg().id()];\n";
25202527
OS << " return isSubclass(OpKind, Kind) ? "
25212528
<< "(unsigned)MCTargetAsmParser::Match_Success :\n "
25222529
<< " getDiagKindFromRegisterClass(Kind);\n }\n\n";
@@ -3412,7 +3419,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
34123419
emitIsSubclass(Target, Info.Classes, OS);
34133420

34143421
// Emit the routine to validate an operand against a match class.
3415-
emitValidateOperandClass(Info, OS);
3422+
emitValidateOperandClass(Target, Info, OS);
34163423

34173424
emitMatchClassKindNames(Info.Classes, OS);
34183425

0 commit comments

Comments
 (0)