[MC] Store operand info immediately after the TargetInsts table. NFC.
authorJay Foad <jay.foad@amd.com>
Thu, 12 Jan 2023 21:02:23 +0000 (21:02 +0000)
committerJay Foad <jay.foad@amd.com>
Mon, 27 Mar 2023 10:39:18 +0000 (11:39 +0100)
This shrinks MCInstrDesc (and hence the whole TargetInsts table) because
we can store a 16-bit offset value to access the operands info, instead
of a pointer. This also reduces the number of relocs that need to be
applied when LLVM is compiled as position-independent code.

Differential Revision: https://reviews.llvm.org/D142219

llvm/include/llvm/MC/MCInstrDesc.h
llvm/unittests/CodeGen/MachineInstrTest.cpp
llvm/unittests/CodeGen/RegAllocScoreTest.cpp
llvm/utils/TableGen/InstrInfoEmitter.cpp

index bc69f88..0f406cb 100644 (file)
@@ -210,9 +210,9 @@ public:
   unsigned char NumImplicitUses; // Num of regs implicitly used
   unsigned char NumImplicitDefs; // Num of regs implicitly defined
   unsigned short ImplicitOffset; // Offset to start of implicit op list
+  unsigned short OpInfoOffset;   // Offset to info about operands
   uint64_t Flags;                // Flags identifying machine instr class
   uint64_t TSFlags;              // Target Specific Flag values
-  const MCOperandInfo *OpInfo;   // 'NumOperands' entries about operands
 
   /// Returns the value of the specified operand constraint if
   /// it is present. Returns -1 if it is not present.
@@ -237,7 +237,8 @@ public:
   unsigned getNumOperands() const { return NumOperands; }
 
   ArrayRef<MCOperandInfo> operands() const {
-    return ArrayRef(OpInfo, NumOperands);
+    auto OpInfo = reinterpret_cast<const MCOperandInfo *>(this + Opcode + 1);
+    return ArrayRef(OpInfo + OpInfoOffset, NumOperands);
   }
 
   /// Return the number of MachineOperands that are register
@@ -563,8 +564,9 @@ public:
   /// reading the flags.  Likewise, the variable shift instruction on X86 is
   /// marked as implicitly reading the 'CL' register, which it always does.
   ArrayRef<MCPhysReg> implicit_uses() const {
-    auto ImplicitOps = reinterpret_cast<const MCPhysReg *>(this + Opcode + 1);
-    return {ImplicitOps + ImplicitOffset, NumImplicitUses};
+    auto ImplicitOps =
+        reinterpret_cast<const MCPhysReg *>(this + Opcode + 1) + ImplicitOffset;
+    return {ImplicitOps, NumImplicitUses};
   }
 
   /// Return a list of registers that are potentially written by any
@@ -576,8 +578,9 @@ public:
   /// registers.  For that instruction, this will return a list containing the
   /// EAX/EDX/EFLAGS registers.
   ArrayRef<MCPhysReg> implicit_defs() const {
-    auto ImplicitOps = reinterpret_cast<const MCPhysReg *>(this + Opcode + 1);
-    return {ImplicitOps + ImplicitOffset + NumImplicitUses, NumImplicitDefs};
+    auto ImplicitOps =
+        reinterpret_cast<const MCPhysReg *>(this + Opcode + 1) + ImplicitOffset;
+    return {ImplicitOps + NumImplicitUses, NumImplicitDefs};
   }
 
   /// Return true if this instruction implicitly
