diff options
Diffstat (limited to 'llvm/tools/llvm-mca/Views')
-rw-r--r-- | llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp | 15 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/BottleneckAnalysis.h | 30 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/DispatchStatistics.cpp | 16 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/DispatchStatistics.h | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/InstructionInfoView.cpp | 4 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/InstructionView.cpp | 33 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/InstructionView.h | 26 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp | 27 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/RegisterFileStatistics.h | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp | 3 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/SchedulerStatistics.h | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/SummaryView.cpp | 7 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/SummaryView.h | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/TimelineView.cpp | 22 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/TimelineView.h | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/Views/View.h | 20 |
17 files changed, 103 insertions, 108 deletions
diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp index 38a8e2ef9c53..5b110d6602df 100644 --- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp +++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp @@ -66,8 +66,6 @@ void PressureTracker::onInstructionExecuted(unsigned IID) { IPI.erase(IID); } void PressureTracker::handleInstructionIssuedEvent( const HWInstructionIssuedEvent &Event) { unsigned IID = Event.IR.getSourceIndex(); - using ResourceRef = HWInstructionIssuedEvent::ResourceRef; - using ResourceUse = std::pair<ResourceRef, ResourceCycles>; for (const ResourceUse &Use : Event.UsedResources) { const ResourceRef &RR = Use.first; unsigned Index = ProcResID2ResourceUsersIndex[RR.first]; @@ -200,8 +198,8 @@ void DependencyGraph::initializeRootSet( } } -void DependencyGraph::propagateThroughEdges( - SmallVectorImpl<unsigned> &RootSet, unsigned Iterations) { +void DependencyGraph::propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet, + unsigned Iterations) { SmallVector<unsigned, 8> ToVisit; // A critical sequence is computed as the longest path from a node of the @@ -223,14 +221,14 @@ void DependencyGraph::propagateThroughEdges( // The `unvisited nodes` set initially contains all the nodes from the // RootSet. A node N is added to the `unvisited nodes` if all its // predecessors have been visited already. - // + // // For simplicity, every node tracks the number of unvisited incoming edges in // field `NumVisitedPredecessors`. When the value of that field drops to // zero, then the corresponding node is added to a `ToVisit` set. // // At the end of every iteration of the outer loop, set `ToVisit` becomes our // new `unvisited nodes` set. - // + // // The algorithm terminates when the set of unvisited nodes (i.e. our RootSet) // is empty. This algorithm works under the assumption that the graph is // acyclic. @@ -269,8 +267,9 @@ void DependencyGraph::getCriticalSequence( // that node is the last instruction of our critical sequence. // Field N.Depth would tell us the total length of the sequence. // - // To obtain the sequence of critical edges, we simply follow the chain of critical - // predecessors starting from node N (field DGNode::CriticalPredecessor). + // To obtain the sequence of critical edges, we simply follow the chain of + // critical predecessors starting from node N (field + // DGNode::CriticalPredecessor). const auto It = std::max_element( Nodes.begin(), Nodes.end(), [](const DGNode &Lhs, const DGNode &Rhs) { return Lhs.Cost < Rhs.Cost; }); diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h index 427937d9e3d7..cd5af0afcf5b 100644 --- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h +++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h @@ -33,9 +33,9 @@ /// In particular, this occurs when there is a delta between the number of uOps /// dispatched and the number of uOps issued to the underlying pipelines. /// -/// The bottleneck analysis view is also responsible for identifying and printing -/// the most "critical" sequence of dependent instructions according to the -/// simulated run. +/// The bottleneck analysis view is also responsible for identifying and +/// printing the most "critical" sequence of dependent instructions according to +/// the simulated run. /// /// Below is the critical sequence computed for the dot-product example on /// btver2: @@ -62,13 +62,14 @@ /// and edges of the graph represent data dependencies or processor resource /// interferences. /// -/// Edges are dynamically 'discovered' by observing instruction state transitions -/// and backend pressure increase events. Edges are internally ranked based on -/// their "criticality". A dependency is considered to be critical if it takes a -/// long time to execute, and if it contributes to backend pressure increases. -/// Criticality is internally measured in terms of cycles; it is computed for -/// every edge in the graph as a function of the edge latency and the number of -/// backend pressure increase cycles contributed by that edge. +/// Edges are dynamically 'discovered' by observing instruction state +/// transitions and backend pressure increase events. Edges are internally +/// ranked based on their "criticality". A dependency is considered to be +/// critical if it takes a long time to execute, and if it contributes to +/// backend pressure increases. Criticality is internally measured in terms of +/// cycles; it is computed for every edge in the graph as a function of the edge +/// latency and the number of backend pressure increase cycles contributed by +/// that edge. /// /// At the end of simulation, costs are propagated to nodes through the edges of /// the graph, and the most expensive path connecting the root-set (a @@ -217,8 +218,8 @@ struct DependencyEdge { // Loop carried dependencies are carefully expanded by the bottleneck analysis // to guarantee that the graph stays acyclic. To this end, extra nodes are // pre-allocated at construction time to describe instructions from "past and -// future" iterations. The graph is kept acyclic mainly because it simplifies the -// complexity of the algorithm that computes the critical sequence. +// future" iterations. The graph is kept acyclic mainly because it simplifies +// the complexity of the algorithm that computes the critical sequence. class DependencyGraph { struct DGNode { unsigned NumPredecessors; @@ -239,7 +240,8 @@ class DependencyGraph { void pruneEdges(unsigned Iterations); void initializeRootSet(SmallVectorImpl<unsigned> &RootSet) const; - void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet, unsigned Iterations); + void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet, + unsigned Iterations); #ifndef NDEBUG void dumpDependencyEdge(raw_ostream &OS, const DependencyEdge &DE, @@ -333,7 +335,7 @@ public: void printView(raw_ostream &OS) const override; StringRef getNameAsString() const override { return "BottleneckAnalysis"; } - json::Value toJSON() const override { return "not implemented"; } + bool isSerializable() const override { return false; } #ifndef NDEBUG void dump(raw_ostream &OS, MCInstPrinter &MCIP) const { DG.dump(OS, MCIP); } diff --git a/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp b/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp index a1c0cf208d35..3dc17c8754d8 100644 --- a/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp +++ b/llvm/tools/llvm-mca/Views/DispatchStatistics.cpp @@ -1,5 +1,4 @@ -//===--------------------- DispatchStatistics.cpp ---------------------*- C++ -//-*-===// +//===--------------------- DispatchStatistics.cpp ---------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -77,10 +76,23 @@ void DispatchStatistics::printDispatchStalls(raw_ostream &OS) const { printStalls(SS, HWStalls[HWStallEvent::StoreQueueFull], NumCycles); SS << "\nGROUP - Static restrictions on the dispatch group: "; printStalls(SS, HWStalls[HWStallEvent::DispatchGroupStall], NumCycles); + SS << "\nUSH - Uncategorised Structural Hazard: "; + printStalls(SS, HWStalls[HWStallEvent::CustomBehaviourStall], NumCycles); SS << '\n'; SS.flush(); OS << Buffer; } +json::Value DispatchStatistics::toJSON() const { + json::Object JO({{"RAT", HWStalls[HWStallEvent::RegisterFileStall]}, + {"RCU", HWStalls[HWStallEvent::RetireControlUnitStall]}, + {"SCHEDQ", HWStalls[HWStallEvent::SchedulerQueueFull]}, + {"LQ", HWStalls[HWStallEvent::LoadQueueFull]}, + {"SQ", HWStalls[HWStallEvent::StoreQueueFull]}, + {"GROUP", HWStalls[HWStallEvent::DispatchGroupStall]}, + {"USH", HWStalls[HWStallEvent::CustomBehaviourStall]}}); + return JO; +} + } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/DispatchStatistics.h b/llvm/tools/llvm-mca/Views/DispatchStatistics.h index 8d999fb0acfe..81b582f74a6b 100644 --- a/llvm/tools/llvm-mca/Views/DispatchStatistics.h +++ b/llvm/tools/llvm-mca/Views/DispatchStatistics.h @@ -79,6 +79,7 @@ public: printDispatchHistogram(OS); } StringRef getNameAsString() const override { return "DispatchStatistics"; } + json::Value toJSON() const override; }; } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp b/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp index 2248f63fe7e9..3f6abf4af2cf 100644 --- a/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp +++ b/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp @@ -93,7 +93,7 @@ void InstructionInfoView::collectData( MutableArrayRef<InstructionInfoViewData> IIVD) const { const llvm::MCSubtargetInfo &STI = getSubTargetInfo(); const MCSchedModel &SM = STI.getSchedModel(); - for (const auto &I : zip(getSource(), IIVD)) { + for (const 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()); @@ -147,7 +147,7 @@ json::Value InstructionInfoView::toJSON() const { JO.try_emplace("Instruction", (unsigned)I.index()); InstInfo.push_back(std::move(JO)); } - return json::Value(std::move(InstInfo)); + return json::Object({{"InstructionList", json::Value(std::move(InstInfo))}}); } } // namespace mca. } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/InstructionView.cpp b/llvm/tools/llvm-mca/Views/InstructionView.cpp index 7f7a5b7cdbbb..3b174a064985 100644 --- a/llvm/tools/llvm-mca/Views/InstructionView.cpp +++ b/llvm/tools/llvm-mca/Views/InstructionView.cpp @@ -1,4 +1,4 @@ -//===----------------------- View.cpp ---------------------------*- C++ -*-===// +//===----------------------- InstructionView.cpp ----------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,15 +11,18 @@ /// //===----------------------------------------------------------------------===// -#include <sstream> #include "Views/InstructionView.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSubtargetInfo.h" namespace llvm { namespace mca { -StringRef InstructionView::printInstructionString(const llvm::MCInst &MCI) const { +InstructionView::~InstructionView() = default; + +StringRef +InstructionView::printInstructionString(const llvm::MCInst &MCI) const { InstructionString = ""; MCIP.printInst(&MCI, 0, "", STI, InstrStream); InstrStream.flush(); @@ -28,33 +31,13 @@ StringRef InstructionView::printInstructionString(const llvm::MCInst &MCI) const } json::Value InstructionView::toJSON() const { - json::Object JO; json::Array SourceInfo; for (const auto &MCI : getSource()) { StringRef Instruction = printInstructionString(MCI); SourceInfo.push_back(Instruction.str()); } - JO.try_emplace("Instructions", std::move(SourceInfo)); - - json::Array Resources; - const MCSchedModel &SM = STI.getSchedModel(); - for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) { - const MCProcResourceDesc &ProcResource = *SM.getProcResource(I); - unsigned NumUnits = ProcResource.NumUnits; - // Skip groups and invalid resources with zero units. - if (ProcResource.SubUnitsIdxBegin || !NumUnits) - continue; - for (unsigned J = 0; J < NumUnits; ++J) { - std::stringstream ResNameStream; - ResNameStream << ProcResource.Name; - if (NumUnits > 1) - ResNameStream << "." << J; - Resources.push_back(ResNameStream.str()); - } - } - JO.try_emplace("Resources", json::Object({{"CPUName", MCPU}, {"Resources", std::move(Resources)}})); - - return JO; + return SourceInfo; } + } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/InstructionView.h b/llvm/tools/llvm-mca/Views/InstructionView.h index 2a260b97d8fb..1843b0513dfc 100644 --- a/llvm/tools/llvm-mca/Views/InstructionView.h +++ b/llvm/tools/llvm-mca/Views/InstructionView.h @@ -1,4 +1,4 @@ -//===----------------------- InstrucionView.h -----------------------------*- C++ -*-===// +//===----------------------- InstructionView.h ------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -16,9 +16,8 @@ #define LLVM_TOOLS_LLVM_MCA_INSTRUCTIONVIEW_H #include "Views/View.h" -#include "llvm/MC/MCInstPrinter.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/JSON.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { namespace mca { @@ -28,7 +27,6 @@ class InstructionView : public View { const llvm::MCSubtargetInfo &STI; llvm::MCInstPrinter &MCIP; llvm::ArrayRef<llvm::MCInst> Source; - StringRef MCPU; mutable std::string InstructionString; mutable raw_string_ostream InstrStream; @@ -36,17 +34,13 @@ class InstructionView : public View { public: void printView(llvm::raw_ostream &) const override {} InstructionView(const llvm::MCSubtargetInfo &STI, - llvm::MCInstPrinter &Printer, - llvm::ArrayRef<llvm::MCInst> S, - StringRef MCPU = StringRef()) - : STI(STI), MCIP(Printer), Source(S), MCPU(MCPU), - InstrStream(InstructionString) {} + llvm::MCInstPrinter &Printer, llvm::ArrayRef<llvm::MCInst> S) + : STI(STI), MCIP(Printer), Source(S), InstrStream(InstructionString) {} + + virtual ~InstructionView(); - virtual ~InstructionView() = default; + StringRef getNameAsString() const override { return "Instructions"; } - StringRef getNameAsString() const override { - return "Instructions and CPU resources"; - } // 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. @@ -55,12 +49,10 @@ public: llvm::MCInstPrinter &getInstPrinter() const { return MCIP; } llvm::ArrayRef<llvm::MCInst> getSource() const { return Source; } + json::Value toJSON() const override; - virtual void printViewJSON(llvm::raw_ostream &OS) override { - json::Value JV = toJSON(); - OS << formatv("{0:2}", JV) << "\n"; - } }; + } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp b/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp index 58736ee0d18c..4ef8053bff41 100644 --- a/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp +++ b/llvm/tools/llvm-mca/Views/RegisterFileStatistics.cpp @@ -60,18 +60,21 @@ void RegisterFileStatistics::updateMoveElimInfo(const Instruction &Inst) { if (!Inst.isOptimizableMove()) return; - assert(Inst.getDefs().size() == 1 && "Expected a single definition!"); - assert(Inst.getUses().size() == 1 && "Expected a single register use!"); - const WriteState &WS = Inst.getDefs()[0]; - const ReadState &RS = Inst.getUses()[0]; - - MoveEliminationInfo &Info = - MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()]; - Info.TotalMoveEliminationCandidates++; - if (WS.isEliminated()) - Info.CurrentMovesEliminated++; - if (WS.isWriteZero() && RS.isReadZero()) - Info.TotalMovesThatPropagateZero++; + if (Inst.getDefs().size() != Inst.getUses().size()) + return; + + for (size_t I = 0, E = Inst.getDefs().size(); I < E; ++I) { + const WriteState &WS = Inst.getDefs()[I]; + const ReadState &RS = Inst.getUses()[E - (I + 1)]; + + MoveEliminationInfo &Info = + MoveElimInfo[Inst.getDefs()[0].getRegisterFileID()]; + Info.TotalMoveEliminationCandidates++; + if (WS.isEliminated()) + Info.CurrentMovesEliminated++; + if (WS.isWriteZero() && RS.isReadZero()) + Info.TotalMovesThatPropagateZero++; + } } void RegisterFileStatistics::onEvent(const HWInstructionEvent &Event) { diff --git a/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h b/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h index cf384dbfe337..ec5c5f431e12 100644 --- a/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h +++ b/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h @@ -76,6 +76,7 @@ public: StringRef getNameAsString() const override { return "RegisterFileStatistics"; } + bool isSerializable() const override { return false; } }; } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp b/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp index 61c115b27be1..1c40428fb018 100644 --- a/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp +++ b/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.cpp @@ -71,7 +71,8 @@ void RetireControlUnitStatistics::printView(raw_ostream &OS) const { } unsigned AvgUsage = (double)SumOfUsedEntries / NumCycles; - double MaxUsagePercentage = ((double)MaxUsedEntries / TotalROBEntries) * 100.0; + double MaxUsagePercentage = + ((double)MaxUsedEntries / TotalROBEntries) * 100.0; double NormalizedMaxPercentage = floor((MaxUsagePercentage * 10) + 0.5) / 10; double AvgUsagePercentage = ((double)AvgUsage / TotalROBEntries) * 100.0; double NormalizedAvgPercentage = floor((AvgUsagePercentage * 10) + 0.5) / 10; diff --git a/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h b/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h index 662a223662e6..86b46e93aa7c 100644 --- a/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h +++ b/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h @@ -55,6 +55,7 @@ public: StringRef getNameAsString() const override { return "RetireControlUnitStatistics"; } + bool isSerializable() const override { return false; } }; } // namespace mca diff --git a/llvm/tools/llvm-mca/Views/SchedulerStatistics.h b/llvm/tools/llvm-mca/Views/SchedulerStatistics.h index 734046c3112f..66f4b0011866 100644 --- a/llvm/tools/llvm-mca/Views/SchedulerStatistics.h +++ b/llvm/tools/llvm-mca/Views/SchedulerStatistics.h @@ -89,6 +89,7 @@ public: void printView(llvm::raw_ostream &OS) const override; StringRef getNameAsString() const override { return "SchedulerStatistics"; } + bool isSerializable() const override { return false; } }; } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/SummaryView.cpp b/llvm/tools/llvm-mca/Views/SummaryView.cpp index c0fe3b5193a7..bf258b4c26b1 100644 --- a/llvm/tools/llvm-mca/Views/SummaryView.cpp +++ b/llvm/tools/llvm-mca/Views/SummaryView.cpp @@ -1,4 +1,4 @@ -//===--------------------- SummaryView.cpp -------------------*- C++ -*-===// +//===--------------------- SummaryView.cpp ----------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -24,9 +24,8 @@ namespace mca { SummaryView::SummaryView(const MCSchedModel &Model, ArrayRef<MCInst> S, unsigned Width) - : SM(Model), Source(S), DispatchWidth(Width?Width: Model.IssueWidth), - LastInstructionIdx(0), - TotalCycles(0), NumMicroOps(0), + : SM(Model), Source(S), DispatchWidth(Width ? Width : Model.IssueWidth), + LastInstructionIdx(0), TotalCycles(0), NumMicroOps(0), ProcResourceUsage(Model.getNumProcResourceKinds(), 0), ProcResourceMasks(Model.getNumProcResourceKinds()), ResIdx2ProcResID(Model.getNumProcResourceKinds(), 0) { diff --git a/llvm/tools/llvm-mca/Views/SummaryView.h b/llvm/tools/llvm-mca/Views/SummaryView.h index 2622e869ef23..e2c7cfd19e94 100644 --- a/llvm/tools/llvm-mca/Views/SummaryView.h +++ b/llvm/tools/llvm-mca/Views/SummaryView.h @@ -1,4 +1,4 @@ -//===--------------------- SummaryView.h ---------------------*- C++ -*-===// +//===--------------------- SummaryView.h ------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/tools/llvm-mca/Views/TimelineView.cpp b/llvm/tools/llvm-mca/Views/TimelineView.cpp index c8b481bc7ce6..9a949761bb75 100644 --- a/llvm/tools/llvm-mca/Views/TimelineView.cpp +++ b/llvm/tools/llvm-mca/Views/TimelineView.cpp @@ -21,8 +21,8 @@ TimelineView::TimelineView(const MCSubtargetInfo &sti, MCInstPrinter &Printer, llvm::ArrayRef<llvm::MCInst> S, unsigned Iterations, unsigned Cycles) : InstructionView(sti, Printer, S), CurrentCycle(0), - MaxCycle(Cycles == 0 ? 80 : Cycles), LastCycle(0), WaitTime(S.size()), - UsedBuffer(S.size()) { + MaxCycle(Cycles == 0 ? std::numeric_limits<unsigned>::max() : Cycles), + LastCycle(0), WaitTime(S.size()), UsedBuffer(S.size()) { unsigned NumInstructions = getSource().size(); assert(Iterations && "Invalid number of iterations specified!"); NumInstructions *= Iterations; @@ -77,8 +77,10 @@ void TimelineView::onEvent(const HWInstructionEvent &Event) { "Instruction cannot be ready if it hasn't been dispatched yet!"); WTEntry.CyclesSpentInSQWhileReady += TVEntry.CycleIssued - TVEntry.CycleReady; - WTEntry.CyclesSpentAfterWBAndBeforeRetire += - (CurrentCycle - 1) - TVEntry.CycleExecuted; + if (CurrentCycle > TVEntry.CycleExecuted) { + WTEntry.CyclesSpentAfterWBAndBeforeRetire += + (CurrentCycle - 1) - TVEntry.CycleExecuted; + } break; } case HWInstructionEvent::Ready: @@ -243,7 +245,8 @@ void TimelineView::printTimelineViewEntry(formatted_raw_ostream &OS, for (unsigned I = Entry.CycleExecuted + 1, E = Entry.CycleRetired; I < E; ++I) OS << TimelineView::DisplayChar::RetireLag; - OS << TimelineView::DisplayChar::Retired; + if (Entry.CycleExecuted < Entry.CycleRetired) + OS << TimelineView::DisplayChar::Retired; // Skip other columns. for (unsigned I = Entry.CycleRetired + 1, E = LastCycle; I <= E; ++I) @@ -285,7 +288,14 @@ void TimelineView::printTimeline(raw_ostream &OS) const { for (unsigned Iteration = 0; Iteration < Iterations; ++Iteration) { for (const MCInst &Inst : Source) { const TimelineViewEntry &Entry = Timeline[IID]; - if (Entry.CycleRetired == 0) + // When an instruction is retired after timeline-max-cycles, + // its CycleRetired is left at 0. However, it's possible for + // a 0 latency instruction to be retired during cycle 0 and we + // don't want to early exit in that case. The CycleExecuted + // attribute is set correctly whether or not it is greater + // than timeline-max-cycles so we can use that to ensure + // we don't early exit because of a 0 latency instruction. + if (Entry.CycleRetired == 0 && Entry.CycleExecuted != 0) return; unsigned SourceIndex = IID % Source.size(); diff --git a/llvm/tools/llvm-mca/Views/TimelineView.h b/llvm/tools/llvm-mca/Views/TimelineView.h index 81f2b0335081..81be8244b779 100644 --- a/llvm/tools/llvm-mca/Views/TimelineView.h +++ b/llvm/tools/llvm-mca/Views/TimelineView.h @@ -125,7 +125,7 @@ class TimelineView : public InstructionView { unsigned LastCycle; struct TimelineViewEntry { - int CycleDispatched; // A negative value is an "invalid cycle". + int CycleDispatched; // A negative value is an "invalid cycle". unsigned CycleReady; unsigned CycleIssued; unsigned CycleExecuted; diff --git a/llvm/tools/llvm-mca/Views/View.h b/llvm/tools/llvm-mca/Views/View.h index 85464bfda662..c604733d4ec9 100644 --- a/llvm/tools/llvm-mca/Views/View.h +++ b/llvm/tools/llvm-mca/Views/View.h @@ -17,32 +17,22 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MCA/HWEventListener.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/JSON.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { namespace mca { class View : public HWEventListener { public: - enum OutputKind { OK_READABLE, OK_JSON }; - - void printView(OutputKind OutputKind, llvm::raw_ostream &OS) { - if (OutputKind == OK_JSON) - printViewJSON(OS); - else - printView(OS); - } + virtual ~View() = default; virtual void printView(llvm::raw_ostream &OS) const = 0; - virtual void printViewJSON(llvm::raw_ostream &OS) { - json::Object JO; - JO.try_emplace(getNameAsString().str(), toJSON()); - OS << formatv("{0:2}", json::Value(std::move(JO))) << "\n"; - } - virtual ~View() = default; virtual StringRef getNameAsString() const = 0; + virtual json::Value toJSON() const { return "not implemented"; } + virtual bool isSerializable() const { return true; } + void anchor() override; }; } // namespace mca |