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));
// 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));
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
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,
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(
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;
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);
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);
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();
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();
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();
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));
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));
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
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);
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
// 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
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();
}
}
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;
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";
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;
// 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) {
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.
<< 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)";
}
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";
}