[llvm] [TableGen] Split large printInstruction() for NVPTX to avoid compiler limits (PR #218530)
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 10 20:09:17 PDT 2026
kazutakahirata wrote:
Thanks for the update and for making it target-agnostic!
IIUC, you are splitting the large `switch` statement into ~24 smaller `switch` statements, each with at most 500 cases, and using the function-pointer table to select which switch to jump into. I'm afraid this design is a bit too complicated. Host toolchains generally don't have problems with large constant tables, which simply end up in `.rodata` without causing relocation problems.
What do you think about using a function-pointer table directly across the entire range of `getOpcode()`? We can deduplicate identical operand printing patterns into shared helper functions, which completely eliminates all `switch` statements from the overflow path, eliminates branching at the dispatch site, and removes the need for `PrintInstructionSplitThreshold` in `Target.td`.
Something like this:
```cpp
// Helper function for an exact operand pattern, shared across instructions.
static void printPattern_0(NVPTXInstPrinter *P, const MCInst *MI,
uint64_t Address, const MCSubtargetInfo &STI,
raw_ostream &O) {
P->printOperand(MI, 0, STI, O);
O << ", ";
P->printOperand(MI, 1, STI, O);
O << ", ";
P->printOperand(MI, 2, STI, O);
}
// No-op helper for instructions fully handled by the table-driven logic.
static void printPattern_None(NVPTXInstPrinter *, const MCInst *,
uint64_t, const MCSubtargetInfo &,
raw_ostream &) {}
// Fallback for invalid or unexpected opcodes (the old default case).
static void printPattern_Unreachable(NVPTXInstPrinter *, const MCInst *,
uint64_t, const MCSubtargetInfo &,
raw_ostream &) {
llvm_unreachable("Unexpected opcode.");
}
// Function-pointer table covering the entire valid range of getOpcode().
static void (*const NVPTXInstPrinters[])(
NVPTXInstPrinter *, const MCInst *, uint64_t,
const MCSubtargetInfo &, raw_ostream &) = {
&printPattern_0, // Shared by ADD_rr, SUB_rr, etc.
&printPattern_None, // No overflow operands left
&printPattern_Unreachable, // Invalid opcode
...
};
// printInstruction dispatches unconditionally with no branches or switches.
void NVPTXInstPrinter::printInstruction(const MCInst *MI, uint64_t Address,
const MCSubtargetInfo &STI,
raw_ostream &O) {
... // Initial tab, mnemonic, and table-driven operand printing
NVPTXInstPrinters[MI->getOpcode()](this, MI, Address, STI, O);
}
```
https://github.com/llvm/llvm-project/pull/218530
More information about the llvm-commits
mailing list