Skip to content

Commit 58fb42c

Browse files
committed
[TableGen] Do not emit mapping that have not been enabled.
- Detect whether logical operand mapping/names operand mappings have been enabled in a previous pass over instructions, and execute the relevant emission code only if those mappings are enabled. - For these mappings, skip the fixed set of predefined instructions as they won't have these mappings enabled.
1 parent c32cd57 commit 58fb42c

File tree

1 file changed

+102
-77
lines changed

1 file changed

+102
-77
lines changed

llvm/utils/TableGen/InstrInfoEmitter.cpp

Lines changed: 102 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class InstrInfoEmitter {
9292
raw_ostream &OS, const CodeGenTarget &Target,
9393
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
9494
void emitLogicalOperandSizeMappings(
95-
raw_ostream &OS, StringRef Namespace,
95+
raw_ostream &OS, const CodeGenTarget &Target,
9696
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
9797
void emitLogicalOperandTypeMappings(
9898
raw_ostream &OS, StringRef Namespace,
@@ -261,7 +261,11 @@ void InstrInfoEmitter::emitOperandNameMappings(
261261
// Max operand index seen.
262262
unsigned MaxOperandNo = 0;
263263

264-
for (const CodeGenInstruction *Inst : NumberedInstructions) {
264+
// Fixed/Predefined instructions do not have UseNamedOperandTable enabled, so
265+
// we can just skip them.
266+
const unsigned NumFixedInsts = Target.getNumFixedInstructions();
267+
for (const CodeGenInstruction *Inst :
268+
NumberedInstructions.drop_front(NumFixedInsts)) {
265269
if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
266270
continue;
267271
std::map<unsigned, unsigned> OpList;
@@ -335,11 +339,18 @@ void InstrInfoEmitter::emitOperandNameMappings(
335339
/// Generate an enum for all the operand types for this target, under the
336340
/// llvm::TargetNamespace::OpTypes namespace.
337341
/// Operand types are all definitions derived of the Operand Target.td class.
342+
///
338343
void InstrInfoEmitter::emitOperandTypeMappings(
339344
raw_ostream &OS, const CodeGenTarget &Target,
340345
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
341-
342346
StringRef Namespace = Target.getInstNamespace();
347+
348+
/// These generated functions are used only by the X86 target
349+
/// (in bolt/lib/Target/X86/X86MCPlusBuilder.cpp). So emit them only
350+
// for X86.
351+
if (Namespace != "X86")
352+
return;
353+
343354
ArrayRef<const Record *> Operands =
344355
Records.getAllDerivedDefinitions("Operand");
345356
ArrayRef<const Record *> RegisterOperands =
@@ -376,73 +387,66 @@ void InstrInfoEmitter::emitOperandTypeMappings(
376387
return NumberedInstructions[I]->TheDef->getName();
377388
};
378389
// TODO: Factor out duplicate operand lists to compress the tables.
379-
if (!NumberedInstructions.empty()) {
380-
std::vector<int> OperandOffsets;
381-
std::vector<const Record *> OperandRecords;
382-
int CurrentOffset = 0;
383-
for (const CodeGenInstruction *Inst : NumberedInstructions) {
384-
OperandOffsets.push_back(CurrentOffset);
385-
for (const auto &Op : Inst->Operands) {
386-
const DagInit *MIOI = Op.MIOperandInfo;
387-
if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) {
388-
// Single, anonymous, operand.
389-
OperandRecords.push_back(Op.Rec);
390+
std::vector<size_t> OperandOffsets;
391+
std::vector<const Record *> OperandRecords;
392+
size_t CurrentOffset = 0;
393+
for (const CodeGenInstruction *Inst : NumberedInstructions) {
394+
OperandOffsets.push_back(CurrentOffset);
395+
for (const auto &Op : Inst->Operands) {
396+
const DagInit *MIOI = Op.MIOperandInfo;
397+
if (!ExpandMIOperandInfo || !MIOI || MIOI->getNumArgs() == 0) {
398+
// Single, anonymous, operand.
399+
OperandRecords.push_back(Op.Rec);
400+
++CurrentOffset;
401+
} else {
402+
for (const Init *Arg : MIOI->getArgs()) {
403+
OperandRecords.push_back(cast<DefInit>(Arg)->getDef());
390404
++CurrentOffset;
391-
} else {
392-
for (const Init *Arg : MIOI->getArgs()) {
393-
OperandRecords.push_back(cast<DefInit>(Arg)->getDef());
394-
++CurrentOffset;
395-
}
396405
}
397406
}
398407
}
408+
}
399409

400-
// Emit the table of offsets (indexes) into the operand type table.
401-
// Size the unsigned integer offset to save space.
402-
assert(OperandRecords.size() <= UINT32_MAX &&
403-
"Too many operands for offset table");
404-
OS << " static const " << getMinimalTypeForRange(OperandRecords.size());
405-
OS << " Offsets[] = {\n";
406-
for (int I = 0, E = OperandOffsets.size(); I != E; ++I) {
407-
OS << " /* " << getInstrName(I) << " */\n";
408-
OS << " " << OperandOffsets[I] << ",\n";
409-
}
410-
OS << " };\n";
410+
// Emit the table of offsets (indexes) into the operand type table.
411+
// Size the unsigned integer offset to save space.
412+
assert(OperandRecords.size() <= UINT32_MAX &&
413+
"Too many operands for offset table");
414+
OS << " static constexpr " << getMinimalTypeForRange(OperandRecords.size());
415+
OS << " Offsets[] = {\n";
416+
for (const auto &[Idx, Offset] : enumerate(OperandOffsets))
417+
OS << " " << Offset << ", // " << getInstrName(Idx) << '\n';
418+
OS << " };\n";
411419

412-
// Add an entry for the end so that we don't need to special case it below.
413-
OperandOffsets.push_back(OperandRecords.size());
414-
415-
// Emit the actual operand types in a flat table.
416-
// Size the signed integer operand type to save space.
417-
assert(EnumVal <= INT16_MAX &&
418-
"Too many operand types for operand types table");
419-
OS << "\n using namespace OpTypes;\n";
420-
OS << " static";
421-
OS << ((EnumVal <= INT8_MAX) ? " const int8_t" : " const int16_t");
422-
OS << " OpcodeOperandTypes[] = {\n ";
423-
for (int I = 0, E = OperandRecords.size(), CurOffset = 0; I != E; ++I) {
424-
// We print each Opcode's operands in its own row.
425-
if (I == OperandOffsets[CurOffset]) {
426-
OS << "\n /* " << getInstrName(CurOffset) << " */\n ";
427-
while (OperandOffsets[++CurOffset] == I)
428-
OS << "/* " << getInstrName(CurOffset) << " */\n ";
429-
}
430-
const Record *OpR = OperandRecords[I];
431-
if ((OpR->isSubClassOf("Operand") ||
432-
OpR->isSubClassOf("RegisterOperand") ||
433-
OpR->isSubClassOf("RegisterClass")) &&
434-
!OpR->isAnonymous())
435-
OS << OpR->getName();
436-
else
437-
OS << -1;
438-
OS << ", ";
420+
// Add an entry for the end so that we don't need to special case it below.
421+
OperandOffsets.push_back(OperandRecords.size());
422+
423+
// Emit the actual operand types in a flat table.
424+
// Size the signed integer operand type to save space.
425+
assert(EnumVal <= INT16_MAX &&
426+
"Too many operand types for operand types table");
427+
OS << "\n using namespace OpTypes;\n";
428+
OS << " static";
429+
OS << (EnumVal <= INT8_MAX ? " constexpr int8_t" : " constexpr int16_t");
430+
OS << " OpcodeOperandTypes[] = {";
431+
size_t CurOffset = 0;
432+
for (auto [Idx, OpR] : enumerate(OperandRecords)) {
433+
// We print each Opcode's operands in its own row.
434+
if (Idx == OperandOffsets[CurOffset]) {
435+
OS << "\n /* " << getInstrName(CurOffset) << " */\n ";
436+
while (OperandOffsets[++CurOffset] == Idx)
437+
OS << "/* " << getInstrName(CurOffset) << " */\n ";
439438
}
440-
OS << "\n };\n";
441-
442-
OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";
443-
} else {
444-
OS << " llvm_unreachable(\"No instructions defined\");\n";
439+
if ((OpR->isSubClassOf("Operand") || OpR->isSubClassOf("RegisterOperand") ||
440+
OpR->isSubClassOf("RegisterClass")) &&
441+
!OpR->isAnonymous())
442+
OS << OpR->getName();
443+
else
444+
OS << -1;
445+
OS << ", ";
445446
}
447+
OS << "\n };\n";
448+
449+
OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n";
446450
OS << "}\n";
447451
OS << "} // end namespace llvm::" << Namespace << "\n";
448452
OS << "#endif // GET_INSTRINFO_OPERAND_TYPE\n\n";
@@ -461,26 +465,31 @@ void InstrInfoEmitter::emitOperandTypeMappings(
461465
SizeToOperandName[Size].push_back(Op->getName());
462466
}
463467
OS << " default: return 0;\n";
464-
for (const auto &KV : SizeToOperandName) {
465-
for (const StringRef &OperandName : KV.second)
468+
for (const auto &[Size, OperandNames] : SizeToOperandName) {
469+
for (const StringRef &OperandName : OperandNames)
466470
OS << " case OpTypes::" << OperandName << ":\n";
467-
OS << " return " << KV.first << ";\n\n";
471+
OS << " return " << Size << ";\n\n";
468472
}
469473
OS << " }\n}\n";
470474
OS << "} // end namespace llvm::" << Namespace << "\n";
471475
OS << "#endif // GET_INSTRINFO_MEM_OPERAND_SIZE\n\n";
472476
}
473477

474478
void InstrInfoEmitter::emitLogicalOperandSizeMappings(
475-
raw_ostream &OS, StringRef Namespace,
479+
raw_ostream &OS, const CodeGenTarget &Target,
476480
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
477-
std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap;
481+
StringRef Namespace = Target.getInstNamespace();
478482

483+
std::map<std::vector<unsigned>, unsigned> LogicalOpSizeMap;
479484
std::map<unsigned, std::vector<std::string>> InstMap;
480485

481486
size_t LogicalOpListSize = 0U;
482487
std::vector<unsigned> LogicalOpList;
483-
for (const auto *Inst : NumberedInstructions) {
488+
489+
// Fixed/Predefined instructions do not have UseLogicalOperandMappings
490+
// enabled, so we can just skip them.
491+
const unsigned NumFixedInsts = Target.getNumFixedInstructions();
492+
for (const auto *Inst : NumberedInstructions.drop_front(NumFixedInsts)) {
484493
if (!Inst->TheDef->getValueAsBit("UseLogicalOperandMappings"))
485494
continue;
486495

@@ -907,22 +916,34 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
907916
unsigned OperandInfoSize =
908917
CollectOperandInfo(OperandInfoList, OperandInfoMap);
909918

919+
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
920+
Target.getInstructionsByEnumValue();
921+
910922
// Collect all of the instruction's implicit uses and defs.
923+
// Also collect which features are enabled by instructions to control
924+
// emission of various mappings.
925+
926+
bool HasUseLogicalOperandMappings = false;
927+
bool HasUseNamedOperandTable = false;
928+
911929
Timer.startTimer("Collect uses/defs");
912930
std::map<std::vector<const Record *>, unsigned> EmittedLists;
913931
std::vector<std::vector<const Record *>> ImplicitLists;
914932
unsigned ImplicitListSize = 0;
915-
for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
916-
std::vector<const Record *> ImplicitOps = II->ImplicitUses;
917-
llvm::append_range(ImplicitOps, II->ImplicitDefs);
933+
for (const CodeGenInstruction *Inst : NumberedInstructions) {
934+
HasUseLogicalOperandMappings |=
935+
Inst->TheDef->getValueAsBit("UseLogicalOperandMappings");
936+
HasUseNamedOperandTable |=
937+
Inst->TheDef->getValueAsBit("UseNamedOperandTable");
938+
939+
std::vector<const Record *> ImplicitOps = Inst->ImplicitUses;
940+
llvm::append_range(ImplicitOps, Inst->ImplicitDefs);
918941
if (EmittedLists.insert({ImplicitOps, ImplicitListSize}).second) {
919942
ImplicitLists.push_back(ImplicitOps);
920943
ImplicitListSize += ImplicitOps.size();
921944
}
922945
}
923946

924-
ArrayRef<const CodeGenInstruction *> NumberedInstructions =
925-
Target.getInstructionsByEnumValue();
926947
OS << "#if defined(GET_INSTRINFO_MC_DESC) || "
927948
"defined(GET_INSTRINFO_CTOR_DTOR)\n";
928949
OS << "namespace llvm {\n\n";
@@ -1123,14 +1144,18 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
11231144

11241145
OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
11251146

1126-
Timer.startTimer("Emit operand name mappings");
1127-
emitOperandNameMappings(OS, Target, NumberedInstructions);
1147+
if (HasUseNamedOperandTable) {
1148+
Timer.startTimer("Emit operand name mappings");
1149+
emitOperandNameMappings(OS, Target, NumberedInstructions);
1150+
}
11281151

11291152
Timer.startTimer("Emit operand type mappings");
11301153
emitOperandTypeMappings(OS, Target, NumberedInstructions);
11311154

1132-
Timer.startTimer("Emit logical operand size mappings");
1133-
emitLogicalOperandSizeMappings(OS, TargetName, NumberedInstructions);
1155+
if (HasUseLogicalOperandMappings) {
1156+
Timer.startTimer("Emit logical operand size mappings");
1157+
emitLogicalOperandSizeMappings(OS, Target, NumberedInstructions);
1158+
}
11341159

11351160
Timer.startTimer("Emit logical operand type mappings");
11361161
emitLogicalOperandTypeMappings(OS, TargetName, NumberedInstructions);

0 commit comments

Comments
 (0)