index 62b1c6f..be409a5 100644 (file)
@@ -51,23 +51,24 @@ TEST(IsIdenticalToTest, DifferentDefs) {
 
   unsigned short NumOps = 2;
   unsigned char NumDefs = 1;
-  MCOperandInfo OpInfo[] = {
-      {0, 0, MCOI::OPERAND_REGISTER, 0},
-      {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
-  MCInstrDesc MCID = {
-      0, NumOps, NumDefs, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef,
-      0, OpInfo};
+  struct {
+    MCInstrDesc MCID;
+    MCOperandInfo OpInfo[2];
+  } Table = {
+      {0, NumOps, NumDefs, 0, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef, 0},
+      {{0, 0, MCOI::OPERAND_REGISTER, 0},
+       {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}};
 
   // Create two MIs with different virtual reg defs and the same uses.
   unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does.
   unsigned VirtualDef2 = -43;
   unsigned VirtualUse = -44;
 
-  auto MI1 = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto MI1 = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
   MI1->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
 
-  auto MI2 = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto MI2 = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
   MI2->addOperand(*MF, MachineOperand::CreateReg(VirtualUse, /*isDef*/ false));
 
@@ -83,11 +84,11 @@ TEST(IsIdenticalToTest, DifferentDefs) {
   // sentinel register.
   unsigned SentinelReg = 0;
 
-  auto MI3 = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto MI3 = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   MI3->addOperand(*MF, MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
   MI3->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
 
-  auto MI4 = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto MI4 = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   MI4->addOperand(*MF, MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
   MI4->addOperand(*MF, MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
 
@@ -122,12 +123,13 @@ TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
 
   unsigned short NumOps = 2;
   unsigned char NumDefs = 1;
-  MCOperandInfo OpInfo[] = {
-      {0, 0, MCOI::OPERAND_REGISTER, 0},
-      {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
-  MCInstrDesc MCID = {
-      0, NumOps, NumDefs, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef,
-      0, OpInfo};
+  struct {
+    MCInstrDesc MCID;
+    MCOperandInfo OpInfo[2];
+  } Table = {
+      {0, NumOps, NumDefs, 0, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef, 0},
+      {{0, 0, MCOI::OPERAND_REGISTER, 0},
+       {0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}}};
 
   // Define a series of instructions with different kinds of operands and make
   // sure that the hash function is consistent with isEqual for various
@@ -138,37 +140,37 @@ TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
   unsigned SentinelReg = 0;
   unsigned PhysicalReg = 45;
 
-  auto VD1VU = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto VD1VU = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   VD1VU->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
   VD1VU->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
 
-  auto VD2VU = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto VD2VU = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   VD2VU->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
   VD2VU->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualReg, /*isDef*/ false));
 
-  auto VD1SU = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto VD1SU = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   VD1SU->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
   VD1SU->addOperand(*MF,
                     MachineOperand::CreateReg(SentinelReg, /*isDef*/ false));
 
-  auto VD1SD = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto VD1SD = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   VD1SD->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualDef1, /*isDef*/ true));
   VD1SD->addOperand(*MF,
                     MachineOperand::CreateReg(SentinelReg, /*isDef*/ true));
 
-  auto VD2PU = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto VD2PU = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   VD2PU->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
   VD2PU->addOperand(*MF,
                     MachineOperand::CreateReg(PhysicalReg, /*isDef*/ false));
 
-  auto VD2PD = MF->CreateMachineInstr(MCID, DebugLoc());
+  auto VD2PD = MF->CreateMachineInstr(Table.MCID, DebugLoc());
   VD2PD->addOperand(*MF,
                     MachineOperand::CreateReg(VirtualDef2, /*isDef*/ true));
   VD2PD->addOperand(*MF,
@@ -200,8 +202,11 @@ TEST(MachineInstrPrintingTest, DebugLocPrinting) {
   Module Mod("Module", Ctx);
   auto MF = createMachineFunction(Ctx, Mod);
 
-  MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0};
-  MCInstrDesc MCID = {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, &OpInfo};
+  struct {
+    MCInstrDesc MCID;
+    MCOperandInfo OpInfo;
+  } Table = {{0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+             {0, 0, MCOI::OPERAND_REGISTER, 0}};
 
   DIFile *DIF = DIFile::getDistinct(Ctx, "filename", "");
   DISubprogram *DIS = DISubprogram::getDistinct(
@@ -209,7 +214,7 @@ TEST(MachineInstrPrintingTest, DebugLocPrinting) {
       DISubprogram::SPFlagZero, nullptr);
   DILocation *DIL = DILocation::get(Ctx, 1, 5, DIS);
   DebugLoc DL(DIL);
-  MachineInstr *MI = MF->CreateMachineInstr(MCID, DL);
+  MachineInstr *MI = MF->CreateMachineInstr(Table.MCID, DL);
   MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ true));
 
   std::string str;
@@ -228,7 +233,7 @@ TEST(MachineInstrSpan, DistanceBegin) {
   auto MF = createMachineFunction(Ctx, Mod);
   auto MBB = MF->CreateMachineBasicBlock();
 
-  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};
+  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
   auto MII = MBB->begin();
   MachineInstrSpan MIS(MII, MBB);
@@ -245,7 +250,7 @@ TEST(MachineInstrSpan, DistanceEnd) {
   auto MF = createMachineFunction(Ctx, Mod);
   auto MBB = MF->CreateMachineBasicBlock();
 
-  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};
+  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
   auto MII = MBB->end();
   MachineInstrSpan MIS(MII, MBB);
@@ -260,7 +265,7 @@ TEST(MachineInstrExtraInfo, AddExtraInfo) {
   LLVMContext Ctx;
   Module Mod("Module", Ctx);
   auto MF = createMachineFunction(Ctx, Mod);
-  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};
+  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
   auto MAI = MCAsmInfo();
@@ -320,7 +325,7 @@ TEST(MachineInstrExtraInfo, ChangeExtraInfo) {
   LLVMContext Ctx;
   Module Mod("Module", Ctx);
   auto MF = createMachineFunction(Ctx, Mod);
-  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};
+  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
   auto MAI = MCAsmInfo();
@@ -361,7 +366,7 @@ TEST(MachineInstrExtraInfo, RemoveExtraInfo) {
   LLVMContext Ctx;
   Module Mod("Module", Ctx);
   auto MF = createMachineFunction(Ctx, Mod);
-  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};
+  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
   auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
   auto MAI = MCAsmInfo();
@@ -428,10 +433,9 @@ TEST(MachineInstrDebugValue, AddDebugValueOperand) {
         TargetOpcode::DBG_INSTR_REF, TargetOpcode::DBG_PHI,
         TargetOpcode::DBG_LABEL}) {
     const MCInstrDesc MCID = {
-        Opcode, 0,      0,
-        0,      0,      0,
-        0,      0,      (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic),
-        0,      nullptr};
+        Opcode, 0, 0, 0, 0,
+        0,      0, 0, 0, (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic),
+        0};
 
     auto *MI = MF->CreateMachineInstr(MCID, DebugLoc());
     MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ false));
@@ -461,7 +465,7 @@ TEST(MachineInstrBuilder, BuildMI) {
   Module Mod("Module", Ctx);
   auto MF = createMachineFunction(Ctx, Mod);
   auto MBB = MF->CreateMachineBasicBlock();
-  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};
+  MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   EXPECT_THAT(BuildMI(*MF, MIMD, MCID), HasMIMetadata(MIMD));
   EXPECT_THAT(BuildMI(*MF, MIMD, MCID), HasMIMetadata(MIMD));
   EXPECT_THAT(BuildMI(*MBB, MBB->end(), MIMD, MCID), HasMIMetadata(MIMD));
index 60ad94b..ff7146e 100644 (file)
@@ -64,7 +64,7 @@ enum MockInstrId {
 
 const std::array<MCInstrDesc, MockInstrId::TotalMockInstrs> MockInstrDescs{{
 #define MOCK_SPEC(IGNORE, OPCODE, FLAGS)                                       \
-  {OPCODE, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0, nullptr},
+  {OPCODE, 0, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0},
     MOCK_INSTR(MOCK_SPEC)
 #undef MOCK_SPEC
 }};
index 58dec4e..d305858 100644 (file)
@@ -61,7 +61,9 @@ public:
 private:
   void emitEnums(raw_ostream &OS);
 
-  typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
+  typedef std::vector<std::string> OperandInfoTy;
+  typedef std::vector<OperandInfoTy> OperandInfoListTy;
+  typedef std::map<OperandInfoTy, unsigned> OperandInfoMapTy;
 
   /// The keys of this map are maps which have OpName enum values as their keys
   /// and instruction operand indices as their values.  The values of this map
@@ -86,9 +88,8 @@ private:
   void emitFeatureVerifier(raw_ostream &OS, const CodeGenTarget &Target);
   void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
                   Record *InstrInfo,
-                  std::map<std::vector<Record*>, unsigned> &EL,
-                  const OperandInfoMapTy &OpInfo,
-                  raw_ostream &OS);
+                  std::map<std::vector<Record *>, unsigned> &EL,
+                  const OperandInfoMapTy &OperandInfo, raw_ostream &OS);
   void emitOperandTypeMappings(
       raw_ostream &OS, const CodeGenTarget &Target,
       ArrayRef<const CodeGenInstruction *> NumberedInstructions);
@@ -108,8 +109,10 @@ private:
       ArrayRef<const CodeGenInstruction *> NumberedInstructions);
 
   // Operand information.
-  void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
-  std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
+  unsigned CollectOperandInfo(OperandInfoListTy &OperandInfoList,
+                              OperandInfoMapTy &OperandInfoMap);
+  void EmitOperandInfo(raw_ostream &OS, OperandInfoListTy &OperandInfoList);
+  OperandInfoTy GetOperandInfo(const CodeGenInstruction &Inst);
 };
 
 } // end anonymous namespace
