diff --git a/llvm/include/llvm/MC/MCInstrDesc.h b/llvm/include/llvm/MC/MCInstrDesc.h --- a/llvm/include/llvm/MC/MCInstrDesc.h +++ b/llvm/include/llvm/MC/MCInstrDesc.h @@ -209,9 +209,9 @@ unsigned short SchedClass; // enum identifying instr sched class 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 uint64_t Flags; // Flags identifying machine instr class uint64_t TSFlags; // Target Specific Flag values - const MCPhysReg *ImplicitOps; // List of implicit uses followed by defs const MCOperandInfo *OpInfo; // 'NumOperands' entries about operands /// Returns the value of the specified operand constraint if @@ -563,7 +563,8 @@ /// reading the flags. Likewise, the variable shift instruction on X86 is /// marked as implicitly reading the 'CL' register, which it always does. ArrayRef implicit_uses() const { - return {ImplicitOps, NumImplicitUses}; + auto ImplicitOps = reinterpret_cast(this + Opcode + 1); + return {ImplicitOps + ImplicitOffset, NumImplicitUses}; } /// Return a list of registers that are potentially written by any @@ -575,7 +576,8 @@ /// registers. For that instruction, this will return a list containing the /// EAX/EDX/EFLAGS registers. ArrayRef implicit_defs() const { - return {ImplicitOps + NumImplicitUses, NumImplicitDefs}; + auto ImplicitOps = reinterpret_cast(this + Opcode + 1); + return {ImplicitOps + ImplicitOffset + NumImplicitUses, NumImplicitDefs}; } /// Return true if this instruction implicitly diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -70,7 +70,7 @@ using namespace llvm; namespace llvm { -extern const MCInstrDesc ARMInsts[]; +extern const MCInstrDesc ARMDescs[]; } // end namespace llvm namespace { @@ -2504,7 +2504,7 @@ } else { unsigned NextOpIndex = Inst.getNumOperands(); const MCInstrDesc &MCID = - ARMInsts[ARM::INSTRUCTION_LIST_END - 1 - Inst.getOpcode()]; + ARMDescs[ARM::INSTRUCTION_LIST_END - 1 - Inst.getOpcode()]; int TiedOp = MCID.getOperandConstraint(NextOpIndex, MCOI::TIED_TO); assert(TiedOp >= 0 && "Inactive register in vpred_r is not tied to an output!"); diff --git a/llvm/unittests/CodeGen/MachineInstrTest.cpp b/llvm/unittests/CodeGen/MachineInstrTest.cpp --- a/llvm/unittests/CodeGen/MachineInstrTest.cpp +++ b/llvm/unittests/CodeGen/MachineInstrTest.cpp @@ -54,9 +54,9 @@ 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, 1ULL << MCID::HasOptionalDef, - 0, nullptr, OpInfo}; + MCInstrDesc MCID = { + 0, NumOps, NumDefs, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef, + 0, OpInfo}; // Create two MIs with different virtual reg defs and the same uses. unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does. @@ -125,9 +125,9 @@ 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, 1ULL << MCID::HasOptionalDef, - 0, nullptr, OpInfo}; + MCInstrDesc MCID = { + 0, NumOps, NumDefs, 0, 0, 0, 0, 0, 1ULL << MCID::HasOptionalDef, + 0, OpInfo}; // Define a series of instructions with different kinds of operands and make // sure that the hash function is consistent with isEqual for various @@ -201,7 +201,7 @@ auto MF = createMachineFunction(Ctx, Mod); MCOperandInfo OpInfo{0, 0, MCOI::OPERAND_REGISTER, 0}; - MCInstrDesc MCID = {0, 1, 1, 0, 0, 0, 0, 0, 0, nullptr, &OpInfo}; + MCInstrDesc MCID = {0, 1, 1, 0, 0, 0, 0, 0, 0, 0, &OpInfo}; DIFile *DIF = DIFile::getDistinct(Ctx, "filename", ""); DISubprogram *DIS = DISubprogram::getDistinct( @@ -228,7 +228,7 @@ auto MF = createMachineFunction(Ctx, Mod); auto MBB = MF->CreateMachineBasicBlock(); - MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr}; + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr}; auto MII = MBB->begin(); MachineInstrSpan MIS(MII, MBB); @@ -245,7 +245,7 @@ auto MF = createMachineFunction(Ctx, Mod); auto MBB = MF->CreateMachineBasicBlock(); - MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr}; + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr}; auto MII = MBB->end(); MachineInstrSpan MIS(MII, MBB); @@ -260,7 +260,7 @@ LLVMContext Ctx; Module Mod("Module", Ctx); auto MF = createMachineFunction(Ctx, Mod); - MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr}; + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr}; auto MI = MF->CreateMachineInstr(MCID, DebugLoc()); auto MAI = MCAsmInfo(); @@ -320,7 +320,7 @@ LLVMContext Ctx; Module Mod("Module", Ctx); auto MF = createMachineFunction(Ctx, Mod); - MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr}; + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr}; auto MI = MF->CreateMachineInstr(MCID, DebugLoc()); auto MAI = MCAsmInfo(); @@ -361,7 +361,7 @@ LLVMContext Ctx; Module Mod("Module", Ctx); auto MF = createMachineFunction(Ctx, Mod); - MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr}; + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr}; auto MI = MF->CreateMachineInstr(MCID, DebugLoc()); auto MAI = MCAsmInfo(); @@ -428,12 +428,10 @@ TargetOpcode::DBG_INSTR_REF, TargetOpcode::DBG_PHI, TargetOpcode::DBG_LABEL}) { const MCInstrDesc MCID = { - Opcode, 0, - 0, 0, - 0, 0, - 0, (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic), - 0, nullptr, - nullptr}; + Opcode, 0, 0, + 0, 0, 0, + 0, 0, (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic), + 0, nullptr}; auto *MI = MF->CreateMachineInstr(MCID, DebugLoc()); MI->addOperand(*MF, MachineOperand::CreateReg(0, /*isDef*/ false)); @@ -463,7 +461,7 @@ Module Mod("Module", Ctx); auto MF = createMachineFunction(Ctx, Mod); auto MBB = MF->CreateMachineBasicBlock(); - MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr}; + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr}; 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)); diff --git a/llvm/unittests/CodeGen/RegAllocScoreTest.cpp b/llvm/unittests/CodeGen/RegAllocScoreTest.cpp --- a/llvm/unittests/CodeGen/RegAllocScoreTest.cpp +++ b/llvm/unittests/CodeGen/RegAllocScoreTest.cpp @@ -64,7 +64,7 @@ const std::array MockInstrDescs{{ #define MOCK_SPEC(IGNORE, OPCODE, FLAGS) \ - {OPCODE, 0, 0, 0, 0, 0, 0, FLAGS, 0, nullptr, nullptr}, + {OPCODE, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0, nullptr}, MOCK_INSTR(MOCK_SPEC) #undef MOCK_SPEC }}; diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp --- a/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -114,14 +114,6 @@ } // end anonymous namespace -static void PrintDefList(const std::vector &Uses, unsigned Num, - raw_ostream &OS) { - OS << "static const MCPhysReg ImplicitList" << Num << "[] = { "; - for (auto [Idx, U] : enumerate(Uses)) - OS << (Idx ? ", " : "") << getQualifiedName(U); - OS << " };\n"; -} - //===----------------------------------------------------------------------===// // Operand Info Emission. //===----------------------------------------------------------------------===// @@ -221,7 +213,6 @@ unsigned OperandListNum = 0; OperandInfoIDs[std::vector()] = ++OperandListNum; - OS << "\n"; const CodeGenTarget &Target = CDP.getTargetInfo(); for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { std::vector OperandInfo = GetOperandInfo(*Inst); @@ -891,45 +882,55 @@ emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS); emitEnums(OS); - OS << "#ifdef GET_INSTRINFO_MC_DESC\n"; - OS << "#undef GET_INSTRINFO_MC_DESC\n"; - - OS << "namespace llvm {\n\n"; - CodeGenTarget &Target = CDP.getTargetInfo(); const std::string &TargetName = std::string(Target.getName()); Record *InstrInfo = Target.getInstructionSet(); - // Keep track of all of the def lists we have emitted already. + // Collect all of the instruction's implicit uses and defs. + Records.startTimer("Collect uses/defs"); std::map, unsigned> EmittedLists; - unsigned ListNumber = 0; - - // Emit all of the instruction's implicit uses and defs. - Records.startTimer("Emit uses/defs"); + std::vector> ImplicitLists; + unsigned ImplicitListSize = 0; for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) { std::vector ImplicitOps = II->ImplicitUses; llvm::append_range(ImplicitOps, II->ImplicitDefs); - if (!ImplicitOps.empty()) { - unsigned &IL = EmittedLists[ImplicitOps]; - if (!IL) { - IL = ++ListNumber; - PrintDefList(ImplicitOps, IL, OS); - } + if (EmittedLists.insert({ImplicitOps, ImplicitListSize}).second) { + ImplicitLists.push_back(ImplicitOps); + ImplicitListSize += ImplicitOps.size(); } } - OperandInfoMapTy OperandInfoIDs; + ArrayRef NumberedInstructions = + Target.getInstructionsByEnumValue(); + OS << "#if defined(GET_INSTRINFO_MC_DESC) || " + "defined(GET_INSTRINFO_CTOR_DTOR)\n"; + OS << "namespace llvm {\n\n"; + + 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 << " MCPhysReg ImplicitOps[" << std::max(ImplicitListSize, 1U) << "];\n"; + OS << "};\n\n"; + + OS << "} // end namespace llvm\n"; + OS << "#endif // defined(GET_INSTRINFO_MC_DESC) || " + "defined(GET_INSTRINFO_CTOR_DTOR)\n\n"; + + OS << "#ifdef GET_INSTRINFO_MC_DESC\n"; + 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 << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n"; - ArrayRef NumberedInstructions = - Target.getInstructionsByEnumValue(); - + OS << "extern const " << TargetName << "InstrTable " << TargetName + << "Descs = {\n {\n"; SequenceToOffsetTable InstrNames; unsigned Num = NumberedInstructions.size(); for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) { @@ -938,7 +939,19 @@ // Emit the record into the table. emitRecord(*Inst, --Num, InstrInfo, EmittedLists, OperandInfoIDs, OS); } - OS << "};\n\n"; + + OS << " }, {\n"; + + // Emit all of the instruction's implicit uses and defs. + Records.startTimer("Emit uses/defs"); + for (auto &List : ImplicitLists) { + OS << " /* " << EmittedLists[List] << " */"; + for (auto &Reg : List) + OS << ' ' << getQualifiedName(Reg) << ','; + OS << '\n'; + } + + OS << " }\n};\n\n"; // Emit the array of instruction names. Records.startTimer("Emit instruction names"); @@ -1005,7 +1018,7 @@ Records.startTimer("Emit initialization routine"); OS << "static inline void Init" << TargetName << "MCInstrInfo(MCInstrInfo *II) {\n"; - OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " << TargetName + OS << " II->InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "; if (HasDeprecationFeatures) OS << TargetName << "InstrDeprecationFeatures, "; @@ -1053,7 +1066,8 @@ OS << "#undef GET_INSTRINFO_CTOR_DTOR\n"; OS << "namespace llvm {\n"; - OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n"; + OS << "extern const " << TargetName << "InstrTable " << TargetName + << "Descs;\n"; OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n"; OS << "extern const char " << TargetName << "InstrNameData[];\n"; if (HasDeprecationFeatures) @@ -1067,7 +1081,7 @@ "CatchRetOpcode, unsigned ReturnOpcode)\n" << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, " "ReturnOpcode) {\n" - << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName + << " InitMCInstrInfo(" << TargetName << "Descs.Insts, " << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "; if (HasDeprecationFeatures) OS << TargetName << "InstrDeprecationFeatures, "; @@ -1112,13 +1126,16 @@ MinOperands = Inst.Operands.back().MIOperandNo + Inst.Operands.back().MINumOperands; - OS << " { "; - OS << Num << ",\t" << MinOperands << ",\t" - << Inst.Operands.NumDefs << ",\t" + OS << " { "; + OS << Num << ",\t" << MinOperands << ",\t" << Inst.Operands.NumDefs << ",\t" << Inst.TheDef->getValueAsInt("Size") << ",\t" - << SchedModels.getSchedClassIdx(Inst) << ",\t" - << Inst.ImplicitUses.size() << ",\t" - << Inst.ImplicitDefs.size() << ",\t0"; + << SchedModels.getSchedClassIdx(Inst) << ",\t"; + + // Emit the implicit use/def list... + OS << Inst.ImplicitUses.size() << ",\t" << Inst.ImplicitDefs.size() << ",\t"; + std::vector ImplicitOps = Inst.ImplicitUses; + llvm::append_range(ImplicitOps, Inst.ImplicitDefs); + OS << EmittedLists[ImplicitOps] << ",\t0"; CodeGenTarget &Target = CDP.getTargetInfo(); @@ -1183,14 +1200,6 @@ OS.write_hex(Value); OS << "ULL, "; - // Emit the implicit use/def list... - std::vector ImplicitOps = Inst.ImplicitUses; - llvm::append_range(ImplicitOps, Inst.ImplicitDefs); - if (ImplicitOps.empty()) - OS << "nullptr, "; - else - OS << "ImplicitList" << EmittedLists[ImplicitOps] << ", "; - // Emit the operand info. std::vector OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty())