unsigned char NumDefs; // Num of args that are definitions
unsigned char Size; // Number of bytes in encoding.
unsigned short SchedClass; // enum identifying instr sched class
+ unsigned char NumImplicitUses; // Num of regs implicitly used
+ unsigned char NumImplicitDefs; // Num of regs implicitly defined
uint64_t Flags; // Flags identifying machine instr class
uint64_t TSFlags; // Target Specific Flag values
- const MCPhysReg *ImplicitUses; // Registers implicitly read by this instr
- const MCPhysReg *ImplicitDefs; // Registers implicitly defined by this instr
+ 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
/// flags register. In this case, the instruction is marked as implicitly
/// reading the flags. Likewise, the variable shift instruction on X86 is
/// marked as implicitly reading the 'CL' register, which it always does.
- ///
- /// This method returns null if the instruction has no implicit uses.
- const MCPhysReg *getImplicitUses() const { return ImplicitUses; }
ArrayRef<MCPhysReg> implicit_uses() const {
- return {ImplicitUses, getNumImplicitUses()};
- }
-
- /// Return the number of implicit uses this instruction has.
- unsigned getNumImplicitUses() const {
- if (!ImplicitUses)
- return 0;
- unsigned i = 0;
- for (; ImplicitUses[i]; ++i) /*empty*/
- ;
- return i;
+ return {ImplicitOps, NumImplicitUses};
}
/// Return a list of registers that are potentially written by any
/// instruction always deposits the quotient and remainder in the EAX/EDX
/// registers. For that instruction, this will return a list containing the
/// EAX/EDX/EFLAGS registers.
- ///
- /// This method returns null if the instruction has no implicit defs.
- const MCPhysReg *getImplicitDefs() const { return ImplicitDefs; }
ArrayRef<MCPhysReg> implicit_defs() const {
- return {ImplicitDefs, getNumImplicitDefs()};
- }
-
- /// Return the number of implicit defs this instruct has.
- unsigned getNumImplicitDefs() const {
- if (!ImplicitDefs)
- return 0;
- unsigned i = 0;
- for (; ImplicitDefs[i]; ++i) /*empty*/
- ;
- return i;
+ return {ImplicitOps + NumImplicitUses, NumImplicitDefs};
}
/// Return true if this instruction implicitly
MCOperandInfo OpInfo[] = {
{0, 0, MCOI::OPERAND_REGISTER, 0},
{0, 1 << MCOI::OptionalDef, MCOI::OPERAND_REGISTER, 0}};
- MCInstrDesc MCID = {
- 0, NumOps, NumDefs, 0, 0, 1ULL << MCID::HasOptionalDef,
- 0, nullptr, nullptr, OpInfo};
+ MCInstrDesc MCID = {0, NumOps, NumDefs, 0,
+ 0, 0, 0, 1ULL << MCID::HasOptionalDef,
+ 0, nullptr, 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, 1ULL << MCID::HasOptionalDef,
- 0, nullptr, nullptr, OpInfo};
+ MCInstrDesc MCID = {0, NumOps, NumDefs, 0,
+ 0, 0, 0, 1ULL << MCID::HasOptionalDef,
+ 0, nullptr, 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, nullptr, nullptr, &OpInfo};
+ MCInstrDesc MCID = {0, 1, 1, 0, 0, 0, 0, 0, 0, nullptr, &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, nullptr, nullptr, nullptr};
+ MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, 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, nullptr, nullptr, nullptr};
+ MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, 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, nullptr, nullptr, nullptr};
+ MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, 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, nullptr, nullptr, nullptr};
+ MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, 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, nullptr, nullptr, nullptr};
+ MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, 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, (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic),
- 0, nullptr, nullptr,
+ Opcode, 0,
+ 0, 0,
+ 0, 0,
+ 0, (1ULL << MCID::Pseudo) | (1ULL << MCID::Variadic),
+ 0, nullptr,
nullptr};
auto *MI = MF->CreateMachineInstr(MCID, DebugLoc());
Module Mod("Module", Ctx);
auto MF = createMachineFunction(Ctx, Mod);
auto MBB = MF->CreateMachineBasicBlock();
- MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr};
+ MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, 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));
static void PrintDefList(const std::vector<Record*> &Uses,
unsigned Num, raw_ostream &OS) {
OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
- for (Record *U : Uses)
- OS << getQualifiedName(U) << ", ";
- OS << "0 };\n";
+ for (auto [Idx, U] : enumerate(Uses))
+ OS << (Idx ? ", " : "") << getQualifiedName(U);
+ OS << " };\n";
}
//===----------------------------------------------------------------------===//
// Emit all of the instruction's implicit uses and defs.
Records.startTimer("Emit uses/defs");
for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
- if (!II->ImplicitUses.empty()) {
- unsigned &IL = EmittedLists[II->ImplicitUses];
+ std::vector<Record *> ImplicitOps = II->ImplicitUses;
+ llvm::append_range(ImplicitOps, II->ImplicitDefs);
+ if (!ImplicitOps.empty()) {
+ unsigned &IL = EmittedLists[ImplicitOps];
if (!IL) {
IL = ++ListNumber;
- PrintDefList(II->ImplicitUses, IL, OS);
- }
- }
- if (!II->ImplicitDefs.empty()) {
- unsigned &IL = EmittedLists[II->ImplicitDefs];
- if (!IL) {
- IL = ++ListNumber;
- PrintDefList(II->ImplicitDefs, IL, OS);
+ PrintDefList(ImplicitOps, IL, OS);
}
}
}
OS << Num << ",\t" << MinOperands << ",\t"
<< Inst.Operands.NumDefs << ",\t"
<< Inst.TheDef->getValueAsInt("Size") << ",\t"
- << SchedModels.getSchedClassIdx(Inst) << ",\t0";
+ << SchedModels.getSchedClassIdx(Inst) << ",\t"
+ << Inst.ImplicitUses.size() << ",\t"
+ << Inst.ImplicitDefs.size() << ",\t0";
CodeGenTarget &Target = CDP.getTargetInfo();
OS.write_hex(Value);
OS << "ULL, ";
- // Emit the implicit uses and defs lists...
- if (Inst.ImplicitUses.empty())
- OS << "nullptr, ";
- else
- OS << "ImplicitList" << EmittedLists[Inst.ImplicitUses] << ", ";
-
- if (Inst.ImplicitDefs.empty())
+ // 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[Inst.ImplicitDefs] << ", ";
+ OS << "ImplicitList" << EmittedLists[ImplicitOps] << ", ";
// Emit the operand info.
std::vector<std::string> OperandInfo = GetOperandInfo(Inst);