@@ -92,7 +92,7 @@ class InstrInfoEmitter {
92
92
raw_ostream &OS, const CodeGenTarget &Target,
93
93
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
94
94
void emitLogicalOperandSizeMappings (
95
- raw_ostream &OS, StringRef Namespace ,
95
+ raw_ostream &OS, const CodeGenTarget &Target ,
96
96
ArrayRef<const CodeGenInstruction *> NumberedInstructions);
97
97
void emitLogicalOperandTypeMappings (
98
98
raw_ostream &OS, StringRef Namespace,
@@ -261,7 +261,11 @@ void InstrInfoEmitter::emitOperandNameMappings(
261
261
// Max operand index seen.
262
262
unsigned MaxOperandNo = 0 ;
263
263
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)) {
265
269
if (!Inst->TheDef ->getValueAsBit (" UseNamedOperandTable" ))
266
270
continue ;
267
271
std::map<unsigned , unsigned > OpList;
@@ -335,11 +339,18 @@ void InstrInfoEmitter::emitOperandNameMappings(
335
339
// / Generate an enum for all the operand types for this target, under the
336
340
// / llvm::TargetNamespace::OpTypes namespace.
337
341
// / Operand types are all definitions derived of the Operand Target.td class.
342
+ // /
338
343
void InstrInfoEmitter::emitOperandTypeMappings (
339
344
raw_ostream &OS, const CodeGenTarget &Target,
340
345
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
341
-
342
346
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
+
343
354
ArrayRef<const Record *> Operands =
344
355
Records.getAllDerivedDefinitions (" Operand" );
345
356
ArrayRef<const Record *> RegisterOperands =
@@ -376,73 +387,66 @@ void InstrInfoEmitter::emitOperandTypeMappings(
376
387
return NumberedInstructions[I]->TheDef ->getName ();
377
388
};
378
389
// 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 ());
390
404
++CurrentOffset;
391
- } else {
392
- for (const Init *Arg : MIOI->getArgs ()) {
393
- OperandRecords.push_back (cast<DefInit>(Arg)->getDef ());
394
- ++CurrentOffset;
395
- }
396
405
}
397
406
}
398
407
}
408
+ }
399
409
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 " ;
411
419
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 " ;
439
438
}
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 << " , " ;
445
446
}
447
+ OS << " \n };\n " ;
448
+
449
+ OS << " return OpcodeOperandTypes[Offsets[Opcode] + OpIdx];\n " ;
446
450
OS << " }\n " ;
447
451
OS << " } // end namespace llvm::" << Namespace << " \n " ;
448
452
OS << " #endif // GET_INSTRINFO_OPERAND_TYPE\n\n " ;
@@ -461,26 +465,31 @@ void InstrInfoEmitter::emitOperandTypeMappings(
461
465
SizeToOperandName[Size].push_back (Op->getName ());
462
466
}
463
467
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 )
466
470
OS << " case OpTypes::" << OperandName << " :\n " ;
467
- OS << " return " << KV. first << " ;\n\n " ;
471
+ OS << " return " << Size << " ;\n\n " ;
468
472
}
469
473
OS << " }\n }\n " ;
470
474
OS << " } // end namespace llvm::" << Namespace << " \n " ;
471
475
OS << " #endif // GET_INSTRINFO_MEM_OPERAND_SIZE\n\n " ;
472
476
}
473
477
474
478
void InstrInfoEmitter::emitLogicalOperandSizeMappings (
475
- raw_ostream &OS, StringRef Namespace ,
479
+ raw_ostream &OS, const CodeGenTarget &Target ,
476
480
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
477
- std::map<std::vector< unsigned >, unsigned > LogicalOpSizeMap ;
481
+ StringRef Namespace = Target. getInstNamespace () ;
478
482
483
+ std::map<std::vector<unsigned >, unsigned > LogicalOpSizeMap;
479
484
std::map<unsigned , std::vector<std::string>> InstMap;
480
485
481
486
size_t LogicalOpListSize = 0U ;
482
487
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)) {
484
493
if (!Inst->TheDef ->getValueAsBit (" UseLogicalOperandMappings" ))
485
494
continue ;
486
495
@@ -907,22 +916,34 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
907
916
unsigned OperandInfoSize =
908
917
CollectOperandInfo (OperandInfoList, OperandInfoMap);
909
918
919
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions =
920
+ Target.getInstructionsByEnumValue ();
921
+
910
922
// 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
+
911
929
Timer.startTimer (" Collect uses/defs" );
912
930
std::map<std::vector<const Record *>, unsigned > EmittedLists;
913
931
std::vector<std::vector<const Record *>> ImplicitLists;
914
932
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 );
918
941
if (EmittedLists.insert ({ImplicitOps, ImplicitListSize}).second ) {
919
942
ImplicitLists.push_back (ImplicitOps);
920
943
ImplicitListSize += ImplicitOps.size ();
921
944
}
922
945
}
923
946
924
- ArrayRef<const CodeGenInstruction *> NumberedInstructions =
925
- Target.getInstructionsByEnumValue ();
926
947
OS << " #if defined(GET_INSTRINFO_MC_DESC) || "
927
948
" defined(GET_INSTRINFO_CTOR_DTOR)\n " ;
928
949
OS << " namespace llvm {\n\n " ;
@@ -1123,14 +1144,18 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
1123
1144
1124
1145
OS << " #endif // GET_INSTRINFO_CTOR_DTOR\n\n " ;
1125
1146
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
+ }
1128
1151
1129
1152
Timer.startTimer (" Emit operand type mappings" );
1130
1153
emitOperandTypeMappings (OS, Target, NumberedInstructions);
1131
1154
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
+ }
1134
1159
1135
1160
Timer.startTimer (" Emit logical operand type mappings" );
1136
1161
emitLogicalOperandTypeMappings (OS, TargetName, NumberedInstructions);
0 commit comments