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
/// 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 {
- return {ImplicitOps, NumImplicitUses};
+ auto ImplicitOps = reinterpret_cast<const MCPhysReg *>(this + Opcode + 1);
+ return {ImplicitOps + ImplicitOffset, NumImplicitUses};
}
/// Return a list of registers that are potentially written by any
/// registers. For that instruction, this will return a list containing the
/// EAX/EDX/EFLAGS registers.
ArrayRef<MCPhysReg> implicit_defs() const {
- return {ImplicitOps + NumImplicitUses, NumImplicitDefs};
+ auto ImplicitOps = reinterpret_cast<const MCPhysReg *>(this + Opcode + 1);
+ return {ImplicitOps + ImplicitOffset + NumImplicitUses, NumImplicitDefs};
}
/// Return true if this instruction implicitly
using namespace llvm;
namespace llvm {
-extern const MCInstrDesc ARMInsts[];
+extern const MCInstrDesc ARMDescs[];
} // end namespace llvm
namespace {
} 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!");
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.
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
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(
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);
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);
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();
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();
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();
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));
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));
const std::array<MCInstrDesc, MockInstrId::TotalMockInstrs> 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
}};
} // end anonymous namespace
-static void PrintDefList(const std::vector<Record *> &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.
//===----------------------------------------------------------------------===//
unsigned OperandListNum = 0;
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
- OS << "\n";
const CodeGenTarget &Target = CDP.getTargetInfo();
for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
std::vector<std::string> OperandInfo = GetOperandInfo(*Inst);
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<std::vector<Record*>, unsigned> EmittedLists;
- unsigned ListNumber = 0;
-
- // Emit all of the instruction's implicit uses and defs.
- Records.startTimer("Emit uses/defs");
+ std::vector<std::vector<Record *>> ImplicitLists;
+ unsigned ImplicitListSize = 0;
for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
std::vector<Record *> 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<const CodeGenInstruction *> 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<const CodeGenInstruction*> NumberedInstructions =
- Target.getInstructionsByEnumValue();
-
+ OS << "extern const " << TargetName << "InstrTable " << TargetName
+ << "Descs = {\n {\n";
SequenceToOffsetTable<std::string> InstrNames;
unsigned Num = NumberedInstructions.size();
for (const CodeGenInstruction *Inst : reverse(NumberedInstructions)) {
// 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");
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, ";
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)
"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, ";
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<Record *> ImplicitOps = Inst.ImplicitUses;
+ llvm::append_range(ImplicitOps, Inst.ImplicitDefs);
+ OS << EmittedLists[ImplicitOps] << ",\t0";
CodeGenTarget &Target = CDP.getTargetInfo();
OS.write_hex(Value);
OS << "ULL, ";
- // Emit the implicit use/def list...
- std::vector<Record *> 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<std::string> OperandInfo = GetOperandInfo(Inst);
if (OperandInfo.empty())