@@ -118,9 +121,9 @@ private:
 // Operand Info Emission.
 //===----------------------------------------------------------------------===//
 
-std::vector<std::string>
+InstrInfoEmitter::OperandInfoTy
 InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
-  std::vector<std::string> Result;
+  OperandInfoTy Result;
 
   for (auto &Op : Inst.Operands) {
     // Handle aggregate operands and normal operands the same way by expanding
@@ -207,23 +210,30 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
   return Result;
 }
 
-void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
-                                       OperandInfoMapTy &OperandInfoIDs) {
-  // ID #0 is for no operand info.
-  unsigned OperandListNum = 0;
-  OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
-
+unsigned
+InstrInfoEmitter::CollectOperandInfo(OperandInfoListTy &OperandInfoList,
+                                     OperandInfoMapTy &OperandInfoMap) {
   const CodeGenTarget &Target = CDP.getTargetInfo();
+  unsigned Offset = 0;
   for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
-    std::vector<std::string> OperandInfo = GetOperandInfo(*Inst);
-    unsigned &N = OperandInfoIDs[OperandInfo];
-    if (N != 0) continue;
-
-    N = ++OperandListNum;
-    OS << "static const MCOperandInfo OperandInfo" << N << "[] = { ";
-    for (const std::string &Info : OperandInfo)
-      OS << "{ " << Info << " }, ";
-    OS << "};\n";
+    OperandInfoTy OperandInfo = GetOperandInfo(*Inst);
+    if (OperandInfoMap.insert({OperandInfo, Offset}).second) {
+      OperandInfoList.push_back(OperandInfo);
+      Offset += OperandInfo.size();
+    }
+  }
+  return Offset;
+}
+
+void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
+                                       OperandInfoListTy &OperandInfoList) {
+  unsigned Offset = 0;
+  for (auto &OperandInfo : OperandInfoList) {
+    OS << "    /* " << Offset << " */";
+    for (auto &Info : OperandInfo)
+      OS << " { " << Info << " },";
+    OS << '\n';
+    Offset += OperandInfo.size();
   }
 }
 
