[llvm] 1220c5d - [MC] Store implicit ops immediately after the TargetInsts table. NFC.
Jay Foad via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 27 03:39:53 PDT 2023
Author: Jay Foad
Date: 2023-03-27T11:39:18+01:00
New Revision: 1220c5d4ac00ebf64128678e4ffd2abd9f5d60ae
URL: https://github.com/llvm/llvm-project/commit/1220c5d4ac00ebf64128678e4ffd2abd9f5d60ae
DIFF: https://github.com/llvm/llvm-project/commit/1220c5d4ac00ebf64128678e4ffd2abd9f5d60ae.diff
LOG: [MC] Store implicit ops immediately after the TargetInsts table. NFC.
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
Added:
Modified:
llvm/include/llvm/MC/MCInstrDesc.h
llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
llvm/unittests/CodeGen/MachineInstrTest.cpp
llvm/unittests/CodeGen/RegAllocScoreTest.cpp
llvm/utils/TableGen/InstrInfoEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCInstrDesc.h b/llvm/include/llvm/MC/MCInstrDesc.h
index 94350572412cb..bc69f884fe897 100644
--- a/llvm/include/llvm/MC/MCInstrDesc.h
+++ b/llvm/include/llvm/MC/MCInstrDesc.h
@@ -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
@@ -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
@@ -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
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 6cbb7120e2667..806ee70dba541 100644
--- 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 @@ 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!");
diff --git a/llvm/unittests/CodeGen/MachineInstrTest.cpp b/llvm/unittests/CodeGen/MachineInstrTest.cpp
index 574e90d22d574..62b1c6fabb8d6 100644
--- a/llvm/unittests/CodeGen/MachineInstrTest.cpp
+++ b/llvm/unittests/CodeGen/MachineInstrTest.cpp
@@ -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
diff erent virtual reg defs and the same uses.
unsigned VirtualDef1 = -42; // The value doesn't matter, but the sign does.
@@ -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
diff erent kinds of operands and make
// sure that the hash function is consistent with isEqual for various
@@ -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(
@@ -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);
@@ -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);
@@ -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();
@@ -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();
@@ -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();
@@ -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));
@@ -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));
diff --git a/llvm/unittests/CodeGen/RegAllocScoreTest.cpp b/llvm/unittests/CodeGen/RegAllocScoreTest.cpp
index 9a0a36aef1122..60ad94b5ed622 100644
--- a/llvm/unittests/CodeGen/RegAllocScoreTest.cpp
+++ b/llvm/unittests/CodeGen/RegAllocScoreTest.cpp
@@ -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
}};
diff --git a/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index c051775890244..58dec4eae6d16 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -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.
//===----------------------------------------------------------------------===//
@@ -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);
@@ -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)) {
@@ -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");
@@ -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, ";
@@ -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)
@@ -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, ";
@@ -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();
@@ -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())
More information about the llvm-commits
mailing list