@@ -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,10 +465,10 @@ 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 " ;
@@ -475,12 +479,15 @@ void InstrInfoEmitter::emitLogicalOperandSizeMappings(
475
479
raw_ostream &OS, StringRef Namespace,
476
480
ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
477
481
std::map<std::vector<unsigned >, unsigned > LogicalOpSizeMap;
478
-
479
482
std::map<unsigned , std::vector<std::string>> InstMap;
480
483
481
484
size_t LogicalOpListSize = 0U ;
482
485
std::vector<unsigned > LogicalOpList;
483
- for (const auto *Inst : NumberedInstructions) {
486
+
487
+ // Fixed/Predefined instructions do not have UseLogicalOperandMappings
488
+ // enabled, so we can just skip them.
489
+ const unsigned NumFixedInsts = CDP.getTargetInfo ().getNumFixedInstructions ();
490
+ for (const auto *Inst : NumberedInstructions.drop_front (NumFixedInsts)) {
484
491
if (!Inst->TheDef ->getValueAsBit (" UseLogicalOperandMappings" ))
485
492
continue ;
486
493
@@ -907,22 +914,34 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
907
914
unsigned OperandInfoSize =
908
915
CollectOperandInfo (OperandInfoList, OperandInfoMap);
909
916
917
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions =
918
+ Target.getInstructionsByEnumValue ();
919
+
910
920
// Collect all of the instruction's implicit uses and defs.
921
+ // Also collect which features are enabled by instructions to control
922
+ // emission of various mappings.
923
+
924
+ bool HasUseLogicalOperandMappings = false ;
925
+ bool HasUseNamedOperandTable = false ;
926
+
911
927
Timer.startTimer (" Collect uses/defs" );
912
928
std::map<std::vector<const Record *>, unsigned > EmittedLists;
913
929
std::vector<std::vector<const Record *>> ImplicitLists;
914
930
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 );
931
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
932
+ HasUseLogicalOperandMappings |=
933
+ Inst->TheDef ->getValueAsBit (" UseLogicalOperandMappings" );
934
+ HasUseNamedOperandTable |=
935
+ Inst->TheDef ->getValueAsBit (" UseNamedOperandTable" );
936
+
937
+ std::vector<const Record *> ImplicitOps = Inst->ImplicitUses ;
938
+ llvm::append_range (ImplicitOps, Inst->ImplicitDefs );
918
939
if (EmittedLists.insert ({ImplicitOps, ImplicitListSize}).second ) {
919
940
ImplicitLists.push_back (ImplicitOps);
920
941
ImplicitListSize += ImplicitOps.size ();
921
942
}
922
943
}
923
944
924
- ArrayRef<const CodeGenInstruction *> NumberedInstructions =
925
- Target.getInstructionsByEnumValue ();
926
945
OS << " #if defined(GET_INSTRINFO_MC_DESC) || "
927
946
" defined(GET_INSTRINFO_CTOR_DTOR)\n " ;
928
947
OS << " namespace llvm {\n\n " ;
@@ -1123,14 +1142,18 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
1123
1142
1124
1143
OS << " #endif // GET_INSTRINFO_CTOR_DTOR\n\n " ;
1125
1144
1126
- Timer.startTimer (" Emit operand name mappings" );
1127
- emitOperandNameMappings (OS, Target, NumberedInstructions);
1145
+ if (HasUseNamedOperandTable) {
1146
+ Timer.startTimer (" Emit operand name mappings" );
1147
+ emitOperandNameMappings (OS, Target, NumberedInstructions);
1148
+ }
1128
1149
1129
1150
Timer.startTimer (" Emit operand type mappings" );
1130
1151
emitOperandTypeMappings (OS, Target, NumberedInstructions);
1131
1152
1132
- Timer.startTimer (" Emit logical operand size mappings" );
1133
- emitLogicalOperandSizeMappings (OS, TargetName, NumberedInstructions);
1153
+ if (HasUseLogicalOperandMappings) {
1154
+ Timer.startTimer (" Emit logical operand size mappings" );
1155
+ emitLogicalOperandSizeMappings (OS, TargetName, NumberedInstructions);
1156
+ }
1134
1157
1135
1158
Timer.startTimer (" Emit logical operand type mappings" );
1136
1159
emitLogicalOperandTypeMappings (OS, TargetName, NumberedInstructions);
0 commit comments