Index: llvm/docs/CommandGuide/llvm-mca.rst =================================================================== --- llvm/docs/CommandGuide/llvm-mca.rst +++ llvm/docs/CommandGuide/llvm-mca.rst @@ -203,16 +203,18 @@ .. option:: -bottleneck-analysis Print information about bottlenecks that affect the throughput. This analysis - can be expensive, and it is disabled by default. Bottlenecks are highlighted + can be expensive, and it is disabled by default. Bottlenecks are highlighted in the summary view. Bottleneck analysis is currently not supported for processors with an in-order backend. .. option:: -json - Print the requested views in JSON format. The instructions and the processor - resources are printed as members of special top level JSON objects. The - individual views refer to them by index. - + Print the requested views in valid JSON format. The instructions and the + processor resources are printed as members of special top level JSON objects. + The individual views refer to them by index, nonetheles, not all views are + printed when using in this format, e.g. bottleneck analysis, timeline view, + etc. + .. option:: -disable-cb Force usage of the generic CustomBehaviour class rather than using the target @@ -987,7 +989,7 @@ Custom Behaviour """""""""""""""""""""""""""""""""""" Due to certain instructions not being expressed perfectly within their -scheduling model, :program:`llvm-ma` isn't always able to simulate them +scheduling model, :program:`llvm-mca` isn't always able to simulate them perfectly. Modifying the scheduling model isn't always a viable option though (maybe because the instruction is modeled incorrectly on purpose or the instruction's behaviour is quite complex). The Index: llvm/tools/llvm-mca/PipelinePrinter.cpp =================================================================== --- llvm/tools/llvm-mca/PipelinePrinter.cpp +++ llvm/tools/llvm-mca/PipelinePrinter.cpp @@ -18,8 +18,18 @@ namespace mca { void PipelinePrinter::printReport(llvm::raw_ostream &OS) const { - for (const auto &V : Views) - V->printView(OutputKind, OS); + json::Object JO; + for (const auto &V : Views) { + if ((OutputKind == View::OK_JSON)) { + if (V->isSerializable()) { + JO.try_emplace(V->getNameAsString().str(), V->toJSON()); + } + } else { + V->printView(OS); + } + } + if (OutputKind == View::OK_JSON) + OS << formatv("{0:2}", json::Value(std::move(JO))) << "\n"; } } // namespace mca. } // namespace llvm Index: llvm/tools/llvm-mca/Views/BottleneckAnalysis.h =================================================================== --- llvm/tools/llvm-mca/Views/BottleneckAnalysis.h +++ llvm/tools/llvm-mca/Views/BottleneckAnalysis.h @@ -15,7 +15,7 @@ /// Example of bottleneck analysis report for a dot-product on X86 btver2: /// /// Cycles with backend pressure increase [ 40.76% ] -/// Throughput Bottlenecks: +/// Throughput Bottlenecks: /// Resource Pressure [ 39.34% ] /// - JFPA [ 39.34% ] /// - JFPU0 [ 39.34% ] @@ -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: @@ -333,7 +337,7 @@ 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); } Index: llvm/tools/llvm-mca/Views/DispatchStatistics.h =================================================================== --- llvm/tools/llvm-mca/Views/DispatchStatistics.h +++ llvm/tools/llvm-mca/Views/DispatchStatistics.h @@ -79,6 +79,7 @@ printDispatchHistogram(OS); } StringRef getNameAsString() const override { return "DispatchStatistics"; } + json::Value toJSON() const override; }; } // namespace mca } // namespace llvm Index: llvm/tools/llvm-mca/Views/DispatchStatistics.cpp =================================================================== --- llvm/tools/llvm-mca/Views/DispatchStatistics.cpp +++ llvm/tools/llvm-mca/Views/DispatchStatistics.cpp @@ -84,5 +84,16 @@ 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 Index: llvm/tools/llvm-mca/Views/InstructionInfoView.cpp =================================================================== --- llvm/tools/llvm-mca/Views/InstructionInfoView.cpp +++ llvm/tools/llvm-mca/Views/InstructionInfoView.cpp @@ -147,7 +147,7 @@ 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 Index: llvm/tools/llvm-mca/Views/RegisterFileStatistics.h =================================================================== --- llvm/tools/llvm-mca/Views/RegisterFileStatistics.h +++ llvm/tools/llvm-mca/Views/RegisterFileStatistics.h @@ -76,6 +76,7 @@ StringRef getNameAsString() const override { return "RegisterFileStatistics"; } + bool isSerializable() const override { return false; } }; } // namespace mca } // namespace llvm Index: llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h =================================================================== --- llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h +++ llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h @@ -55,6 +55,7 @@ StringRef getNameAsString() const override { return "RetireControlUnitStatistics"; } + bool isSerializable() const override { return false; } }; } // namespace mca Index: llvm/tools/llvm-mca/Views/SchedulerStatistics.h =================================================================== --- llvm/tools/llvm-mca/Views/SchedulerStatistics.h +++ llvm/tools/llvm-mca/Views/SchedulerStatistics.h @@ -89,6 +89,7 @@ void printView(llvm::raw_ostream &OS) const override; StringRef getNameAsString() const override { return "SchedulerStatistics"; } + bool isSerializable() const override { return false; } }; } // namespace mca } // namespace llvm Index: llvm/tools/llvm-mca/Views/TimelineView.h =================================================================== --- llvm/tools/llvm-mca/Views/TimelineView.h +++ llvm/tools/llvm-mca/Views/TimelineView.h @@ -125,7 +125,7 @@ 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; @@ -181,6 +181,7 @@ } StringRef getNameAsString() const override { return "TimelineView"; } json::Value toJSON() const override; + bool isSerializable() const override { return false; } }; } // namespace mca } // namespace llvm Index: llvm/tools/llvm-mca/Views/View.h =================================================================== --- llvm/tools/llvm-mca/Views/View.h +++ llvm/tools/llvm-mca/Views/View.h @@ -17,8 +17,8 @@ #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 { @@ -43,6 +43,7 @@ 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