[llvm] [llvm][AsmPrinter] Add an option to print instruction latencies (PR #113243)
Jon Roelofs via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 26 09:01:07 PDT 2024
https://github.com/jroelofs updated https://github.com/llvm/llvm-project/pull/113243
>From 49ed93d9bed8c1f373c848de2255428aa7805156 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Mon, 21 Oct 2024 17:52:35 -0700
Subject: [PATCH 01/11] [llvm][AsmPrinter] Add an option to print instruction
latencies
... matching what we have in the disassembler. This isn't turned on by default
since several of the scheduling models are not completely accurate, and we
don't want to be misleading.
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 94 +++++++++++++++++++++-
llvm/test/CodeGen/AArch64/latency.ll | 10 +++
2 files changed, 102 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/latency.ll
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 2d444f2f970ac1..dce558eaa6a75b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -166,6 +166,13 @@ static cl::opt<bool> EmitJumpTableSizesSection(
cl::desc("Emit a section containing jump table addresses and sizes"),
cl::Hidden, cl::init(false));
+// This isn't turned on by default, since several of the scheduling models are
+// not completely accurate, and we don't want to be misleading.
+static cl::opt<bool> PrintLatency(
+ "asm-print-latency",
+ cl::desc("Print instruction latencies as verbose asm comments."),
+ cl::Hidden, cl::init(false));
+
STATISTIC(EmittedInsts, "Number of machine instrs printed");
char AsmPrinter::ID = 0;
@@ -1084,8 +1091,78 @@ void AsmPrinter::emitFunctionEntryLabel() {
}
}
+/// Gets latency information for \p Inst from the itinerary
+/// scheduling model.
+/// \return The maximum expected latency over all the operands or -1
+/// if no information is available.
+static int getItineraryLatency(const MachineInstr &MI,
+ const MachineFunction *MF,
+ const MCSubtargetInfo *STI) {
+ const int NoInformationAvailable = -1;
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+
+ // Check if we have a CPU to get the itinerary information.
+ if (STI->getCPU().empty())
+ return NoInformationAvailable;
+
+ // Get itinerary information.
+ InstrItineraryData IID = STI->getInstrItineraryForCPU(STI->getCPU());
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc &Desc = TII->get(MI.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+
+ unsigned Latency = 0;
+
+ for (unsigned Idx = 0, IdxEnd = MI.getNumOperands(); Idx != IdxEnd; ++Idx)
+ if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
+ Latency = std::max(Latency, *OperCycle);
+
+ return (int)Latency;
+}
+
+/// Gets latency information for \p Inst.
+/// \return The maximum expected latency over all the definitions or -1
+/// if no information is available.
+static int getLatency(const MachineInstr &MI, const MCSubtargetInfo *STI) {
+ const MCSchedModel SCModel = STI->getSchedModel();
+ const int NoInformationAvailable = -1;
+
+ const MachineFunction *MF = MI.getMF();
+ if (!MF)
+ return NoInformationAvailable;
+
+ // Check if we have a scheduling model for instructions.
+ if (!SCModel.hasInstrSchedModel())
+ // Try to fall back to the itinerary model if the scheduling model doesn't
+ // have a scheduling table. Note the default does not have a table.
+ return getItineraryLatency(MI, MF, STI);
+
+ // Get the scheduling class of the requested instruction.
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+ const MCInstrDesc &Desc = TII->get(MI.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+ const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
+ // Resolving the variant SchedClass requires an MI to pass to
+ // SubTargetInfo::resolveSchedClass.
+ if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
+ return NoInformationAvailable;
+
+ // Compute output latency.
+ int16_t Latency = 0;
+ for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
+ DefIdx != DefEnd; ++DefIdx) {
+ // Lookup the definition's write latency in SubtargetInfo.
+ const MCWriteLatencyEntry *WLEntry =
+ STI->getWriteLatencyEntry(SCDesc, DefIdx);
+ Latency = std::max(Latency, WLEntry->Cycles);
+ }
+
+ return Latency;
+}
+
/// emitComments - Pretty-print comments for instructions.
-static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
+static void emitComments(const MachineInstr &MI, const MCSubtargetInfo *STI,
+ raw_ostream &CommentOS) {
const MachineFunction *MF = MI.getMF();
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
@@ -1113,6 +1190,13 @@ static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
// Check for spill-induced copies
if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
CommentOS << " Reload Reuse\n";
+
+ if (PrintLatency) {
+ int Latency = getLatency(MI, STI);
+ // Report only interesting latencies.
+ if (1 < Latency)
+ CommentOS << " Latency: " << Latency << "\n";
+ }
}
/// emitImplicitDef - This method emits the specified machine instruction
@@ -1763,6 +1847,12 @@ void AsmPrinter::emitFunctionBody() {
int NumInstsInFunction = 0;
bool IsEHa = MMI->getModule()->getModuleFlag("eh-asynch");
+ const MCSubtargetInfo *STI = nullptr;
+ if (this->MF)
+ STI = &getSubtargetInfo();
+ else
+ STI = TM.getMCSubtargetInfo();
+
bool CanDoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE);
for (auto &MBB : *MF) {
// Print a label for the basic block.
@@ -1786,7 +1876,7 @@ void AsmPrinter::emitFunctionBody() {
Handler->beginInstruction(&MI);
if (isVerbose())
- emitComments(MI, OutStreamer->getCommentOS());
+ emitComments(MI, STI, OutStreamer->getCommentOS());
switch (MI.getOpcode()) {
case TargetOpcode::CFI_INSTRUCTION:
diff --git a/llvm/test/CodeGen/AArch64/latency.ll b/llvm/test/CodeGen/AArch64/latency.ll
new file mode 100644
index 00000000000000..b722eec3e2571a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/latency.ll
@@ -0,0 +1,10 @@
+; RUN: llc -mtriple=arm64-apple-ios %s -o - -mcpu=cyclone -asm-print-latency=1 | FileCheck %s --match-full-lines --check-prefix=ON
+; RUN: llc -mtriple=arm64-apple-ios %s -o - -mcpu=cyclone -asm-print-latency=0 | FileCheck %s --match-full-lines --check-prefix=OFF
+; RUN: llc -mtriple=arm64-apple-ios %s -o - -mcpu=cyclone | FileCheck %s --match-full-lines --check-prefix=OFF
+
+define <4 x i64> @load_v4i64(ptr %ptr){
+; ON: ldp q0, q1, [x0] ; Latency: 4
+; OFF: ldp q0, q1, [x0]
+ %a = load <4 x i64>, ptr %ptr
+ ret <4 x i64> %a
+}
>From 78da0e3f27d4e5d3da569d97dfd5bdbc277a26b8 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 22 Oct 2024 19:08:08 -0700
Subject: [PATCH 02/11] add a test for a cpu with itineraries
---
llvm/test/CodeGen/ARM/latency.ll | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 llvm/test/CodeGen/ARM/latency.ll
diff --git a/llvm/test/CodeGen/ARM/latency.ll b/llvm/test/CodeGen/ARM/latency.ll
new file mode 100644
index 00000000000000..ada6254666fdef
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/latency.ll
@@ -0,0 +1,16 @@
+; RUN: llc -mtriple=thumb-none-eabi %s -o - -mcpu=cortex-m0 -asm-print-latency=1 | FileCheck %s --match-full-lines --check-prefix=ON
+; RUN: llc -mtriple=thumb-none-eabi %s -o - -mcpu=cortex-m0 -asm-print-latency=0 | FileCheck %s --match-full-lines --check-prefix=OFF
+; RUN: llc -mtriple=thumb-none-eabi %s -o - -mcpu=cortex-m0 | FileCheck %s --match-full-lines --check-prefix=OFF
+
+define i64 @load_i64(ptr %ptr){
+; ON: ldr r2, [r0] @ Latency: 4
+; ON: ldr r1, [r0, #4] @ Latency: 4
+; ON: mov r0, r2 @ Latency: 2
+; ON: bx lr
+; OFF: ldr r2, [r0]
+; OFF: ldr r1, [r0, #4]
+; OFF: mov r0, r2
+; OFf: bx lr
+ %a = load i64, ptr %ptr
+ ret i64 %a
+}
>From 90cb604a5bc9bdad9a25fb66519a67850981342c Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 22 Oct 2024 19:18:57 -0700
Subject: [PATCH 03/11] use MCSchedModel::computeInstrLatency
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 37 +++++++--------------
llvm/lib/MC/MCDisassembler/Disassembler.cpp | 2 +-
2 files changed, 13 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index dce558eaa6a75b..0db06edfeb5564 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1095,15 +1095,14 @@ void AsmPrinter::emitFunctionEntryLabel() {
/// scheduling model.
/// \return The maximum expected latency over all the operands or -1
/// if no information is available.
-static int getItineraryLatency(const MachineInstr &MI,
+static std::optional<int> getItineraryLatency(const MachineInstr &MI,
const MachineFunction *MF,
const MCSubtargetInfo *STI) {
- const int NoInformationAvailable = -1;
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
// Check if we have a CPU to get the itinerary information.
if (STI->getCPU().empty())
- return NoInformationAvailable;
+ return std::nullopt;
// Get itinerary information.
InstrItineraryData IID = STI->getInstrItineraryForCPU(STI->getCPU());
@@ -1117,14 +1116,14 @@ static int getItineraryLatency(const MachineInstr &MI,
if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
Latency = std::max(Latency, *OperCycle);
- return (int)Latency;
+ return int(Latency);
}
/// Gets latency information for \p Inst.
/// \return The maximum expected latency over all the definitions or -1
/// if no information is available.
-static int getLatency(const MachineInstr &MI, const MCSubtargetInfo *STI) {
- const MCSchedModel SCModel = STI->getSchedModel();
+static std::optional<int> getLatency(const MachineInstr &MI, const MCSubtargetInfo *STI) {
+ const MCSchedModel &SCModel = STI->getSchedModel();
const int NoInformationAvailable = -1;
const MachineFunction *MF = MI.getMF();
@@ -1141,22 +1140,9 @@ static int getLatency(const MachineInstr &MI, const MCSubtargetInfo *STI) {
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
const MCInstrDesc &Desc = TII->get(MI.getOpcode());
unsigned SCClass = Desc.getSchedClass();
- const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
- // Resolving the variant SchedClass requires an MI to pass to
- // SubTargetInfo::resolveSchedClass.
- if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
+ int Latency = SCModel.computeInstrLatency(*STI, SCClass);
+ if (Latency <= 0)
return NoInformationAvailable;
-
- // Compute output latency.
- int16_t Latency = 0;
- for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
- DefIdx != DefEnd; ++DefIdx) {
- // Lookup the definition's write latency in SubtargetInfo.
- const MCWriteLatencyEntry *WLEntry =
- STI->getWriteLatencyEntry(SCDesc, DefIdx);
- Latency = std::max(Latency, WLEntry->Cycles);
- }
-
return Latency;
}
@@ -1192,10 +1178,11 @@ static void emitComments(const MachineInstr &MI, const MCSubtargetInfo *STI,
CommentOS << " Reload Reuse\n";
if (PrintLatency) {
- int Latency = getLatency(MI, STI);
- // Report only interesting latencies.
- if (1 < Latency)
- CommentOS << " Latency: " << Latency << "\n";
+ if (auto Latency = getLatency(MI, STI)) {
+ // Report only interesting latencies.
+ if (1 < *Latency)
+ CommentOS << " Latency: " << *Latency << "\n";
+ }
}
}
diff --git a/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index f5d6c6bb561871..ac0fe382177ad7 100644
--- a/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -195,7 +195,7 @@ static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
// Try to compute scheduling information.
const MCSubtargetInfo *STI = DC->getSubtargetInfo();
- const MCSchedModel SCModel = STI->getSchedModel();
+ const MCSchedModel &SCModel = STI->getSchedModel();
const int NoInformationAvailable = -1;
// Check if we have a scheduling model for instructions.
>From 071fa717fed2834587b291cb70c00e8da33a51cc Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 22 Oct 2024 19:23:50 -0700
Subject: [PATCH 04/11] simplify both implementations
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 5 ++---
llvm/lib/MC/MCDisassembler/Disassembler.cpp | 23 +++------------------
2 files changed, 5 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0db06edfeb5564..82be03862fb778 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1124,11 +1124,10 @@ static std::optional<int> getItineraryLatency(const MachineInstr &MI,
/// if no information is available.
static std::optional<int> getLatency(const MachineInstr &MI, const MCSubtargetInfo *STI) {
const MCSchedModel &SCModel = STI->getSchedModel();
- const int NoInformationAvailable = -1;
const MachineFunction *MF = MI.getMF();
if (!MF)
- return NoInformationAvailable;
+ return std::nullopt;
// Check if we have a scheduling model for instructions.
if (!SCModel.hasInstrSchedModel())
@@ -1142,7 +1141,7 @@ static std::optional<int> getLatency(const MachineInstr &MI, const MCSubtargetIn
unsigned SCClass = Desc.getSchedClass();
int Latency = SCModel.computeInstrLatency(*STI, SCClass);
if (Latency <= 0)
- return NoInformationAvailable;
+ return std::nullopt;
return Latency;
}
diff --git a/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index ac0fe382177ad7..69a5c9246c50d3 100644
--- a/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -186,7 +186,7 @@ static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
Latency = std::max(Latency, *OperCycle);
- return (int)Latency;
+ return int(Latency);
}
/// Gets latency information for \p Inst, based on \p DC information.
@@ -196,7 +196,6 @@ static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
// Try to compute scheduling information.
const MCSubtargetInfo *STI = DC->getSubtargetInfo();
const MCSchedModel &SCModel = STI->getSchedModel();
- const int NoInformationAvailable = -1;
// Check if we have a scheduling model for instructions.
if (!SCModel.hasInstrSchedModel())
@@ -205,25 +204,9 @@ static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
return getItineraryLatency(DC, Inst);
// Get the scheduling class of the requested instruction.
- const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ const MCInstrDesc &Desc = DC->getInstrInfo()->get(Inst.getOpcode());
unsigned SCClass = Desc.getSchedClass();
- const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass);
- // Resolving the variant SchedClass requires an MI to pass to
- // SubTargetInfo::resolveSchedClass.
- if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant())
- return NoInformationAvailable;
-
- // Compute output latency.
- int16_t Latency = 0;
- for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
- DefIdx != DefEnd; ++DefIdx) {
- // Lookup the definition's write latency in SubtargetInfo.
- const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc,
- DefIdx);
- Latency = std::max(Latency, WLEntry->Cycles);
- }
-
- return Latency;
+ return SCModel.computeInstrLatency(*STI, SCClass);
}
/// Emits latency information in DC->CommentStream for \p Inst, based
>From 3be57dd82fe17045924b3614053323b1ca56b1b4 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Tue, 22 Oct 2024 19:28:42 -0700
Subject: [PATCH 05/11] clang-format
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 82be03862fb778..28b6f0b59807ee 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1096,8 +1096,8 @@ void AsmPrinter::emitFunctionEntryLabel() {
/// \return The maximum expected latency over all the operands or -1
/// if no information is available.
static std::optional<int> getItineraryLatency(const MachineInstr &MI,
- const MachineFunction *MF,
- const MCSubtargetInfo *STI) {
+ const MachineFunction *MF,
+ const MCSubtargetInfo *STI) {
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
// Check if we have a CPU to get the itinerary information.
@@ -1122,7 +1122,8 @@ static std::optional<int> getItineraryLatency(const MachineInstr &MI,
/// Gets latency information for \p Inst.
/// \return The maximum expected latency over all the definitions or -1
/// if no information is available.
-static std::optional<int> getLatency(const MachineInstr &MI, const MCSubtargetInfo *STI) {
+static std::optional<int> getLatency(const MachineInstr &MI,
+ const MCSubtargetInfo *STI) {
const MCSchedModel &SCModel = STI->getSchedModel();
const MachineFunction *MF = MI.getMF();
>From 5af5fafecc055d8e854de404a1209f9dcf3b4486 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Thu, 24 Oct 2024 16:00:37 -0700
Subject: [PATCH 06/11] make the two impls even closer to 'the same'
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 32 +++++++++---------
llvm/lib/MC/MCDisassembler/Disassembler.cpp | 37 ++++++++++++---------
2 files changed, 37 insertions(+), 32 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 28b6f0b59807ee..ce32c7f5af21fd 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1095,19 +1095,19 @@ void AsmPrinter::emitFunctionEntryLabel() {
/// scheduling model.
/// \return The maximum expected latency over all the operands or -1
/// if no information is available.
-static std::optional<int> getItineraryLatency(const MachineInstr &MI,
- const MachineFunction *MF,
- const MCSubtargetInfo *STI) {
- const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+static std::optional<int> getItineraryLatency(const MCSubtargetInfo *STI,
+ const MCInstrInfo *MCII,
+ const MachineInstr &MI) {
+ llvm::StringRef CPU = STI->getCPU();
// Check if we have a CPU to get the itinerary information.
- if (STI->getCPU().empty())
+ if (CPU.empty())
return std::nullopt;
// Get itinerary information.
- InstrItineraryData IID = STI->getInstrItineraryForCPU(STI->getCPU());
+ InstrItineraryData IID = STI->getInstrItineraryForCPU(CPU);
// Get the scheduling class of the requested instruction.
- const MCInstrDesc &Desc = TII->get(MI.getOpcode());
+ const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
unsigned SCClass = Desc.getSchedClass();
unsigned Latency = 0;
@@ -1122,23 +1122,20 @@ static std::optional<int> getItineraryLatency(const MachineInstr &MI,
/// Gets latency information for \p Inst.
/// \return The maximum expected latency over all the definitions or -1
/// if no information is available.
-static std::optional<int> getLatency(const MachineInstr &MI,
- const MCSubtargetInfo *STI) {
+static std::optional<int> getLatency(const MCSubtargetInfo *STI,
+ const MCInstrInfo *MCII,
+ const MachineInstr &MI) {
+ // Try to compute scheduling information.
const MCSchedModel &SCModel = STI->getSchedModel();
- const MachineFunction *MF = MI.getMF();
- if (!MF)
- return std::nullopt;
-
// Check if we have a scheduling model for instructions.
if (!SCModel.hasInstrSchedModel())
// Try to fall back to the itinerary model if the scheduling model doesn't
// have a scheduling table. Note the default does not have a table.
- return getItineraryLatency(MI, MF, STI);
+ return getItineraryLatency(STI, MCII, MI);
// Get the scheduling class of the requested instruction.
- const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
- const MCInstrDesc &Desc = TII->get(MI.getOpcode());
+ const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
unsigned SCClass = Desc.getSchedClass();
int Latency = SCModel.computeInstrLatency(*STI, SCClass);
if (Latency <= 0)
@@ -1178,7 +1175,8 @@ static void emitComments(const MachineInstr &MI, const MCSubtargetInfo *STI,
CommentOS << " Reload Reuse\n";
if (PrintLatency) {
- if (auto Latency = getLatency(MI, STI)) {
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+ if (auto Latency = getLatency(STI, TII, MI)) {
// Report only interesting latencies.
if (1 < *Latency)
CommentOS << " Latency: " << *Latency << "\n";
diff --git a/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index 69a5c9246c50d3..e70b7e9bea636f 100644
--- a/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -166,18 +166,19 @@ static void emitComments(LLVMDisasmContext *DC,
/// scheduling model, based on \p DC information.
/// \return The maximum expected latency over all the operands or -1
/// if no information is available.
-static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
- const int NoInformationAvailable = -1;
+static std::optional<int> getItineraryLatency(const MCSubtargetInfo *STI,
+ const MCInstrInfo *MCII,
+ const MCInst &Inst) {
+ llvm::StringRef CPU = STI->getCPU();
// Check if we have a CPU to get the itinerary information.
- if (DC->getCPU().empty())
- return NoInformationAvailable;
+ if (CPU.empty())
+ return std::nullopt;
// Get itinerary information.
- const MCSubtargetInfo *STI = DC->getSubtargetInfo();
- InstrItineraryData IID = STI->getInstrItineraryForCPU(DC->getCPU());
+ InstrItineraryData IID = STI->getInstrItineraryForCPU(CPU);
// Get the scheduling class of the requested instruction.
- const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ const MCInstrDesc& Desc = MCII->get(Inst.getOpcode());
unsigned SCClass = Desc.getSchedClass();
unsigned Latency = 0;
@@ -192,33 +193,39 @@ static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
/// Gets latency information for \p Inst, based on \p DC information.
/// \return The maximum expected latency over all the definitions or -1
/// if no information is available.
-static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
+static std::optional<int> getLatency(const MCSubtargetInfo *STI, const MCInstrInfo *MCII, const MCInst &Inst) {
// Try to compute scheduling information.
- const MCSubtargetInfo *STI = DC->getSubtargetInfo();
const MCSchedModel &SCModel = STI->getSchedModel();
// Check if we have a scheduling model for instructions.
if (!SCModel.hasInstrSchedModel())
// Try to fall back to the itinerary model if the scheduling model doesn't
// have a scheduling table. Note the default does not have a table.
- return getItineraryLatency(DC, Inst);
+ return getItineraryLatency(STI, MCII, Inst);
// Get the scheduling class of the requested instruction.
- const MCInstrDesc &Desc = DC->getInstrInfo()->get(Inst.getOpcode());
+ const MCInstrDesc &Desc = MCII->get(Inst.getOpcode());
unsigned SCClass = Desc.getSchedClass();
- return SCModel.computeInstrLatency(*STI, SCClass);
+ int Latency = SCModel.computeInstrLatency(*STI, SCClass);
+ if (Latency <= 0)
+ return std::nullopt;
+ return Latency;
}
/// Emits latency information in DC->CommentStream for \p Inst, based
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
- int Latency = getLatency(DC, Inst);
+ const MCSubtargetInfo *STI = DC->getSubtargetInfo();
+ const MCInstrInfo *MCII = DC->getInstrInfo();
+ std::optional<int> Latency = getLatency(STI, MCII, Inst);
+ if (!Latency)
+ return;
// Report only interesting latencies.
- if (Latency < 2)
+ if (*Latency < 2)
return;
- DC->CommentStream << "Latency: " << Latency << '\n';
+ DC->CommentStream << "Latency: " << *Latency << '\n';
}
//
>From 57503393f69b1c04516b3abc3bf55a447bbc7cb1 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Fri, 25 Oct 2024 09:54:15 -0700
Subject: [PATCH 07/11] move disassembler's latency calculation into MCSchedule
---
llvm/lib/MC/MCDisassembler/Disassembler.cpp | 59 ++-------------------
llvm/lib/MC/MCSchedule.cpp | 35 ++++++++++++
2 files changed, 39 insertions(+), 55 deletions(-)
diff --git a/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index e70b7e9bea636f..88a02f5492f6b8 100644
--- a/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -162,70 +162,19 @@ static void emitComments(LLVMDisasmContext *DC,
DC->CommentsToEmit.clear();
}
-/// Gets latency information for \p Inst from the itinerary
-/// scheduling model, based on \p DC information.
-/// \return The maximum expected latency over all the operands or -1
-/// if no information is available.
-static std::optional<int> getItineraryLatency(const MCSubtargetInfo *STI,
- const MCInstrInfo *MCII,
- const MCInst &Inst) {
- llvm::StringRef CPU = STI->getCPU();
-
- // Check if we have a CPU to get the itinerary information.
- if (CPU.empty())
- return std::nullopt;
-
- // Get itinerary information.
- InstrItineraryData IID = STI->getInstrItineraryForCPU(CPU);
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc& Desc = MCII->get(Inst.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
-
- unsigned Latency = 0;
-
- for (unsigned Idx = 0, IdxEnd = Inst.getNumOperands(); Idx != IdxEnd; ++Idx)
- if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
- Latency = std::max(Latency, *OperCycle);
-
- return int(Latency);
-}
-
-/// Gets latency information for \p Inst, based on \p DC information.
-/// \return The maximum expected latency over all the definitions or -1
-/// if no information is available.
-static std::optional<int> getLatency(const MCSubtargetInfo *STI, const MCInstrInfo *MCII, const MCInst &Inst) {
- // Try to compute scheduling information.
- const MCSchedModel &SCModel = STI->getSchedModel();
-
- // Check if we have a scheduling model for instructions.
- if (!SCModel.hasInstrSchedModel())
- // Try to fall back to the itinerary model if the scheduling model doesn't
- // have a scheduling table. Note the default does not have a table.
- return getItineraryLatency(STI, MCII, Inst);
-
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc &Desc = MCII->get(Inst.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
- int Latency = SCModel.computeInstrLatency(*STI, SCClass);
- if (Latency <= 0)
- return std::nullopt;
- return Latency;
-}
-
/// Emits latency information in DC->CommentStream for \p Inst, based
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
const MCSubtargetInfo *STI = DC->getSubtargetInfo();
const MCInstrInfo *MCII = DC->getInstrInfo();
- std::optional<int> Latency = getLatency(STI, MCII, Inst);
- if (!Latency)
- return;
+ const MCSchedModel &SCModel = STI->getSchedModel();
+ int Latency = SCModel.computeInstrLatency(*STI, *MCII, Inst);
// Report only interesting latencies.
- if (*Latency < 2)
+ if (Latency < 2)
return;
- DC->CommentStream << "Latency: " << *Latency << '\n';
+ DC->CommentStream << "Latency: " << Latency << '\n';
}
//
diff --git a/llvm/lib/MC/MCSchedule.cpp b/llvm/lib/MC/MCSchedule.cpp
index 4f7125864c5a01..c0e0fa49eccad9 100644
--- a/llvm/lib/MC/MCSchedule.cpp
+++ b/llvm/lib/MC/MCSchedule.cpp
@@ -66,9 +66,44 @@ int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
llvm_unreachable("unsupported variant scheduling class");
}
+/// Gets latency information for \p Inst from the itinerary
+/// scheduling model.
+/// \return The maximum expected latency over all the operands or -1
+/// if no information is available.
+static int getItineraryLatency(const MCSubtargetInfo &STI,
+ const MCInstrInfo &MCII, const MCInst &Inst) {
+ static const int NoInformationAvailable = -1;
+
+ llvm::StringRef CPU = STI.getCPU();
+
+ // Check if we have a CPU to get the itinerary information.
+ if (CPU.empty())
+ return NoInformationAvailable;
+
+ // Get itinerary information.
+ InstrItineraryData IID = STI.getInstrItineraryForCPU(CPU);
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc &Desc = MCII.get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+
+ unsigned Latency = 0;
+
+ for (unsigned Idx = 0, IdxEnd = Inst.getNumOperands(); Idx != IdxEnd; ++Idx)
+ if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
+ Latency = std::max(Latency, *OperCycle);
+
+ return int(Latency);
+}
+
int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
const MCInstrInfo &MCII,
const MCInst &Inst) const {
+ // Check if we have a scheduling model for instructions.
+ if (!hasInstrSchedModel())
+ // Try to fall back to the itinerary model if the scheduling model doesn't
+ // have a scheduling table. Note the default does not have a table.
+ return getItineraryLatency(STI, MCII, Inst);
+
unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
if (!SCDesc->isValid())
>From 5f3369eeea14aa3bc4e7f66da5cf042c0f511a43 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Fri, 25 Oct 2024 11:02:30 -0700
Subject: [PATCH 08/11] unify getLatency between Disassembler / AsmPrinter
---
llvm/include/llvm/MC/MCSchedule.h | 72 +++++++++++++++++++++-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 65 +++----------------
llvm/lib/MC/MCSchedule.cpp | 53 +---------------
3 files changed, 81 insertions(+), 109 deletions(-)
diff --git a/llvm/include/llvm/MC/MCSchedule.h b/llvm/include/llvm/MC/MCSchedule.h
index 5a6471ac1c892a..6adb83a0ecda93 100644
--- a/llvm/include/llvm/MC/MCSchedule.h
+++ b/llvm/include/llvm/MC/MCSchedule.h
@@ -14,9 +14,11 @@
#ifndef LLVM_MC_MCSCHEDULE_H
#define LLVM_MC_MCSCHEDULE_H
-#include "llvm/Config/llvm-config.h"
-#include "llvm/Support/DataTypes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCInstrDesc.h"
+#include "llvm/Support/ErrorHandling.h"
#include <cassert>
+#include <optional>
namespace llvm {
@@ -25,6 +27,7 @@ struct InstrItinerary;
class MCSubtargetInfo;
class MCInstrInfo;
class MCInst;
+class MCInstrDesc;
class InstrItineraryData;
/// Define a kind of processor resource that will be modeled by the scheduler.
@@ -369,9 +372,15 @@ struct MCSchedModel {
const MCSchedClassDesc &SCDesc);
int computeInstrLatency(const MCSubtargetInfo &STI, unsigned SClass) const;
+
int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
const MCInst &Inst) const;
+ template <typename MCSubtargetInfo, typename MCInstrInfo,
+ typename InstrItineraryData, typename MCInstOrMachineInstr>
+ int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
+ const MCInstOrMachineInstr &Inst) const;
+
// Returns the reciprocal throughput information from a MCSchedClassDesc.
static double
getReciprocalThroughput(const MCSubtargetInfo &STI,
@@ -393,6 +402,65 @@ struct MCSchedModel {
static const MCSchedModel Default;
};
+// The first three are only template'd arguments so we can get away with leaving
+// them as incomplete types below. The third is a template over
+// MCInst/MachineInstr so as to avoid a layering violation here that would make
+// the MC layer depend on CodeGen.
+template <typename MCSubtargetInfo, typename MCInstrInfo,
+ typename InstrItineraryData, typename MCInstOrMachineInstr>
+int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
+ const MCInstrInfo &MCII,
+ const MCInstOrMachineInstr &Inst) const {
+ static const int NoInformationAvailable = -1;
+ // Check if we have a scheduling model for instructions.
+ if (!hasInstrSchedModel()) {
+ // Try to fall back to the itinerary model if the scheduling model doesn't
+ // have a scheduling table. Note the default does not have a table.
+
+ llvm::StringRef CPU = STI.getCPU();
+
+ // Check if we have a CPU to get the itinerary information.
+ if (CPU.empty())
+ return NoInformationAvailable;
+
+ // Get itinerary information.
+ InstrItineraryData IID = STI.getInstrItineraryForCPU(CPU);
+ // Get the scheduling class of the requested instruction.
+ const MCInstrDesc &Desc = MCII.get(Inst.getOpcode());
+ unsigned SCClass = Desc.getSchedClass();
+
+ unsigned Latency = 0;
+
+ for (unsigned Idx = 0, IdxEnd = Inst.getNumOperands(); Idx != IdxEnd; ++Idx)
+ if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
+ Latency = std::max(Latency, *OperCycle);
+
+ return int(Latency);
+ }
+
+ unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
+ const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
+ if (!SCDesc->isValid())
+ return 0;
+
+ if constexpr (std::is_same_v<MCInstOrMachineInstr, MCInst>) {
+ unsigned CPUID = getProcessorID();
+ while (SCDesc->isVariant()) {
+ SchedClass =
+ STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
+ SCDesc = getSchedClassDesc(SchedClass);
+ }
+
+ if (SchedClass)
+ return MCSchedModel::computeInstrLatency(STI, *SCDesc);
+
+ llvm_unreachable("unsupported variant scheduling class");
+ } else if (SchedClass)
+ return MCSchedModel::computeInstrLatency(STI, SchedClass);
+
+ return NoInformationAvailable;
+}
+
} // namespace llvm
#endif
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index ce32c7f5af21fd..84f58b576e0fd3 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -91,6 +91,7 @@
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
@@ -1091,58 +1092,6 @@ void AsmPrinter::emitFunctionEntryLabel() {
}
}
-/// Gets latency information for \p Inst from the itinerary
-/// scheduling model.
-/// \return The maximum expected latency over all the operands or -1
-/// if no information is available.
-static std::optional<int> getItineraryLatency(const MCSubtargetInfo *STI,
- const MCInstrInfo *MCII,
- const MachineInstr &MI) {
- llvm::StringRef CPU = STI->getCPU();
-
- // Check if we have a CPU to get the itinerary information.
- if (CPU.empty())
- return std::nullopt;
-
- // Get itinerary information.
- InstrItineraryData IID = STI->getInstrItineraryForCPU(CPU);
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
-
- unsigned Latency = 0;
-
- for (unsigned Idx = 0, IdxEnd = MI.getNumOperands(); Idx != IdxEnd; ++Idx)
- if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
- Latency = std::max(Latency, *OperCycle);
-
- return int(Latency);
-}
-
-/// Gets latency information for \p Inst.
-/// \return The maximum expected latency over all the definitions or -1
-/// if no information is available.
-static std::optional<int> getLatency(const MCSubtargetInfo *STI,
- const MCInstrInfo *MCII,
- const MachineInstr &MI) {
- // Try to compute scheduling information.
- const MCSchedModel &SCModel = STI->getSchedModel();
-
- // Check if we have a scheduling model for instructions.
- if (!SCModel.hasInstrSchedModel())
- // Try to fall back to the itinerary model if the scheduling model doesn't
- // have a scheduling table. Note the default does not have a table.
- return getItineraryLatency(STI, MCII, MI);
-
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
- int Latency = SCModel.computeInstrLatency(*STI, SCClass);
- if (Latency <= 0)
- return std::nullopt;
- return Latency;
-}
-
/// emitComments - Pretty-print comments for instructions.
static void emitComments(const MachineInstr &MI, const MCSubtargetInfo *STI,
raw_ostream &CommentOS) {
@@ -1176,11 +1125,13 @@ static void emitComments(const MachineInstr &MI, const MCSubtargetInfo *STI,
if (PrintLatency) {
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
- if (auto Latency = getLatency(STI, TII, MI)) {
- // Report only interesting latencies.
- if (1 < *Latency)
- CommentOS << " Latency: " << *Latency << "\n";
- }
+ const MCSchedModel &SCModel = STI->getSchedModel();
+ int Latency = SCModel.computeInstrLatency<MCSubtargetInfo, MCInstrInfo,
+ InstrItineraryData, MachineInstr>(
+ *STI, *TII, MI);
+ // Report only interesting latencies.
+ if (1 < Latency)
+ CommentOS << " Latency: " << Latency << "\n";
}
}
diff --git a/llvm/lib/MC/MCSchedule.cpp b/llvm/lib/MC/MCSchedule.cpp
index c0e0fa49eccad9..acc0711a0652e4 100644
--- a/llvm/lib/MC/MCSchedule.cpp
+++ b/llvm/lib/MC/MCSchedule.cpp
@@ -66,59 +66,12 @@ int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
llvm_unreachable("unsupported variant scheduling class");
}
-/// Gets latency information for \p Inst from the itinerary
-/// scheduling model.
-/// \return The maximum expected latency over all the operands or -1
-/// if no information is available.
-static int getItineraryLatency(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII, const MCInst &Inst) {
- static const int NoInformationAvailable = -1;
-
- llvm::StringRef CPU = STI.getCPU();
-
- // Check if we have a CPU to get the itinerary information.
- if (CPU.empty())
- return NoInformationAvailable;
-
- // Get itinerary information.
- InstrItineraryData IID = STI.getInstrItineraryForCPU(CPU);
- // Get the scheduling class of the requested instruction.
- const MCInstrDesc &Desc = MCII.get(Inst.getOpcode());
- unsigned SCClass = Desc.getSchedClass();
-
- unsigned Latency = 0;
-
- for (unsigned Idx = 0, IdxEnd = Inst.getNumOperands(); Idx != IdxEnd; ++Idx)
- if (std::optional<unsigned> OperCycle = IID.getOperandCycle(SCClass, Idx))
- Latency = std::max(Latency, *OperCycle);
-
- return int(Latency);
-}
-
int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
const MCInstrInfo &MCII,
const MCInst &Inst) const {
- // Check if we have a scheduling model for instructions.
- if (!hasInstrSchedModel())
- // Try to fall back to the itinerary model if the scheduling model doesn't
- // have a scheduling table. Note the default does not have a table.
- return getItineraryLatency(STI, MCII, Inst);
-
- unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
- const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
- if (!SCDesc->isValid())
- return 0;
-
- unsigned CPUID = getProcessorID();
- while (SCDesc->isVariant()) {
- SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
- SCDesc = getSchedClassDesc(SchedClass);
- }
-
- if (SchedClass)
- return MCSchedModel::computeInstrLatency(STI, *SCDesc);
-
- llvm_unreachable("unsupported variant scheduling class");
+ return MCSchedModel::computeInstrLatency<MCSubtargetInfo, MCInstrInfo,
+ InstrItineraryData, MCInst>(
+ STI, MCII, Inst);
}
double
>From 8d2c37d8d2197d38038b595e68158e52547dbdfd Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sat, 26 Oct 2024 08:20:17 -0700
Subject: [PATCH 09/11] clang-format
---
llvm/lib/MC/MCDisassembler/Disassembler.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index 88a02f5492f6b8..f0c138513a033b 100644
--- a/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -166,7 +166,7 @@ static void emitComments(LLVMDisasmContext *DC,
/// on the information available in \p DC.
static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) {
const MCSubtargetInfo *STI = DC->getSubtargetInfo();
- const MCInstrInfo *MCII = DC->getInstrInfo();
+ const MCInstrInfo *MCII = DC->getInstrInfo();
const MCSchedModel &SCModel = STI->getSchedModel();
int Latency = SCModel.computeInstrLatency(*STI, *MCII, Inst);
>From 4482142e1889236a0b98c6625db88fb2b1220ac4 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sat, 26 Oct 2024 08:57:39 -0700
Subject: [PATCH 10/11] move variant sched class resolution into callback, per
quentin's idea
---
llvm/include/llvm/MC/MCSchedule.h | 37 +++++++++++++------------------
llvm/lib/MC/MCSchedule.cpp | 21 +++++++++++++++++-
2 files changed, 35 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/MC/MCSchedule.h b/llvm/include/llvm/MC/MCSchedule.h
index 6adb83a0ecda93..fe731d086f70ae 100644
--- a/llvm/include/llvm/MC/MCSchedule.h
+++ b/llvm/include/llvm/MC/MCSchedule.h
@@ -378,8 +378,12 @@ struct MCSchedModel {
template <typename MCSubtargetInfo, typename MCInstrInfo,
typename InstrItineraryData, typename MCInstOrMachineInstr>
- int computeInstrLatency(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
- const MCInstOrMachineInstr &Inst) const;
+ int computeInstrLatency(
+ const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
+ const MCInstOrMachineInstr &Inst,
+ llvm::function_ref<const MCSchedClassDesc *(const MCSchedClassDesc *)>
+ ResolveVariantSchedClass =
+ [](const MCSchedClassDesc *SCDesc) { return SCDesc; }) const;
// Returns the reciprocal throughput information from a MCSchedClassDesc.
static double
@@ -408,9 +412,11 @@ struct MCSchedModel {
// the MC layer depend on CodeGen.
template <typename MCSubtargetInfo, typename MCInstrInfo,
typename InstrItineraryData, typename MCInstOrMachineInstr>
-int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII,
- const MCInstOrMachineInstr &Inst) const {
+int MCSchedModel::computeInstrLatency(
+ const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
+ const MCInstOrMachineInstr &Inst,
+ llvm::function_ref<const MCSchedClassDesc *(const MCSchedClassDesc *)>
+ ResolveVariantSchedClass) const {
static const int NoInformationAvailable = -1;
// Check if we have a scheduling model for instructions.
if (!hasInstrSchedModel()) {
@@ -440,25 +446,12 @@ int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
- if (!SCDesc->isValid())
- return 0;
-
- if constexpr (std::is_same_v<MCInstOrMachineInstr, MCInst>) {
- unsigned CPUID = getProcessorID();
- while (SCDesc->isVariant()) {
- SchedClass =
- STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
- SCDesc = getSchedClassDesc(SchedClass);
- }
-
- if (SchedClass)
- return MCSchedModel::computeInstrLatency(STI, *SCDesc);
+ SCDesc = ResolveVariantSchedClass(SCDesc);
- llvm_unreachable("unsupported variant scheduling class");
- } else if (SchedClass)
- return MCSchedModel::computeInstrLatency(STI, SchedClass);
+ if (!SCDesc || !SCDesc->isValid())
+ return NoInformationAvailable;
- return NoInformationAvailable;
+ return MCSchedModel::computeInstrLatency(STI, *SCDesc);
}
} // namespace llvm
diff --git a/llvm/lib/MC/MCSchedule.cpp b/llvm/lib/MC/MCSchedule.cpp
index acc0711a0652e4..ed243cecabb763 100644
--- a/llvm/lib/MC/MCSchedule.cpp
+++ b/llvm/lib/MC/MCSchedule.cpp
@@ -71,7 +71,26 @@ int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
const MCInst &Inst) const {
return MCSchedModel::computeInstrLatency<MCSubtargetInfo, MCInstrInfo,
InstrItineraryData, MCInst>(
- STI, MCII, Inst);
+ STI, MCII, Inst,
+ [&](const MCSchedClassDesc *SCDesc) -> const MCSchedClassDesc * {
+ if (!SCDesc->isValid())
+ return nullptr;
+
+ unsigned CPUID = getProcessorID();
+ unsigned SchedClass = 0;
+ while (SCDesc->isVariant()) {
+ SchedClass =
+ STI.resolveVariantSchedClass(SchedClass, &Inst, &MCII, CPUID);
+ SCDesc = getSchedClassDesc(SchedClass);
+ }
+
+ if (!SchedClass) {
+ assert(false && "unsupported variant scheduling class");
+ return nullptr;
+ }
+
+ return SCDesc;
+ });
}
double
>From bd1e4e889f70cf5c7d77cafabc1cb538ececaf7b Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sat, 26 Oct 2024 09:00:39 -0700
Subject: [PATCH 11/11] cl::desc's shouldn't have full stops
---
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 84f58b576e0fd3..5c3ae5bf7f89ce 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -171,7 +171,7 @@ static cl::opt<bool> EmitJumpTableSizesSection(
// not completely accurate, and we don't want to be misleading.
static cl::opt<bool> PrintLatency(
"asm-print-latency",
- cl::desc("Print instruction latencies as verbose asm comments."),
+ cl::desc("Print instruction latencies as verbose asm comments"),
cl::Hidden, cl::init(false));
STATISTIC(EmittedInsts, "Number of machine instrs printed");
More information about the llvm-commits
mailing list