Skip to content

Commit

Permalink
[MC] Store implicit ops immediately after the TargetInsts table. NFC.
Browse files Browse the repository at this point in the history
This shrinks MCInstrDesc (and hence the whole TargetInsts table) because
we can store a 16-bit offset value to access the implicit operands,
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/D142218
  • Loading branch information
jayfoad committed Mar 27, 2023
1 parent a826b90 commit 1220c5d
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 73 deletions.
8 changes: 5 additions & 3 deletions llvm/include/llvm/MC/MCInstrDesc.h
Expand Up @@ -209,9 +209,9 @@ class MCInstrDesc {
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
Expand Down Expand Up @@ -563,7 +563,8 @@ class MCInstrDesc {
/// 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
Expand All @@ -575,7 +576,8 @@ class MCInstrDesc {
/// 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
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
Expand Up @@ -70,7 +70,7 @@
using namespace llvm;

namespace llvm {
extern const MCInstrDesc ARMInsts[];
extern const MCInstrDesc ARMDescs[];
} // end namespace llvm

namespace {
Expand Down Expand Up @@ -2504,7 +2504,7 @@ class ARMOperand : public MCParsedAsmOperand {
} 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!");
Expand Down
36 changes: 17 additions & 19 deletions llvm/unittests/CodeGen/MachineInstrTest.cpp
Expand Up @@ -54,9 +54,9 @@ TEST(IsIdenticalToTest, DifferentDefs) {
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.
Expand Down Expand Up @@ -125,9 +125,9 @@ TEST(MachineInstrExpressionTraitTest, IsEqualAgreesWithGetHashValue) {
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
Expand Down Expand Up @@ -201,7 +201,7 @@ TEST(MachineInstrPrintingTest, DebugLocPrinting) {
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(
Expand All @@ -228,7 +228,7 @@ TEST(MachineInstrSpan, DistanceBegin) {
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);
Expand All @@ -245,7 +245,7 @@ TEST(MachineInstrSpan, DistanceEnd) {
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);
Expand All @@ -260,7 +260,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, nullptr, nullptr};
MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};

auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
auto MAI = MCAsmInfo();
Expand Down Expand Up @@ -320,7 +320,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, nullptr, nullptr};
MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};

auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
auto MAI = MCAsmInfo();
Expand Down Expand Up @@ -361,7 +361,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, nullptr, nullptr};
MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr};

auto MI = MF->CreateMachineInstr(MCID, DebugLoc());
auto MAI = MCAsmInfo();
Expand Down Expand Up @@ -428,12 +428,10 @@ TEST(MachineInstrDebugValue, AddDebugValueOperand) {
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));
Expand Down Expand Up @@ -463,7 +461,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, 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));
Expand Down
2 changes: 1 addition & 1 deletion llvm/unittests/CodeGen/RegAllocScoreTest.cpp
Expand Up @@ -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, FLAGS, 0, nullptr, nullptr},
{OPCODE, 0, 0, 0, 0, 0, 0, 0, FLAGS, 0, nullptr},
MOCK_INSTR(MOCK_SPEC)
#undef MOCK_SPEC
}};
Expand Down
105 changes: 57 additions & 48 deletions llvm/utils/TableGen/InstrInfoEmitter.cpp
Expand Up @@ -114,14 +114,6 @@ class InstrInfoEmitter {

} // 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.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -221,7 +213,6 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
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);
Expand Down Expand Up @@ -891,45 +882,55 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
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)) {
Expand All @@ -938,7 +939,19 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
// 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");
Expand Down Expand Up @@ -1005,7 +1018,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
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, ";
Expand Down Expand Up @@ -1053,7 +1066,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
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)
Expand All @@ -1067,7 +1081,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
"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, ";
Expand Down Expand Up @@ -1112,13 +1126,16 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
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();

Expand Down Expand Up @@ -1183,14 +1200,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
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())
Expand Down

0 comments on commit 1220c5d

Please sign in to comment.