From 8af3fe81eb94e71c4921ac246feaa76c47ecbf39 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Thu, 8 Mar 2018 16:08:43 +0000 Subject: [PATCH] [llvm-mca] Unify the API for the various views. NFCI This allows the customization of the performance report. Users can specify their own custom sequence of views. Each view contributes a portion of the performance report generated by the BackendPrinter. Internally, class BackendPrinter keeps a sequence of views; views are printed out in sequence when method 'printReport()' is called. This patch addresses one of the two review comments from Clement in D43951. llvm-svn: 327018 --- llvm/tools/llvm-mca/Backend.cpp | 10 +-- llvm/tools/llvm-mca/Backend.h | 16 ++-- llvm/tools/llvm-mca/BackendPrinter.cpp | 136 +++-------------------------- llvm/tools/llvm-mca/BackendPrinter.h | 76 ++++------------ llvm/tools/llvm-mca/BackendStatistics.cpp | 59 +++++++++++++ llvm/tools/llvm-mca/BackendStatistics.h | 56 +++++++++++- llvm/tools/llvm-mca/CMakeLists.txt | 1 + llvm/tools/llvm-mca/HWEventListener.h | 3 +- llvm/tools/llvm-mca/ResourcePressureView.h | 6 +- llvm/tools/llvm-mca/TimelineView.h | 8 +- llvm/tools/llvm-mca/View.cpp | 21 +++++ llvm/tools/llvm-mca/View.h | 33 +++++++ llvm/tools/llvm-mca/llvm-mca.cpp | 72 ++++++++++++--- 13 files changed, 280 insertions(+), 217 deletions(-) create mode 100644 llvm/tools/llvm-mca/View.cpp create mode 100644 llvm/tools/llvm-mca/View.h diff --git a/llvm/tools/llvm-mca/Backend.cpp b/llvm/tools/llvm-mca/Backend.cpp index 890cbc1..62e2395 100644 --- a/llvm/tools/llvm-mca/Backend.cpp +++ b/llvm/tools/llvm-mca/Backend.cpp @@ -31,12 +31,12 @@ void Backend::addEventListener(HWEventListener *Listener) { void Backend::runCycle(unsigned Cycle) { notifyCycleBegin(Cycle); - if (!SM->hasNext()) { + if (!SM.hasNext()) { notifyCycleEnd(Cycle); return; } - InstRef IR = SM->peekNext(); + InstRef IR = SM.peekNext(); const InstrDesc *Desc = &IB->getOrCreateInstrDesc(STI, *IR.second); while (DU->isAvailable(Desc->NumMicroOps) && DU->canDispatch(*Desc)) { Instruction *NewIS = IB->createInstruction(STI, *DU, IR.first, *IR.second); @@ -49,12 +49,12 @@ void Backend::runCycle(unsigned Cycle) { notifyInstructionExecuted(IR.first); // Check if we have dispatched all the instructions. - SM->updateNext(); - if (!SM->hasNext()) + SM.updateNext(); + if (!SM.hasNext()) break; // Prepare for the next round. - IR = SM->peekNext(); + IR = SM.peekNext(); Desc = &IB->getOrCreateInstrDesc(STI, *IR.second); } diff --git a/llvm/tools/llvm-mca/Backend.h b/llvm/tools/llvm-mca/Backend.h index 6e2db08..5d1df1d 100644 --- a/llvm/tools/llvm-mca/Backend.h +++ b/llvm/tools/llvm-mca/Backend.h @@ -48,7 +48,7 @@ class Backend { std::unique_ptr IB; std::unique_ptr HWS; std::unique_ptr DU; - std::unique_ptr SM; + SourceMgr &SM; unsigned Cycles; llvm::DenseMap> Instructions; @@ -58,7 +58,7 @@ class Backend { public: Backend(const llvm::MCSubtargetInfo &Subtarget, const llvm::MCInstrInfo &MCII, - const llvm::MCRegisterInfo &MRI, std::unique_ptr Source, + const llvm::MCRegisterInfo &MRI, SourceMgr &Source, unsigned DispatchWidth = 0, unsigned RegisterFileSize = 0, unsigned MaxRetirePerCycle = 0, unsigned LoadQueueSize = 0, unsigned StoreQueueSize = 0, bool AssumeNoAlias = false) @@ -69,17 +69,17 @@ public: DU(llvm::make_unique( this, MRI, Subtarget.getSchedModel().MicroOpBufferSize, RegisterFileSize, MaxRetirePerCycle, DispatchWidth, HWS.get())), - SM(std::move(Source)), Cycles(0) { + SM(Source), Cycles(0) { IB = llvm::make_unique(MCII, getProcResourceMasks()); } void run() { - while (SM->hasNext() || !DU->isRCUEmpty()) + while (SM.hasNext() || !DU->isRCUEmpty()) runCycle(Cycles++); } - unsigned getNumIterations() const { return SM->getNumIterations(); } - unsigned getNumInstructions() const { return SM->size(); } + unsigned getNumIterations() const { return SM.getNumIterations(); } + unsigned getNumInstructions() const { return SM.size(); } unsigned getNumCycles() const { return Cycles; } unsigned getTotalRegisterMappingsCreated() const { return DU->getTotalRegisterMappingsCreated(); @@ -114,14 +114,14 @@ public: } const llvm::MCInst &getMCInstFromIndex(unsigned Index) const { - return SM->getMCInstFromIndex(Index); + return SM.getMCInstFromIndex(Index); } const InstrDesc &getInstrDesc(const llvm::MCInst &Inst) const { return IB->getOrCreateInstrDesc(STI, Inst); } - const SourceMgr &getSourceMgr() const { return *SM; } + const SourceMgr &getSourceMgr() const { return SM; } void addEventListener(HWEventListener *Listener); void notifyCycleBegin(unsigned Cycle); diff --git a/llvm/tools/llvm-mca/BackendPrinter.cpp b/llvm/tools/llvm-mca/BackendPrinter.cpp index 521ef04..d98082a 100644 --- a/llvm/tools/llvm-mca/BackendPrinter.cpp +++ b/llvm/tools/llvm-mca/BackendPrinter.cpp @@ -13,25 +13,15 @@ //===----------------------------------------------------------------------===// #include "BackendPrinter.h" +#include "View.h" #include "llvm/CodeGen/TargetSchedule.h" namespace mca { using namespace llvm; -std::unique_ptr -BackendPrinter::getOutputStream(std::string OutputFile) { - if (OutputFile == "") - OutputFile = "-"; - std::error_code EC; - auto Out = llvm::make_unique(OutputFile, EC, sys::fs::F_None); - if (!EC) - return Out; - errs() << EC.message() << '\n'; - return nullptr; -} - -void BackendPrinter::printGeneralStatistics(unsigned Iterations, +void BackendPrinter::printGeneralStatistics(raw_ostream &OS, + unsigned Iterations, unsigned Cycles, unsigned Instructions, unsigned DispatchWidth) const { @@ -46,67 +36,10 @@ void BackendPrinter::printGeneralStatistics(unsigned Iterations, TempStream << "\nDispatch Width: " << DispatchWidth; TempStream << "\nIPC: " << format("%.2f", IPC) << '\n'; TempStream.flush(); - File->os() << Buffer; -} - -void BackendPrinter::printRATStatistics(unsigned TotalMappings, - unsigned MaxUsedMappings) const { - std::string Buffer; - raw_string_ostream TempStream(Buffer); - TempStream << "\n\nRegister Alias Table:"; - TempStream << "\nTotal number of mappings created: " << TotalMappings; - TempStream << "\nMax number of mappings used: " << MaxUsedMappings - << '\n'; - TempStream.flush(); - File->os() << Buffer; -} - -void BackendPrinter::printDispatchStalls(unsigned RATStalls, unsigned RCUStalls, - unsigned SCHEDQStalls, - unsigned LDQStalls, unsigned STQStalls, - unsigned DGStalls) const { - std::string Buffer; - raw_string_ostream TempStream(Buffer); - TempStream << "\n\nDynamic Dispatch Stall Cycles:\n"; - TempStream << "RAT - Register unavailable: " - << RATStalls; - TempStream << "\nRCU - Retire tokens unavailable: " - << RCUStalls; - TempStream << "\nSCHEDQ - Scheduler full: " - << SCHEDQStalls; - TempStream << "\nLQ - Load queue full: " - << LDQStalls; - TempStream << "\nSQ - Store queue full: " - << STQStalls; - TempStream << "\nGROUP - Static restrictions on the dispatch group: " - << DGStalls; - TempStream << '\n'; - TempStream.flush(); - File->os() << Buffer; -} - -void BackendPrinter::printSchedulerUsage( - const MCSchedModel &SM, const ArrayRef &Usage) const { - std::string Buffer; - raw_string_ostream TempStream(Buffer); - TempStream << "\n\nScheduler's queue usage:\n"; - const ArrayRef ResourceMasks = B.getProcResourceMasks(); - for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) { - const MCProcResourceDesc &ProcResource = *SM.getProcResource(I); - if (!ProcResource.BufferSize) - continue; - - for (const BufferUsageEntry &Entry : Usage) - if (ResourceMasks[I] == Entry.first) - TempStream << ProcResource.Name << ", " << Entry.second << '/' - << ProcResource.BufferSize << '\n'; - } - - TempStream.flush(); - File->os() << Buffer; + OS << Buffer; } -void BackendPrinter::printInstructionInfo() const { +void BackendPrinter::printInstructionInfo(raw_ostream &OS) const { std::string Buffer; raw_string_ostream TempStream(Buffer); @@ -143,67 +76,22 @@ void BackendPrinter::printInstructionInfo() const { TempStream << (ID.MayLoad ? " * " : " "); TempStream << (ID.MayStore ? " * " : " "); TempStream << (ID.HasSideEffects ? " * " : " "); - MCIP->printInst(&Inst, TempStream, "", B.getSTI()); + MCIP.printInst(&Inst, TempStream, "", B.getSTI()); TempStream << '\n'; } TempStream.flush(); - File->os() << Buffer; + OS << Buffer; } -void BackendPrinter::printReport() const { - assert(isFileValid()); +void BackendPrinter::printReport(llvm::raw_ostream &OS) const { unsigned Cycles = B.getNumCycles(); - printGeneralStatistics(B.getNumIterations(), Cycles, B.getNumInstructions(), + printGeneralStatistics(OS, B.getNumIterations(), Cycles, B.getNumInstructions(), B.getDispatchWidth()); - printInstructionInfo(); + printInstructionInfo(OS); - if (EnableVerboseOutput) { - printDispatchStalls(B.getNumRATStalls(), B.getNumRCUStalls(), - B.getNumSQStalls(), B.getNumLDQStalls(), - B.getNumSTQStalls(), B.getNumDispatchGroupStalls()); - printRATStatistics(B.getTotalRegisterMappingsCreated(), - B.getMaxUsedRegisterMappings()); - BS->printHistograms(File->os()); - - std::vector Usage; - B.getBuffersUsage(Usage); - printSchedulerUsage(B.getSchedModel(), Usage); - } - - if (RPV) - RPV->printResourcePressure(getOStream(), Cycles); - - if (TV) { - TV->printTimeline(getOStream()); - TV->printAverageWaitTimes(getOStream()); - } -} - -void BackendPrinter::addResourcePressureView() { - if (!RPV) { - RPV = llvm::make_unique( - B.getSTI(), *MCIP, B.getSourceMgr(), B.getProcResourceMasks()); - B.addEventListener(RPV.get()); - } -} - -void BackendPrinter::addTimelineView(unsigned MaxIterations, - unsigned MaxCycles) { - if (!TV) { - TV = llvm::make_unique(B.getSTI(), *MCIP, B.getSourceMgr(), - MaxIterations, MaxCycles); - B.addEventListener(TV.get()); - } -} - -void BackendPrinter::initialize(std::string OutputFileName) { - File = getOutputStream(OutputFileName); - MCIP->setPrintImmHex(false); - if (EnableVerboseOutput) { - BS = llvm::make_unique(); - B.addEventListener(BS.get()); - } + for (const auto &V : Views) + V->printView(OS); } } // namespace mca. diff --git a/llvm/tools/llvm-mca/BackendPrinter.h b/llvm/tools/llvm-mca/BackendPrinter.h index b4793b6..f018cc8 100644 --- a/llvm/tools/llvm-mca/BackendPrinter.h +++ b/llvm/tools/llvm-mca/BackendPrinter.h @@ -9,9 +9,11 @@ /// \file /// /// This file implements class BackendPrinter. -/// BackendPrinter is able to collect statistics related to the code executed -/// by the Backend class. Information is then printed out with the help of -/// a MCInstPrinter (to pretty print MCInst objects) and other helper classes. +/// +/// BackendPrinter allows the customization of the performance report. With the +/// help of this class, users can specify their own custom sequence of views. +/// Each view is then printed out in sequence when method printReport() is +/// called. /// //===----------------------------------------------------------------------===// @@ -19,20 +21,15 @@ #define LLVM_TOOLS_LLVM_MCA_BACKENDPRINTER_H #include "Backend.h" -#include "BackendStatistics.h" -#include "ResourcePressureView.h" -#include "TimelineView.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCInstPrinter.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/ToolOutputFile.h" +#include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "llvm-mca" namespace mca { -class ResourcePressureView; -class TimelineView; +class View; /// \brief A printer class that knows how to collects statistics on the /// code analyzed by the llvm-mca tool. @@ -42,59 +39,24 @@ class TimelineView; /// classes the task of printing out timeline information as well as /// resource pressure. class BackendPrinter { - Backend &B; - bool EnableVerboseOutput; - - std::unique_ptr MCIP; - std::unique_ptr File; + const Backend &B; + llvm::MCInstPrinter &MCIP; + llvm::SmallVector, 8> Views; - std::unique_ptr RPV; - std::unique_ptr TV; - std::unique_ptr BS; - - using Histogram = std::map; - void printDUStatistics(const Histogram &Stats, unsigned Cycles) const; - void printDispatchStalls(unsigned RATStalls, unsigned RCUStalls, - unsigned SQStalls, unsigned LDQStalls, - unsigned STQStalls, unsigned DGStalls) const; - void printRATStatistics(unsigned Mappings, unsigned MaxUsedMappings) const; - void printRCUStatistics(const Histogram &Histogram, unsigned Cycles) const; - void printIssuePerCycle(const Histogram &IssuePerCycle, - unsigned TotalCycles) const; - void printSchedulerUsage(const llvm::MCSchedModel &SM, - const llvm::ArrayRef &Usage) const; - void printGeneralStatistics(unsigned Iterations, unsigned Cycles, + void printGeneralStatistics(llvm::raw_ostream &OS, + unsigned Iterations, unsigned Cycles, unsigned Instructions, unsigned DispatchWidth) const; - void printInstructionInfo() const; - - std::unique_ptr getOutputStream(std::string OutputFile); - void initialize(std::string OputputFileName); + void printInstructionInfo(llvm::raw_ostream &OS) const; public: - BackendPrinter(Backend &backend, std::string OutputFileName, - std::unique_ptr IP, bool EnableVerbose) - : B(backend), EnableVerboseOutput(EnableVerbose), MCIP(std::move(IP)) { - initialize(OutputFileName); - } - - ~BackendPrinter() { - if (File) - File->keep(); - } - - bool isFileValid() const { return File.get(); } - llvm::raw_ostream &getOStream() const { - assert(isFileValid()); - return File->os(); - } - - llvm::MCInstPrinter &getMCInstPrinter() const { return *MCIP; } + BackendPrinter(const Backend &backend, llvm::MCInstPrinter &IP) + : B(backend), MCIP(IP) {} - void addResourcePressureView(); - void addTimelineView(unsigned MaxIterations = 3, unsigned MaxCycles = 80); + llvm::MCInstPrinter &getMCInstPrinter() const { return MCIP; } - void printReport() const; + void addView(std::unique_ptr V) { Views.emplace_back(std::move(V)); } + void printReport(llvm::raw_ostream &OS) const; }; } // namespace mca diff --git a/llvm/tools/llvm-mca/BackendStatistics.cpp b/llvm/tools/llvm-mca/BackendStatistics.cpp index 8a848cb..b3532c7 100644 --- a/llvm/tools/llvm-mca/BackendStatistics.cpp +++ b/llvm/tools/llvm-mca/BackendStatistics.cpp @@ -75,5 +75,64 @@ void BackendStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const { OS << Buffer; } +void BackendStatistics::printRATStatistics(raw_ostream &OS, + unsigned TotalMappings, + unsigned MaxUsedMappings) const { + std::string Buffer; + raw_string_ostream TempStream(Buffer); + TempStream << "\n\nRegister Alias Table:"; + TempStream << "\nTotal number of mappings created: " << TotalMappings; + TempStream << "\nMax number of mappings used: " << MaxUsedMappings + << '\n'; + TempStream.flush(); + OS << Buffer; +} + +void BackendStatistics::printDispatchStalls(raw_ostream &OS, + unsigned RATStalls, unsigned RCUStalls, + unsigned SCHEDQStalls, + unsigned LDQStalls, unsigned STQStalls, + unsigned DGStalls) const { + std::string Buffer; + raw_string_ostream TempStream(Buffer); + TempStream << "\n\nDynamic Dispatch Stall Cycles:\n"; + TempStream << "RAT - Register unavailable: " + << RATStalls; + TempStream << "\nRCU - Retire tokens unavailable: " + << RCUStalls; + TempStream << "\nSCHEDQ - Scheduler full: " + << SCHEDQStalls; + TempStream << "\nLQ - Load queue full: " + << LDQStalls; + TempStream << "\nSQ - Store queue full: " + << STQStalls; + TempStream << "\nGROUP - Static restrictions on the dispatch group: " + << DGStalls; + TempStream << '\n'; + TempStream.flush(); + OS << Buffer; +} + +void BackendStatistics::printSchedulerUsage(raw_ostream &OS, + const MCSchedModel &SM, const ArrayRef &Usage) const { + std::string Buffer; + raw_string_ostream TempStream(Buffer); + TempStream << "\n\nScheduler's queue usage:\n"; + const ArrayRef ResourceMasks = B.getProcResourceMasks(); + for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) { + const MCProcResourceDesc &ProcResource = *SM.getProcResource(I); + if (!ProcResource.BufferSize) + continue; + + for (const BufferUsageEntry &Entry : Usage) + if (ResourceMasks[I] == Entry.first) + TempStream << ProcResource.Name << ", " << Entry.second << '/' + << ProcResource.BufferSize << '\n'; + } + + TempStream.flush(); + OS << Buffer; +} + } // namespace mca diff --git a/llvm/tools/llvm-mca/BackendStatistics.h b/llvm/tools/llvm-mca/BackendStatistics.h index ac15ed2..7d79d24 100644 --- a/llvm/tools/llvm-mca/BackendStatistics.h +++ b/llvm/tools/llvm-mca/BackendStatistics.h @@ -14,6 +14,20 @@ /// Example: /// ======== /// +/// Dynamic Dispatch Stall Cycles: +/// RAT - Register unavailable: 0 +/// RCU - Retire tokens unavailable: 0 +/// SCHEDQ - Scheduler full: 42 +/// LQ - Load queue full: 0 +/// SQ - Store queue full: 0 +/// GROUP - Static restrictions on the dispatch group: 0 +/// +/// +/// Register Alias Table: +/// Total number of mappings created: 210 +/// Max number of mappings used: 35 +/// +/// /// Dispatch Logic - number of cycles where we saw N instructions dispatched: /// [# dispatched], [# cycles] /// 0, 15 (11.5%) @@ -32,18 +46,28 @@ /// 2, 1 (0.8%) /// 4, 3 (2.3%) /// +/// +/// Scheduler's queue usage: +/// JALU01, 0/20 +/// JFPU01, 18/18 +/// JLSAGU, 0/12 +/// //===----------------------------------------------------------------------===// #ifndef LLVM_TOOLS_LLVM_MCA_BACKENDSTATISTICS_H #define LLVM_TOOLS_LLVM_MCA_BACKENDSTATISTICS_H -#include "HWEventListener.h" +#include "Backend.h" +#include "View.h" #include "llvm/Support/raw_ostream.h" #include namespace mca { -class BackendStatistics : public HWEventListener { +class BackendStatistics : public View { + // TODO: remove the dependency from Backend. + const Backend &B; + using Histogram = std::map; Histogram DispatchGroupSizePerCycle; Histogram RetiredPerCycle; @@ -67,8 +91,24 @@ class BackendStatistics : public HWEventListener { void printDispatchUnitStatistics(llvm::raw_ostream &OS) const; void printSchedulerStatistics(llvm::raw_ostream &OS) const; + void printDispatchStalls(llvm::raw_ostream &OS, unsigned RATStalls, + unsigned RCUStalls, unsigned SQStalls, + unsigned LDQStalls, unsigned STQStalls, + unsigned DGStalls) const; + void printRATStatistics(llvm::raw_ostream &OS, unsigned Mappings, + unsigned MaxUsedMappings) const; + void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram, + unsigned Cycles) const; + void printDispatchUnitUsage(llvm::raw_ostream &OS, const Histogram &Stats, + unsigned Cycles) const; + void printIssuePerCycle(const Histogram &IssuePerCycle, + unsigned TotalCycles) const; + void printSchedulerUsage(llvm::raw_ostream &OS, const llvm::MCSchedModel &SM, + const llvm::ArrayRef &Usage) const; + public: - BackendStatistics() : NumDispatched(0), NumIssued(0), NumRetired(0) {} + BackendStatistics(const Backend &backend) + : B(backend), NumDispatched(0), NumIssued(0), NumRetired(0) {} void onInstructionDispatched(unsigned Index) override { NumDispatched++; } void @@ -83,10 +123,18 @@ public: void onCycleEnd(unsigned Cycle) override { updateHistograms(); } - void printHistograms(llvm::raw_ostream &OS) { + void printView(llvm::raw_ostream &OS) const override { + printDispatchStalls(OS, B.getNumRATStalls(), B.getNumRCUStalls(), B.getNumSQStalls(), + B.getNumLDQStalls(), B.getNumSTQStalls(), B.getNumDispatchGroupStalls()); + printRATStatistics(OS, B.getTotalRegisterMappingsCreated(), + B.getMaxUsedRegisterMappings()); printDispatchUnitStatistics(OS); printSchedulerStatistics(OS); printRetireUnitStatistics(OS); + + std::vector Usage; + B.getBuffersUsage(Usage); + printSchedulerUsage(OS, B.getSchedModel(), Usage); } }; diff --git a/llvm/tools/llvm-mca/CMakeLists.txt b/llvm/tools/llvm-mca/CMakeLists.txt index 348f00f..e6a7435 100644 --- a/llvm/tools/llvm-mca/CMakeLists.txt +++ b/llvm/tools/llvm-mca/CMakeLists.txt @@ -22,4 +22,5 @@ add_llvm_tool(llvm-mca ResourcePressureView.cpp Scheduler.cpp TimelineView.cpp + View.cpp ) diff --git a/llvm/tools/llvm-mca/HWEventListener.h b/llvm/tools/llvm-mca/HWEventListener.h index ba9d326..d3a3229 100644 --- a/llvm/tools/llvm-mca/HWEventListener.h +++ b/llvm/tools/llvm-mca/HWEventListener.h @@ -21,7 +21,8 @@ namespace mca { -struct HWEventListener { +class HWEventListener { +public: // Events generated by the Retire Control Unit. virtual void onInstructionRetired(unsigned Index) {}; diff --git a/llvm/tools/llvm-mca/ResourcePressureView.h b/llvm/tools/llvm-mca/ResourcePressureView.h index 7017f0b..ad8c1b7 100644 --- a/llvm/tools/llvm-mca/ResourcePressureView.h +++ b/llvm/tools/llvm-mca/ResourcePressureView.h @@ -58,7 +58,7 @@ #ifndef LLVM_TOOLS_LLVM_MCA_RESOURCEPRESSUREVIEW_H #define LLVM_TOOLS_LLVM_MCA_RESOURCEPRESSUREVIEW_H -#include "HWEventListener.h" +#include "View.h" #include "SourceMgr.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -70,7 +70,7 @@ class Backend; /// 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 HWEventListener { +class ResourcePressureView : public View { const llvm::MCSubtargetInfo &STI; llvm::MCInstPrinter &MCIP; const SourceMgr &Source; @@ -101,7 +101,7 @@ public: unsigned Index, const llvm::ArrayRef> &Used) override; - void printResourcePressure(llvm::raw_ostream &OS, unsigned Cycles) const { + void printView(llvm::raw_ostream &OS) const { unsigned Executions = Source.getNumIterations(); printResourcePressurePerIteration(OS, Executions); printResourcePressurePerInstruction(OS, Executions); diff --git a/llvm/tools/llvm-mca/TimelineView.h b/llvm/tools/llvm-mca/TimelineView.h index ac1ccd1..9ce2804 100644 --- a/llvm/tools/llvm-mca/TimelineView.h +++ b/llvm/tools/llvm-mca/TimelineView.h @@ -100,7 +100,7 @@ #ifndef LLVM_TOOLS_LLVM_MCA_TIMELINEVIEW_H #define LLVM_TOOLS_LLVM_MCA_TIMELINEVIEW_H -#include "HWEventListener.h" +#include "View.h" #include "SourceMgr.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -116,7 +116,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 HWEventListener { +class TimelineView : public View { const llvm::MCSubtargetInfo &STI; llvm::MCInstPrinter &MCIP; const SourceMgr &AsmSequence; @@ -174,6 +174,10 @@ public: // print functionalities. void printTimeline(llvm::raw_ostream &OS) const; void printAverageWaitTimes(llvm::raw_ostream &OS) const; + void printView(llvm::raw_ostream &OS) const override { + printTimeline(OS); + printAverageWaitTimes(OS); + } }; } // namespace mca diff --git a/llvm/tools/llvm-mca/View.cpp b/llvm/tools/llvm-mca/View.cpp new file mode 100644 index 0000000..1b54e4e --- /dev/null +++ b/llvm/tools/llvm-mca/View.cpp @@ -0,0 +1,21 @@ +//===----------------------- View.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines the virtual anchor method in View.h to pin the vtable. +/// +//===----------------------------------------------------------------------===// + +#include "View.h" + +namespace mca { + +void View::anchor() {} + +} // namespace mca diff --git a/llvm/tools/llvm-mca/View.h b/llvm/tools/llvm-mca/View.h new file mode 100644 index 0000000..e5d22866 --- /dev/null +++ b/llvm/tools/llvm-mca/View.h @@ -0,0 +1,33 @@ +//===----------------------- View.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file defines the main interface for Views. Each view contributes a +/// portion of the final report generated by the tool. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_VIEW_H +#define LLVM_TOOLS_LLVM_MCA_VIEW_H + +#include "HWEventListener.h" +#include "llvm/Support/raw_ostream.h" + +namespace mca { + +class View : public HWEventListener { +public: + virtual void printView(llvm::raw_ostream &OS) const = 0; + virtual ~View() = default; + void anchor() override; +}; + +} + +#endif diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 824a959..d7ffb2f 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -21,7 +21,6 @@ // //===----------------------------------------------------------------------===// -#include "BackendPrinter.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" @@ -29,12 +28,20 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ToolOutputFile.h" +#include "BackendPrinter.h" +#include "BackendStatistics.h" +#include "ResourcePressureView.h" +#include "TimelineView.h" + using namespace llvm; @@ -51,7 +58,7 @@ static cl::opt static cl::opt TripleName("mtriple", cl::desc("Target triple to assemble for, " - "see -version for available targets")); + "see -version for available targets")); static cl::opt MCPU("mcpu", @@ -101,10 +108,10 @@ static cl::opt PrintModeVerbose("verbose", cl::desc("Enable verbose output"), cl::init(false)); -static cl::opt - AssumeNoAlias("noalias", - cl::desc("If set, it assumes that loads and stores do not alias"), - cl::init(true)); +static cl::opt AssumeNoAlias( + "noalias", + cl::desc("If set, it assumes that loads and stores do not alias"), + cl::init(true)); static cl::opt LoadQueueSize("lqueue", cl::desc("Size of the load queue"), cl::init(0)); @@ -148,6 +155,17 @@ static int AssembleInput(const char *ProgName, const Target *TheTarget, return Parser->Run(false); } +static ErrorOr> getOutputStream() { + if (OutputFilename == "") + OutputFilename = "-"; + std::error_code EC; + auto Out = + llvm::make_unique(OutputFilename, EC, sys::fs::F_None); + if (!EC) + return std::move(Out); + return EC; +} + namespace { class MCStreamerWrapper final : public MCStreamer { @@ -284,6 +302,15 @@ int main(int argc, char **argv) { return 1; } + // Now initialize the output file. + auto OF = getOutputStream(); + if (std::error_code EC = OF.getError()) { + errs() << EC.message() << '\n'; + return 1; + } + + std::unique_ptr TOF = std::move(*OF); + const MCSchedModel &SM = STI->getSchedModel(); unsigned Width = SM.IssueWidth; @@ -291,17 +318,36 @@ int main(int argc, char **argv) { Width = DispatchWidth; std::unique_ptr B = llvm::make_unique( - *STI, *MCII, *MRI, std::move(S), Width, RegisterFileSize, MaxRetirePerCycle, + *STI, *MCII, *MRI, *S, Width, RegisterFileSize, MaxRetirePerCycle, LoadQueueSize, StoreQueueSize, AssumeNoAlias); std::unique_ptr Printer = - llvm::make_unique(*B, OutputFilename, std::move(IP), - PrintModeVerbose); - Printer->addResourcePressureView(); - if (PrintTimelineView) - Printer->addTimelineView(TimelineMaxIterations, TimelineMaxCycles); + llvm::make_unique(*B, *IP); + + if (PrintModeVerbose) { + std::unique_ptr BS = + llvm::make_unique(*B); + B->addEventListener(BS.get()); + Printer->addView(std::move(BS)); + } + + std::unique_ptr RPV = + llvm::make_unique(*STI, *IP, *S, + B->getProcResourceMasks()); + B->addEventListener(RPV.get()); + Printer->addView(std::move(RPV)); + + if (PrintTimelineView) { + std::unique_ptr TV = + llvm::make_unique( + *STI, *IP, *S, TimelineMaxIterations, TimelineMaxCycles); + B->addEventListener(TV.get()); + Printer->addView(std::move(TV)); + } B->run(); - Printer->printReport(); + Printer->printReport(TOF->os()); + TOF->keep(); + return 0; } -- 2.7.4