@@ -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+ // /
338343void 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,10 +465,10 @@ 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 " ;
@@ -475,12 +479,15 @@ void InstrInfoEmitter::emitLogicalOperandSizeMappings(
475479 raw_ostream &OS, StringRef Namespace,
476480 ArrayRef<const CodeGenInstruction *> NumberedInstructions) {
477481 std::map<std::vector<unsigned >, unsigned > LogicalOpSizeMap;
478-
479482 std::map<unsigned , std::vector<std::string>> InstMap;
480483
481484 size_t LogicalOpListSize = 0U ;
482485 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)) {
484491 if (!Inst->TheDef ->getValueAsBit (" UseLogicalOperandMappings" ))
485492 continue ;
486493
@@ -907,22 +914,34 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
907914 unsigned OperandInfoSize =
908915 CollectOperandInfo (OperandInfoList, OperandInfoMap);
909916
917+ ArrayRef<const CodeGenInstruction *> NumberedInstructions =
918+ Target.getInstructionsByEnumValue ();
919+
910920 // 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+
911927 Timer.startTimer (" Collect uses/defs" );
912928 std::map<std::vector<const Record *>, unsigned > EmittedLists;
913929 std::vector<std::vector<const Record *>> ImplicitLists;
914930 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 );
918939 if (EmittedLists.insert ({ImplicitOps, ImplicitListSize}).second ) {
919940 ImplicitLists.push_back (ImplicitOps);
920941 ImplicitListSize += ImplicitOps.size ();
921942 }
922943 }
923944
924- ArrayRef<const CodeGenInstruction *> NumberedInstructions =
925- Target.getInstructionsByEnumValue ();
926945 OS << " #if defined(GET_INSTRINFO_MC_DESC) || "
927946 " defined(GET_INSTRINFO_CTOR_DTOR)\n " ;
928947 OS << " namespace llvm {\n\n " ;
@@ -1123,14 +1142,18 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
11231142
11241143 OS << " #endif // GET_INSTRINFO_CTOR_DTOR\n\n " ;
11251144
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+ }
11281149
11291150 Timer.startTimer (" Emit operand type mappings" );
11301151 emitOperandTypeMappings (OS, Target, NumberedInstructions);
11311152
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+ }
11341157
11351158 Timer.startTimer (" Emit logical operand type mappings" );
11361159 emitLogicalOperandTypeMappings (OS, TargetName, NumberedInstructions);
0 commit comments