@@ -886,6 +896,13 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
   const std::string &TargetName = std::string(Target.getName());
   Record *InstrInfo = Target.getInstructionSet();
 
+  // Collect all of the operand info records.
+  Records.startTimer("Collect operand info");
+  OperandInfoListTy OperandInfoList;
+  OperandInfoMapTy OperandInfoMap;
+  unsigned OperandInfoSize =
+      CollectOperandInfo(OperandInfoList, OperandInfoMap);
+
   // Collect all of the instruction's implicit uses and defs.
   Records.startTimer("Collect uses/defs");
   std::map<std::vector<Record*>, unsigned> EmittedLists;
@@ -908,8 +925,11 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
 
   OS << "struct " << TargetName << "InstrTable {\n";
   OS << "  MCInstrDesc Insts[" << NumberedInstructions.size() << "];\n";
-  OS << "  static_assert(alignof(MCInstrDesc) >= alignof(MCPhysReg), "
-        "\"Unwanted padding between Insts and ImplicitOps\");\n";
+  OS << "  static_assert(alignof(MCInstrDesc) >= alignof(MCOperandInfo), "
+        "\"Unwanted padding between Insts and OperandInfo\");\n";
+  OS << "  MCOperandInfo OperandInfo[" << OperandInfoSize << "];\n";
+  OS << "  static_assert(alignof(MCOperandInfo) >= alignof(MCPhysReg), "
+        "\"Unwanted padding between OperandInfo and ImplicitOps\");\n";
   OS << "  MCPhysReg ImplicitOps[" << std::max(ImplicitListSize, 1U) << "];\n";
   OS << "};\n\n";
 
