Skip to content

Commit 13e662c

Browse files
committed
[TableGenn] Improvements to Named operands in InstrInfoEmitter
- Assign OpName enum values in the same alphabetical order in which they are emitted (and get of OPERAND_LAST which is not used anywhere). - Inline `initOperandMapData` into `emitOperandNameMappings` to help see clearly how various maps are computed. - Emit the static `OperandMap` table as int8_t when possible. This should help reduce the static size by 50% in the common case.
1 parent 27e01d1 commit 13e662c

File tree

1 file changed

+56
-65
lines changed

1 file changed

+56
-65
lines changed

llvm/utils/TableGen/InstrInfoEmitter.cpp

Lines changed: 56 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040

4141
using namespace llvm;
4242

43-
cl::OptionCategory InstrInfoEmitterCat("Options for -gen-instr-info");
43+
static cl::OptionCategory InstrInfoEmitterCat("Options for -gen-instr-info");
4444
static cl::opt<bool> ExpandMIOperandInfo(
4545
"instr-info-expand-mi-operand-info",
4646
cl::desc("Expand operand's MIOperandInfo DAG into suboperands"),
@@ -67,13 +67,6 @@ class InstrInfoEmitter {
6767
typedef std::vector<OperandInfoTy> OperandInfoListTy;
6868
typedef std::map<OperandInfoTy, unsigned> OperandInfoMapTy;
6969

70-
/// The keys of this map are maps which have OpName enum values as their keys
71-
/// and instruction operand indices as their values. The values of this map
72-
/// are lists of instruction names.
73-
typedef std::map<std::map<unsigned, unsigned>, std::vector<std::string>>
74-
OpNameMapTy;
75-
typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
76-
7770
/// Generate member functions in the target-specific GenInstrInfo class.
7871
///
7972
/// This method is used to custom expand TIIPredicate definitions.
@@ -95,15 +88,9 @@ class InstrInfoEmitter {
9588
void emitOperandTypeMappings(
9689
raw_ostream &OS, const CodeGenTarget &Target,
9790
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
98-
void
99-
initOperandMapData(ArrayRef<const CodeGenInstruction *> NumberedInstructions,
100-
StringRef Namespace,
101-
std::map<std::string, unsigned> &Operands,
102-
OpNameMapTy &OperandMap);
10391
void emitOperandNameMappings(
10492
raw_ostream &OS, const CodeGenTarget &Target,
10593
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
106-
10794
void emitLogicalOperandSizeMappings(
10895
raw_ostream &OS, StringRef Namespace,
10996
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
@@ -239,35 +226,6 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
239226
}
240227
}
241228

242-
/// Initialize data structures for generating operand name mappings.
243-
///
244-
/// \param Operands [out] A map used to generate the OpName enum with operand
245-
/// names as its keys and operand enum values as its values.
246-
/// \param OperandMap [out] A map for representing the operand name mappings for
247-
/// each instructions. This is used to generate the OperandMap table as
248-
/// well as the getNamedOperandIdx() function.
249-
void InstrInfoEmitter::initOperandMapData(
250-
ArrayRef<const CodeGenInstruction *> NumberedInstructions,
251-
StringRef Namespace, std::map<std::string, unsigned> &Operands,
252-
OpNameMapTy &OperandMap) {
253-
unsigned NumOperands = 0;
254-
for (const CodeGenInstruction *Inst : NumberedInstructions) {
255-
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
256-
continue;
257-
std::map<unsigned, unsigned> OpList;
258-
for (const auto &Info : Inst->Operands) {
259-
StrUintMapIter I = Operands.find(Info.Name);
260-
261-
if (I == Operands.end()) {
262-
I = Operands.insert(Operands.begin(), {Info.Name, NumOperands++});
263-
}
264-
OpList[I->second] = Info.MIOperandNo;
265-
}
266-
OperandMap[OpList].push_back(Namespace.str() +
267-
"::" + Inst->TheDef->getName().str());
268-
}
269-
}
270-
271229
/// Generate a table and function for looking up the indices of operands by
272230
/// name.
273231
///
@@ -283,22 +241,52 @@ void InstrInfoEmitter::emitOperandNameMappings(
283241
raw_ostream &OS, const CodeGenTarget &Target,
284242
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
285243
StringRef Namespace = Target.getInstNamespace();
286-
// Map of operand names to their enumeration value. This will be used to
287-
// generate the OpName enum.
288-
std::map<std::string, unsigned> Operands;
289-
OpNameMapTy OperandMap;
290244

291-
initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap);
245+
/// To facilitate assigning OpName enum values in the sorted alphabetical
246+
/// order, we go through an indirection from OpName -> ID, and Enum -> ID.
247+
/// This allows us to build the OpList and assign IDs to OpNames in a single
248+
/// scan of the instructions below.
249+
250+
// Map of operand names to their ID.
251+
std::map<std::string, unsigned> OperandNameToID;
252+
// Map from operand name enum value -> ID.
253+
std::vector<unsigned> OperandEnumToID;
254+
255+
/// The keys of this map is a map which have OpName ID values as their keys
256+
/// and instruction operand indices as their values. The values of this map
257+
/// are lists of instruction names. This map helps to unique entries among
258+
/// instructions that have identical OpName -> Operand index mapping.
259+
std::map<std::map<unsigned, unsigned>, std::vector<std::string>> OperandMap;
260+
261+
// Max operand index seen.
262+
unsigned MaxOperandNo = 0;
263+
unsigned NumOperandNames = 0;
264+
265+
for (const CodeGenInstruction *Inst : NumberedInstructions) {
266+
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
267+
continue;
268+
std::map<unsigned, unsigned> OpList;
269+
for (const auto &Info : Inst->Operands) {
270+
auto [I, Inserted] = OperandNameToID.try_emplace(Info.Name, 0);
271+
if (Inserted)
272+
I->second = NumOperandNames++;
273+
OpList[I->second] = Info.MIOperandNo;
274+
MaxOperandNo = std::max(MaxOperandNo, Info.MIOperandNo);
275+
}
276+
OperandMap[OpList].push_back(Inst->TheDef->getName().str());
277+
}
278+
279+
OperandEnumToID.reserve(NumOperandNames);
280+
for (const auto &Op : OperandNameToID)
281+
OperandEnumToID.push_back(Op.second);
292282

293283
OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n";
294284
OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";
295285
OS << "namespace llvm::" << Namespace << "::OpName {\n";
296286
OS << "enum {\n";
297-
for (const auto &Op : Operands)
298-
OS << " " << Op.first << " = " << Op.second << ",\n";
299-
300-
OS << " OPERAND_LAST";
301-
OS << "\n};\n";
287+
for (const auto &[I, Op] : enumerate(OperandNameToID))
288+
OS << " " << Op.first << " = " << I << ",\n";
289+
OS << "};\n";
302290
OS << "} // end namespace llvm::" << Namespace << "::OpName\n";
303291
OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n";
304292

@@ -307,28 +295,31 @@ void InstrInfoEmitter::emitOperandNameMappings(
307295
OS << "namespace llvm::" << Namespace << " {\n";
308296
OS << "LLVM_READONLY\n";
309297
OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";
310-
if (!Operands.empty()) {
311-
OS << " static const int16_t OperandMap [][" << Operands.size()
298+
if (NumOperandNames != 0) {
299+
assert(MaxOperandNo <= std::numeric_limits<int16_t>::max());
300+
StringRef Type = MaxOperandNo <= std::numeric_limits<int8_t>::max()
301+
? "int8_t"
302+
: "int16_t";
303+
OS << " static constexpr " << Type << " OperandMap[][" << NumOperandNames
312304
<< "] = {\n";
313305
for (const auto &Entry : OperandMap) {
314306
const std::map<unsigned, unsigned> &OpList = Entry.first;
315-
OS << "{";
316-
317-
// Emit a row of the OperandMap table
318-
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
319-
OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", ";
320307

308+
// Emit a row of the OperandMap table.
309+
OS << " {";
310+
for (int i = 0; i < static_cast<int>(NumOperandNames); ++i) {
311+
unsigned ID = OperandEnumToID[i];
312+
OS << (OpList.count(ID) ? (int)OpList.find(ID)->second : -1) << ", ";
313+
}
321314
OS << "},\n";
322315
}
323316
OS << "};\n";
324317

325318
OS << " switch(Opcode) {\n";
326-
unsigned TableIndex = 0;
327-
for (const auto &Entry : OperandMap) {
319+
for (const auto &[TableIndex, Entry] : enumerate(OperandMap)) {
328320
for (const std::string &Name : Entry.second)
329-
OS << " case " << Name << ":\n";
330-
331-
OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n";
321+
OS << " case " << Namespace << "::" << Name << ":\n";
322+
OS << " return OperandMap[" << TableIndex << "][NamedIdx];\n";
332323
}
333324
OS << " default: return -1;\n";
334325
OS << " }\n";

0 commit comments

Comments
 (0)