[llvm] e02920f - [llvm-mca][NFC] Refactor handling of views that examine individual instructions,
Wolfgang Pieb via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 12:12:58 PDT 2020
Author: Wolfgang Pieb
Date: 2020-08-25T12:12:37-07:00
New Revision: e02920fe55761aaa06b33caec381bc2a1c36ad1c
URL: https://github.com/llvm/llvm-project/commit/e02920fe55761aaa06b33caec381bc2a1c36ad1c
DIFF: https://github.com/llvm/llvm-project/commit/e02920fe55761aaa06b33caec381bc2a1c36ad1c.diff
LOG: [llvm-mca][NFC] Refactor handling of views that examine individual instructions,
including printing them.
Reviewers: andreadb, lebedev.ri
Differential Review: https://reviews.llvm.org/D86390
Introduces a new base class "InstructionView" that such views derive from.
Other views still use the "View" base class.
Added:
Modified:
llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
llvm/tools/llvm-mca/Views/InstructionInfoView.h
llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
llvm/tools/llvm-mca/Views/ResourcePressureView.h
llvm/tools/llvm-mca/Views/TimelineView.cpp
llvm/tools/llvm-mca/Views/TimelineView.h
llvm/tools/llvm-mca/Views/View.cpp
llvm/tools/llvm-mca/Views/View.h
Removed:
################################################################################
diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
index 99deed6eae97..519b928fda5d 100644
--- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
+++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
@@ -16,7 +16,6 @@
#include "llvm/MC/MCInst.h"
#include "llvm/MCA/Support.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/FormattedStream.h"
namespace llvm {
namespace mca {
@@ -284,21 +283,14 @@ void DependencyGraph::getCriticalSequence(
}
}
-static void printInstruction(formatted_raw_ostream &FOS,
- const MCSubtargetInfo &STI, MCInstPrinter &MCIP,
- const MCInst &MCI,
- bool UseDifferentColor = false) {
- std::string Instruction;
- raw_string_ostream InstrStream(Instruction);
-
+void BottleneckAnalysis::printInstruction(formatted_raw_ostream &FOS,
+ const MCInst &MCI,
+ bool UseDifferentColor) const {
FOS.PadToColumn(14);
- MCIP.printInst(&MCI, 0, "", STI, InstrStream);
- InstrStream.flush();
-
if (UseDifferentColor)
FOS.changeColor(raw_ostream::CYAN, true, false);
- FOS << StringRef(Instruction).ltrim();
+ FOS << printInstructionString(MCI);
if (UseDifferentColor)
FOS.resetColor();
}
@@ -316,6 +308,7 @@ void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const {
OS << "\nCritical sequence based on the simulation:\n\n";
const DependencyEdge &FirstEdge = *Seq[0];
+ ArrayRef<llvm::MCInst> Source = getSource();
unsigned FromIID = FirstEdge.FromIID % Source.size();
unsigned ToIID = FirstEdge.ToIID % Source.size();
bool IsLoopCarried = FromIID >= ToIID;
@@ -331,17 +324,17 @@ void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const {
unsigned CurrentIID = 0;
if (IsLoopCarried) {
FOS << "\n +----< " << FromIID << ".";
- printInstruction(FOS, STI, MCIP, Source[FromIID], HasColors);
+ printInstruction(FOS, Source[FromIID], HasColors);
FOS << "\n |\n | < loop carried > \n |";
} else {
while (CurrentIID < FromIID) {
FOS << "\n " << CurrentIID << ".";
- printInstruction(FOS, STI, MCIP, Source[CurrentIID]);
+ printInstruction(FOS, Source[CurrentIID]);
CurrentIID++;
}
FOS << "\n +----< " << CurrentIID << ".";
- printInstruction(FOS, STI, MCIP, Source[CurrentIID], HasColors);
+ printInstruction(FOS, Source[CurrentIID], HasColors);
CurrentIID++;
}
@@ -351,17 +344,17 @@ void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const {
while (CurrentIID < LastIID) {
FOS << "\n | " << CurrentIID << ".";
- printInstruction(FOS, STI, MCIP, Source[CurrentIID]);
+ printInstruction(FOS, Source[CurrentIID]);
CurrentIID++;
}
if (CurrentIID == ToIID) {
FOS << "\n +----> " << ToIID << ".";
- printInstruction(FOS, STI, MCIP, Source[CurrentIID], HasColors);
+ printInstruction(FOS, Source[CurrentIID], HasColors);
} else {
FOS << "\n |\n | < loop carried > \n |"
<< "\n +----> " << ToIID << ".";
- printInstruction(FOS, STI, MCIP, Source[ToIID], HasColors);
+ printInstruction(FOS, Source[ToIID], HasColors);
}
FOS.PadToColumn(58);
@@ -373,7 +366,7 @@ void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const {
FOS << "## REGISTER dependency: ";
if (HasColors)
FOS.changeColor(raw_ostream::MAGENTA, true, false);
- MCIP.printRegName(FOS, Dep.ResourceOrRegID);
+ getInstPrinter().printRegName(FOS, Dep.ResourceOrRegID);
} else if (Dep.Type == DependencyEdge::DT_MEMORY) {
FOS << "## MEMORY dependency.";
} else {
@@ -397,7 +390,7 @@ void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const {
while (CurrentIID < Source.size()) {
FOS << "\n " << CurrentIID << ".";
- printInstruction(FOS, STI, MCIP, Source[CurrentIID]);
+ printInstruction(FOS, Source[CurrentIID]);
CurrentIID++;
}
@@ -451,8 +444,8 @@ void DependencyGraph::addDependency(unsigned From, unsigned To,
BottleneckAnalysis::BottleneckAnalysis(const MCSubtargetInfo &sti,
MCInstPrinter &Printer,
ArrayRef<MCInst> S, unsigned NumIter)
- : STI(sti), MCIP(Printer), Tracker(STI.getSchedModel()), DG(S.size() * 3),
- Source(S), Iterations(NumIter), TotalCycles(0),
+ : InstructionView(sti, Printer, S), Tracker(sti.getSchedModel()),
+ DG(S.size() * 3), Iterations(NumIter), TotalCycles(0),
PressureIncreasedBecauseOfResources(false),
PressureIncreasedBecauseOfRegisterDependencies(false),
PressureIncreasedBecauseOfMemoryDependencies(false),
@@ -461,7 +454,7 @@ BottleneckAnalysis::BottleneckAnalysis(const MCSubtargetInfo &sti,
void BottleneckAnalysis::addRegisterDep(unsigned From, unsigned To,
unsigned RegID, unsigned Cost) {
bool IsLoopCarried = From >= To;
- unsigned SourceSize = Source.size();
+ unsigned SourceSize = getSource().size();
if (IsLoopCarried) {
DG.addRegisterDep(From, To + SourceSize, RegID, Cost);
DG.addRegisterDep(From + SourceSize, To + (SourceSize * 2), RegID, Cost);
@@ -473,7 +466,7 @@ void BottleneckAnalysis::addRegisterDep(unsigned From, unsigned To,
void BottleneckAnalysis::addMemoryDep(unsigned From, unsigned To,
unsigned Cost) {
bool IsLoopCarried = From >= To;
- unsigned SourceSize = Source.size();
+ unsigned SourceSize = getSource().size();
if (IsLoopCarried) {
DG.addMemoryDep(From, To + SourceSize, Cost);
DG.addMemoryDep(From + SourceSize, To + (SourceSize * 2), Cost);
@@ -485,7 +478,7 @@ void BottleneckAnalysis::addMemoryDep(unsigned From, unsigned To,
void BottleneckAnalysis::addResourceDep(unsigned From, unsigned To,
uint64_t Mask, unsigned Cost) {
bool IsLoopCarried = From >= To;
- unsigned SourceSize = Source.size();
+ unsigned SourceSize = getSource().size();
if (IsLoopCarried) {
DG.addResourceDep(From, To + SourceSize, Mask, Cost);
DG.addResourceDep(From + SourceSize, To + (SourceSize * 2), Mask, Cost);
@@ -508,6 +501,7 @@ void BottleneckAnalysis::onEvent(const HWInstructionEvent &Event) {
if (Event.Type != HWInstructionEvent::Issued)
return;
+ ArrayRef<llvm::MCInst> Source = getSource();
const Instruction &IS = *Event.IR.getInstruction();
unsigned To = IID % Source.size();
@@ -617,7 +611,7 @@ void BottleneckAnalysis::printBottleneckHints(raw_ostream &OS) const {
if (BPI.PressureIncreaseCycles) {
ArrayRef<unsigned> Distribution = Tracker.getResourcePressureDistribution();
- const MCSchedModel &SM = STI.getSchedModel();
+ const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
for (unsigned I = 0, E = Distribution.size(); I < E; ++I) {
unsigned ResourceCycles = Distribution[I];
if (ResourceCycles) {
diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
index 9e3bd5978f09..a0aad9faff40 100644
--- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
+++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
@@ -87,6 +87,7 @@
#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FormattedStream.h"
namespace llvm {
namespace mca {
@@ -282,13 +283,10 @@ class DependencyGraph {
};
/// A view that collects and prints a few performance numbers.
-class BottleneckAnalysis : public View {
- const MCSubtargetInfo &STI;
- MCInstPrinter &MCIP;
+class BottleneckAnalysis : public InstructionView {
PressureTracker Tracker;
DependencyGraph DG;
- ArrayRef<MCInst> Source;
unsigned Iterations;
unsigned TotalCycles;
@@ -317,6 +315,9 @@ class BottleneckAnalysis : public View {
void addMemoryDep(unsigned From, unsigned To, unsigned Cy);
void addResourceDep(unsigned From, unsigned To, uint64_t Mask, unsigned Cy);
+ void printInstruction(formatted_raw_ostream &FOS, const MCInst &MCI,
+ bool UseDifferentColor = false) const;
+
// Prints a bottleneck message to OS.
void printBottleneckHints(raw_ostream &OS) const;
void printCriticalSequence(raw_ostream &OS) const;
diff --git a/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp b/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
index 548f0b36d055..da53f16a9913 100644
--- a/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
+++ b/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
@@ -20,9 +20,8 @@ namespace mca {
void InstructionInfoView::printView(raw_ostream &OS) const {
std::string Buffer;
raw_string_ostream TempStream(Buffer);
- std::string Instruction;
- raw_string_ostream InstrStream(Instruction);
+ ArrayRef<llvm::MCInst> Source = getSource();
if (!Source.size())
return;
@@ -82,14 +81,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
}
const MCInst &Inst = std::get<1>(I.value());
- MCIP.printInst(&Inst, 0, "", STI, InstrStream);
- InstrStream.flush();
-
- // Consume any tabs or spaces at the beginning of the string.
- StringRef Str(Instruction);
- Str = Str.ltrim();
- TempStream << Str << '\n';
- Instruction = "";
+ TempStream << printInstructionString(Inst) << '\n';
}
TempStream.flush();
@@ -98,8 +90,9 @@ void InstructionInfoView::printView(raw_ostream &OS) const {
void InstructionInfoView::collectData(
MutableArrayRef<InstructionInfoViewData> IIVD) const {
+ const llvm::MCSubtargetInfo &STI = getSubTargetInfo();
const MCSchedModel &SM = STI.getSchedModel();
- for (auto I : zip(Source, IIVD)) {
+ for (auto I : zip(getSource(), IIVD)) {
const MCInst &Inst = std::get<0>(I);
InstructionInfoViewData &IIVDEntry = std::get<1>(I);
const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode());
diff --git a/llvm/tools/llvm-mca/Views/InstructionInfoView.h b/llvm/tools/llvm-mca/Views/InstructionInfoView.h
index aca7e5894a89..c2093b2d0429 100644
--- a/llvm/tools/llvm-mca/Views/InstructionInfoView.h
+++ b/llvm/tools/llvm-mca/Views/InstructionInfoView.h
@@ -50,13 +50,10 @@ namespace llvm {
namespace mca {
/// A view that prints out generic instruction information.
-class InstructionInfoView : public View {
- const llvm::MCSubtargetInfo &STI;
+class InstructionInfoView : public InstructionView {
const llvm::MCInstrInfo &MCII;
CodeEmitter &CE;
bool PrintEncodings;
- llvm::ArrayRef<llvm::MCInst> Source;
- llvm::MCInstPrinter &MCIP;
struct InstructionInfoViewData {
unsigned NumMicroOpcodes = 0;
@@ -76,8 +73,8 @@ class InstructionInfoView : public View {
const llvm::MCInstrInfo &II, CodeEmitter &C,
bool ShouldPrintEncodings, llvm::ArrayRef<llvm::MCInst> S,
llvm::MCInstPrinter &IP)
- : STI(ST), MCII(II), CE(C), PrintEncodings(ShouldPrintEncodings),
- Source(S), MCIP(IP) {}
+ : InstructionView(ST, IP, S), MCII(II), CE(C),
+ PrintEncodings(ShouldPrintEncodings) {}
void printView(llvm::raw_ostream &OS) const override;
};
diff --git a/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp b/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
index bdb9dc21247b..a5a74210c672 100644
--- a/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
+++ b/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
@@ -21,10 +21,10 @@ namespace mca {
ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
MCInstPrinter &Printer,
ArrayRef<MCInst> S)
- : STI(sti), MCIP(Printer), Source(S), LastInstructionIdx(0) {
+ : InstructionView(sti, Printer, S), LastInstructionIdx(0) {
// Populate the map of resource descriptors.
unsigned R2VIndex = 0;
- const MCSchedModel &SM = STI.getSchedModel();
+ const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
unsigned NumUnits = ProcResource.NumUnits;
@@ -37,7 +37,7 @@ ResourcePressureView::ResourcePressureView(const llvm::MCSubtargetInfo &sti,
}
NumResourceUnits = R2VIndex;
- ResourceUsage.resize(NumResourceUnits * (Source.size() + 1));
+ ResourceUsage.resize(NumResourceUnits * (getSource().size() + 1));
std::fill(ResourceUsage.begin(), ResourceUsage.end(), 0.0);
}
@@ -52,6 +52,7 @@ void ResourcePressureView::onEvent(const HWInstructionEvent &Event) {
return;
const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
+ ArrayRef<llvm::MCInst> Source = getSource();
const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
for (const std::pair<ResourceRef, ResourceCycles> &Use :
IssueEvent.UsedResources) {
@@ -105,7 +106,7 @@ void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const {
formatted_raw_ostream FOS(TempStream);
FOS << "\n\nResources:\n";
- const MCSchedModel &SM = STI.getSchedModel();
+ const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
for (unsigned I = 1, ResourceIndex = 0, E = SM.getNumProcResourceKinds();
I < E; ++I) {
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
@@ -132,6 +133,7 @@ void ResourcePressureView::printResourcePressurePerIter(raw_ostream &OS) const {
FOS << '\n';
FOS.flush();
+ ArrayRef<llvm::MCInst> Source = getSource();
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
for (unsigned I = 0, E = NumResourceUnits; I < E; ++I) {
double Usage = ResourceUsage[I + Source.size() * E];
@@ -148,13 +150,11 @@ void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
formatted_raw_ostream FOS(TempStream);
FOS << "\n\nResource pressure by instruction:\n";
- printColumnNames(FOS, STI.getSchedModel());
+ printColumnNames(FOS, getSubTargetInfo().getSchedModel());
FOS << "Instructions:\n";
- std::string Instruction;
- raw_string_ostream InstrStream(Instruction);
-
unsigned InstrIndex = 0;
+ ArrayRef<llvm::MCInst> Source = getSource();
const unsigned Executions = LastInstructionIdx / Source.size() + 1;
for (const MCInst &MCI : Source) {
unsigned BaseEltIdx = InstrIndex * NumResourceUnits;
@@ -163,16 +163,7 @@ void ResourcePressureView::printResourcePressurePerInst(raw_ostream &OS) const {
printResourcePressure(FOS, Usage / Executions, (J + 1) * 7);
}
- MCIP.printInst(&MCI, 0, "", STI, InstrStream);
- InstrStream.flush();
- StringRef Str(Instruction);
-
- // Remove any tabs or spaces at the beginning of the instruction.
- Str = Str.ltrim();
-
- FOS << Str << '\n';
- Instruction = "";
-
+ FOS << printInstructionString(MCI) << '\n';
FOS.flush();
OS << Buffer;
Buffer = "";
diff --git a/llvm/tools/llvm-mca/Views/ResourcePressureView.h b/llvm/tools/llvm-mca/Views/ResourcePressureView.h
index 0fa0b9a36aa3..39914f9e2f27 100644
--- a/llvm/tools/llvm-mca/Views/ResourcePressureView.h
+++ b/llvm/tools/llvm-mca/Views/ResourcePressureView.h
@@ -69,10 +69,7 @@ namespace mca {
/// This class collects resource pressure statistics and it is able to print
/// out all the collected information as a table to an output stream.
-class ResourcePressureView : public View {
- const llvm::MCSubtargetInfo &STI;
- llvm::MCInstPrinter &MCIP;
- llvm::ArrayRef<llvm::MCInst> Source;
+class ResourcePressureView : public InstructionView {
unsigned LastInstructionIdx;
// Map to quickly obtain the ResourceUsage column index from a processor
diff --git a/llvm/tools/llvm-mca/Views/TimelineView.cpp b/llvm/tools/llvm-mca/Views/TimelineView.cpp
index cf5b48e811b8..f520c5c31d3f 100644
--- a/llvm/tools/llvm-mca/Views/TimelineView.cpp
+++ b/llvm/tools/llvm-mca/Views/TimelineView.cpp
@@ -20,10 +20,10 @@ namespace mca {
TimelineView::TimelineView(const MCSubtargetInfo &sti, MCInstPrinter &Printer,
llvm::ArrayRef<llvm::MCInst> S, unsigned Iterations,
unsigned Cycles)
- : STI(sti), MCIP(Printer), Source(S), CurrentCycle(0),
+ : InstructionView(sti, Printer, S), CurrentCycle(0),
MaxCycle(Cycles == 0 ? 80 : Cycles), LastCycle(0), WaitTime(S.size()),
UsedBuffer(S.size()) {
- unsigned NumInstructions = Source.size();
+ unsigned NumInstructions = getSource().size();
assert(Iterations && "Invalid number of iterations specified!");
NumInstructions *= Iterations;
Timeline.resize(NumInstructions);
@@ -40,10 +40,10 @@ TimelineView::TimelineView(const MCSubtargetInfo &sti, MCInstPrinter &Printer,
void TimelineView::onReservedBuffers(const InstRef &IR,
ArrayRef<unsigned> Buffers) {
- if (IR.getSourceIndex() >= Source.size())
+ if (IR.getSourceIndex() >= getSource().size())
return;
- const MCSchedModel &SM = STI.getSchedModel();
+ const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
std::pair<unsigned, int> BufferInfo = {0, -1};
for (const unsigned Buffer : Buffers) {
const MCProcResourceDesc &MCDesc = *SM.getProcResource(Buffer);
@@ -70,7 +70,7 @@ void TimelineView::onEvent(const HWInstructionEvent &Event) {
// Update the WaitTime entry which corresponds to this Index.
assert(TVEntry.CycleDispatched >= 0 && "Invalid TVEntry found!");
unsigned CycleDispatched = static_cast<unsigned>(TVEntry.CycleDispatched);
- WaitTimeEntry &WTEntry = WaitTime[Index % Source.size()];
+ WaitTimeEntry &WTEntry = WaitTime[Index % getSource().size()];
WTEntry.CyclesSpentInSchedulerQueue +=
TVEntry.CycleIssued - CycleDispatched;
assert(CycleDispatched <= TVEntry.CycleReady &&
@@ -133,7 +133,7 @@ void TimelineView::printWaitTimeEntry(formatted_raw_ostream &OS,
const WaitTimeEntry &Entry,
unsigned SourceIndex,
unsigned Executions) const {
- bool PrintingTotals = SourceIndex == Source.size();
+ bool PrintingTotals = SourceIndex == getSource().size();
unsigned CumulativeExecutions = PrintingTotals ? Timeline.size() : Executions;
if (!PrintingTotals)
@@ -164,7 +164,8 @@ void TimelineView::printWaitTimeEntry(formatted_raw_ostream &OS,
OS.PadToColumn(27);
if (!PrintingTotals)
tryChangeColor(OS, Entry.CyclesSpentAfterWBAndBeforeRetire,
- CumulativeExecutions, STI.getSchedModel().MicroOpBufferSize);
+ CumulativeExecutions,
+ getSubTargetInfo().getSchedModel().MicroOpBufferSize);
OS << format("%.1f", floor((AverageTime3 * 10) + 0.5) / 10);
if (OS.has_colors())
@@ -181,33 +182,19 @@ void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
"[3]: Average time elapsed from WB until retire stage\n\n"
" [0] [1] [2] [3]\n";
OS << Header;
-
- // Use a
diff erent string stream for printing instructions.
- std::string Instruction;
- raw_string_ostream InstrStream(Instruction);
-
formatted_raw_ostream FOS(OS);
- unsigned Executions = Timeline.size() / Source.size();
+ unsigned Executions = Timeline.size() / getSource().size();
unsigned IID = 0;
- for (const MCInst &Inst : Source) {
+ for (const MCInst &Inst : getSource()) {
printWaitTimeEntry(FOS, WaitTime[IID], IID, Executions);
- // Append the instruction info at the end of the line.
- MCIP.printInst(&Inst, 0, "", STI, InstrStream);
- InstrStream.flush();
-
- // Consume any tabs or spaces at the beginning of the string.
- StringRef Str(Instruction);
- Str = Str.ltrim();
- FOS << " " << Str << '\n';
+ FOS << " " << printInstructionString(Inst) << '\n';
FOS.flush();
- Instruction = "";
-
++IID;
}
// If the timeline contains more than one instruction,
// let's also print global averages.
- if (Source.size() != 1) {
+ if (getSource().size() != 1) {
WaitTimeEntry TotalWaitTime = std::accumulate(
WaitTime.begin(), WaitTime.end(), WaitTimeEntry{0, 0, 0},
[](const WaitTimeEntry &A, const WaitTimeEntry &B) {
@@ -220,7 +207,7 @@ void TimelineView::printAverageWaitTimes(raw_ostream &OS) const {
printWaitTimeEntry(FOS, TotalWaitTime, IID, Executions);
FOS << " "
<< "<total>" << '\n';
- InstrStream.flush();
+ FOS.flush();
}
}
@@ -292,11 +279,8 @@ void TimelineView::printTimeline(raw_ostream &OS) const {
printTimelineHeader(FOS, LastCycle);
FOS.flush();
- // Use a
diff erent string stream for the instruction.
- std::string Instruction;
- raw_string_ostream InstrStream(Instruction);
-
unsigned IID = 0;
+ ArrayRef<llvm::MCInst> Source = getSource();
const unsigned Iterations = Timeline.size() / Source.size();
for (unsigned Iteration = 0; Iteration < Iterations; ++Iteration) {
for (const MCInst &Inst : Source) {
@@ -306,16 +290,8 @@ void TimelineView::printTimeline(raw_ostream &OS) const {
unsigned SourceIndex = IID % Source.size();
printTimelineViewEntry(FOS, Entry, Iteration, SourceIndex);
- // Append the instruction info at the end of the line.
- MCIP.printInst(&Inst, 0, "", STI, InstrStream);
- InstrStream.flush();
-
- // Consume any tabs or spaces at the beginning of the string.
- StringRef Str(Instruction);
- Str = Str.ltrim();
- FOS << " " << Str << '\n';
+ FOS << " " << printInstructionString(Inst) << '\n';
FOS.flush();
- Instruction = "";
++IID;
}
diff --git a/llvm/tools/llvm-mca/Views/TimelineView.h b/llvm/tools/llvm-mca/Views/TimelineView.h
index 9bec3b87db45..528579edf708 100644
--- a/llvm/tools/llvm-mca/Views/TimelineView.h
+++ b/llvm/tools/llvm-mca/Views/TimelineView.h
@@ -118,11 +118,7 @@ namespace mca {
/// a TimelineViewEntry object. TimelineViewEntry objects are then used
/// to print the timeline information, as well as the "average wait times"
/// for every instruction in the input assembly sequence.
-class TimelineView : public View {
- const llvm::MCSubtargetInfo &STI;
- llvm::MCInstPrinter &MCIP;
- llvm::ArrayRef<llvm::MCInst> Source;
-
+class TimelineView : public InstructionView {
unsigned CurrentCycle;
unsigned MaxCycle;
unsigned LastCycle;
diff --git a/llvm/tools/llvm-mca/Views/View.cpp b/llvm/tools/llvm-mca/Views/View.cpp
index 8e5c34d2d5c2..4cef7456f366 100644
--- a/llvm/tools/llvm-mca/Views/View.cpp
+++ b/llvm/tools/llvm-mca/Views/View.cpp
@@ -17,5 +17,13 @@ namespace llvm {
namespace mca {
void View::anchor() {}
+
+StringRef InstructionView::printInstructionString(const llvm::MCInst &MCI) const {
+ InstructionString = "";
+ MCIP.printInst(&MCI, 0, "", STI, InstrStream);
+ InstrStream.flush();
+ // Remove any tabs or spaces at the beginning of the instruction.
+ return StringRef(InstructionString).ltrim();
+ }
} // namespace mca
} // namespace llvm
diff --git a/llvm/tools/llvm-mca/Views/View.h b/llvm/tools/llvm-mca/Views/View.h
index 3b52511b4d29..1af6e5959f31 100644
--- a/llvm/tools/llvm-mca/Views/View.h
+++ b/llvm/tools/llvm-mca/Views/View.h
@@ -15,6 +15,7 @@
#ifndef LLVM_TOOLS_LLVM_MCA_VIEW_H
#define LLVM_TOOLS_LLVM_MCA_VIEW_H
+#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MCA/HWEventListener.h"
#include "llvm/Support/raw_ostream.h"
@@ -27,6 +28,33 @@ class View : public HWEventListener {
virtual ~View() = default;
void anchor() override;
};
+
+// The base class for views that deal with individual machine instructions.
+class InstructionView : public View {
+ const llvm::MCSubtargetInfo &STI;
+ llvm::MCInstPrinter &MCIP;
+ llvm::ArrayRef<llvm::MCInst> Source;
+
+ mutable std::string InstructionString;
+ mutable raw_string_ostream InstrStream;
+
+protected:
+ InstructionView(const llvm::MCSubtargetInfo &STI,
+ llvm::MCInstPrinter &Printer,
+ llvm::ArrayRef<llvm::MCInst> S)
+ : STI(STI), MCIP(Printer), Source(S), InstrStream(InstructionString) {}
+
+ virtual ~InstructionView() = default;
+
+ // Return a reference to a string representing a given machine instruction.
+ // The result should be used or copied before the next call to
+ // printInstructionString() as it will overwrite the previous result.
+ StringRef printInstructionString(const llvm::MCInst &MCI) const;
+
+ const llvm::MCSubtargetInfo &getSubTargetInfo() const { return STI; }
+ llvm::MCInstPrinter &getInstPrinter() const { return MCIP; }
+ llvm::ArrayRef<llvm::MCInst> getSource() const { return Source; }
+};
} // namespace mca
} // namespace llvm
More information about the llvm-commits
mailing list