Skip to content

Commit 807a82d

Browse files
authored
[TableGen] Implement getNamedOperandIdx with another table lookup. NFC. (llvm#151116)
Use direct table lookup instead of a switch over all opcodes. In my Release+Asserts build this reduced the code size for AMDGPU::getNamedOperandIdx from 11422 to 80 bytes, and the total size of all its tables (including the jump table for the switch) from 243564 to 155020 bytes.
1 parent 730d05b commit 807a82d

File tree

2 files changed

+31
-32
lines changed

2 files changed

+31
-32
lines changed

llvm/test/TableGen/get-named-operand-idx.td

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,10 @@ def InstD : InstBase {
7272
// CHECK: {0, 1, 2, -1, -1, },
7373
// CHECK: {-1, -1, -1, 0, 1, },
7474
// CHECK: };
75-
// CHECK: switch(Opcode) {
76-
// CHECK: case MyNamespace::InstA:
77-
// CHECK: return OperandMap[0][static_cast<unsigned>(Name)];
78-
// CHECK: case MyNamespace::InstB:
79-
// CHECK: case MyNamespace::InstC:
80-
// CHECK: return OperandMap[1][static_cast<unsigned>(Name)];
81-
// CHECK: default: return -1;
82-
// CHECK: }
75+
// CHECK: static constexpr uint8_t InstructionIndex[] = {
76+
// CHECK: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
77+
// CHECK: };
78+
// CHECK: return OperandMap[InstructionIndex[Opcode]][(unsigned)Name];
8379
// CHECK: }
8480
// CHECK: } // end namespace llvm::MyNamespace
8581
// CHECK: #endif //GET_INSTRINFO_NAMED_OPS

llvm/utils/TableGen/InstrInfoEmitter.cpp

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -250,29 +250,38 @@ void InstrInfoEmitter::emitOperandNameMappings(
250250
// Map of operand names to their ID.
251251
MapVector<StringRef, unsigned> OperandNameToID;
252252

253-
/// The keys of this map is a map which have OpName ID values as their keys
254-
/// and instruction operand indices as their values. The values of this map
255-
/// are lists of instruction names. This map helps to unique entries among
253+
/// A key in this map is a vector mapping OpName ID values to instruction
254+
/// operand indices or -1 (but without any trailing -1 values which will be
255+
/// added later). The corresponding value in this map is the index of that row
256+
/// in the emitted OperandMap table. This map helps to unique entries among
256257
/// instructions that have identical OpName -> Operand index mapping.
257-
std::map<std::map<unsigned, unsigned>, std::vector<StringRef>> OperandMap;
258+
MapVector<SmallVector<int>, unsigned> OperandMap;
258259

259260
// Max operand index seen.
260261
unsigned MaxOperandNo = 0;
261262

262263
// Fixed/Predefined instructions do not have UseNamedOperandTable enabled, so
263-
// we can just skip them.
264+
// add a dummy map entry for them.
265+
OperandMap.try_emplace({}, 0);
266+
unsigned FirstTargetVal = TargetInstructions.front()->EnumVal;
267+
SmallVector<unsigned> InstructionIndex(FirstTargetVal, 0);
264268
for (const CodeGenInstruction *Inst : TargetInstructions) {
265-
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
269+
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) {
270+
InstructionIndex.push_back(0);
266271
continue;
267-
std::map<unsigned, unsigned> OpList;
272+
}
273+
SmallVector<int> OpList;
268274
for (const auto &Info : Inst->Operands) {
269275
unsigned ID =
270276
OperandNameToID.try_emplace(Info.Name, OperandNameToID.size())
271277
.first->second;
278+
OpList.resize(std::max((unsigned)OpList.size(), ID + 1), -1);
272279
OpList[ID] = Info.MIOperandNo;
273280
MaxOperandNo = std::max(MaxOperandNo, Info.MIOperandNo);
274281
}
275-
OperandMap[OpList].push_back(Inst->TheDef->getName());
282+
auto [It, Inserted] =
283+
OperandMap.try_emplace(std::move(OpList), OperandMap.size());
284+
InstructionIndex.push_back(It->second);
276285
}
277286

278287
const size_t NumOperandNames = OperandNameToID.size();
@@ -302,28 +311,22 @@ void InstrInfoEmitter::emitOperandNameMappings(
302311
StringRef Type = MaxOperandNo <= INT8_MAX ? "int8_t" : "int16_t";
303312
OS << " static constexpr " << Type << " OperandMap[][" << NumOperandNames
304313
<< "] = {\n";
305-
for (const auto &Entry : OperandMap) {
306-
const std::map<unsigned, unsigned> &OpList = Entry.first;
307-
314+
for (const auto &[OpList, _] : OperandMap) {
308315
// Emit a row of the OperandMap table.
309316
OS << " {";
310-
for (unsigned ID = 0; ID < NumOperandNames; ++ID) {
311-
auto Iter = OpList.find(ID);
312-
OS << (Iter != OpList.end() ? (int)Iter->second : -1) << ", ";
313-
}
317+
for (unsigned ID = 0; ID < NumOperandNames; ++ID)
318+
OS << (ID < OpList.size() ? OpList[ID] : -1) << ", ";
314319
OS << "},\n";
315320
}
316321
OS << " };\n";
317322

318-
OS << " switch(Opcode) {\n";
319-
for (const auto &[TableIndex, Entry] : enumerate(OperandMap)) {
320-
for (StringRef Name : Entry.second)
321-
OS << " case " << Namespace << "::" << Name << ":\n";
322-
OS << " return OperandMap[" << TableIndex
323-
<< "][static_cast<unsigned>(Name)];\n";
324-
}
325-
OS << " default: return -1;\n";
326-
OS << " }\n";
323+
Type = OperandMap.size() <= UINT8_MAX + 1 ? "uint8_t" : "uint16_t";
324+
OS << " static constexpr " << Type << " InstructionIndex[] = {";
325+
for (auto [TableIndex, Entry] : enumerate(InstructionIndex))
326+
OS << (TableIndex % 16 == 0 ? "\n " : " ") << Entry << ',';
327+
OS << "\n };\n";
328+
329+
OS << " return OperandMap[InstructionIndex[Opcode]][(unsigned)Name];\n";
327330
} else {
328331
// There are no operands, so no need to emit anything
329332
OS << " return -1;\n";

0 commit comments

Comments
 (0)