@@ -921,14 +941,12 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
   OS << "#undef GET_INSTRINFO_MC_DESC\n";
   OS << "namespace llvm {\n\n";
 
-  // Emit all of the operand info records.
-  Records.startTimer("Emit operand info");
-  OperandInfoMapTy OperandInfoIDs;
-  EmitOperandInfo(OS, OperandInfoIDs);
-  OS << "\n";
-
   // Emit all of the MCInstrDesc records in reverse ENUM ordering.
   Records.startTimer("Emit InstrDesc records");
+  OS << "static_assert(sizeof(MCOperandInfo) % sizeof(MCPhysReg) == 0);\n";
+  OS << "static constexpr unsigned " << TargetName << "ImpOpBase = sizeof "
+     << TargetName << "InstrTable::OperandInfo / (sizeof(MCPhysReg));\n\n";
+
   OS << "extern const " << TargetName << "InstrTable " << TargetName
      << "Descs = {\n  {\n";
   SequenceToOffsetTable<std::string> InstrNames;
@@ -937,11 +955,17 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
     // Keep a list of the instruction names.
     InstrNames.add(std::string(Inst->TheDef->getName()));
     // Emit the record into the table.
-    emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoIDs, OS);
+    emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoMap, OS);
   }
 
   OS << "  }, {\n";
 
+  // Emit all of the operand info records.
+  Records.startTimer("Emit operand info");
+  EmitOperandInfo(OS, OperandInfoList);
+
+  OS << "  }, {\n";
+
   // Emit all of the instruction's implicit uses and defs.
   Records.startTimer("Emit uses/defs");
   for (auto &List : ImplicitLists) {
@@ -1115,11 +1139,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
   emitFeatureVerifier(OS, Target);
 }
 
-void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
-                                  Record *InstrInfo,
-                         std::map<std::vector<Record*>, unsigned> &EmittedLists,
-                                  const OperandInfoMapTy &OpInfo,
-                                  raw_ostream &OS) {
+void InstrInfoEmitter::emitRecord(
+    const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo,
+    std::map<std::vector<Record *>, unsigned> &EmittedLists,
+    const OperandInfoMapTy &OperandInfoMap, raw_ostream &OS) {
   int MinOperands = 0;
   if (!Inst.Operands.empty())
     // Each logical operand can be multiple MI operands.
@@ -1131,13 +1154,18 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
      << Inst.TheDef->getValueAsInt("Size") << ",\t"
      << SchedModels.getSchedClassIdx(Inst) << ",\t";
 
+  CodeGenTarget &Target = CDP.getTargetInfo();
+
   // Emit the implicit use/def list...
   OS << Inst.ImplicitUses.size() << ",\t" << Inst.ImplicitDefs.size() << ",\t";
   std::vector<Record *> ImplicitOps = Inst.ImplicitUses;
   llvm::append_range(ImplicitOps, Inst.ImplicitDefs);
-  OS << EmittedLists[ImplicitOps] << ",\t0";
+  OS << Target.getName() << "ImpOpBase + " << EmittedLists[ImplicitOps]
+     << ",\t";
 
-  CodeGenTarget &Target = CDP.getTargetInfo();
+  // Emit the operand info offset.
+  OperandInfoTy OperandInfo = GetOperandInfo(Inst);
+  OS << OperandInfoMap.find(OperandInfo)->second << ",\t0";
 
   // Emit all of the target independent flags...
   if (Inst.isPreISelOpcode)    OS << "|(1ULL<<MCID::PreISelOpcode)";
@@ -1198,14 +1226,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
   }
   OS << ", 0x";
   OS.write_hex(Value);
-  OS << "ULL, ";
-
-  // Emit the operand info.
-  std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
-  if (OperandInfo.empty())
-    OS << "nullptr";
-  else
-    OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
+  OS << "ULL";
 
   OS << " },  // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
 }