forked from OSchip/llvm-project
[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
This commit is contained in:
parent
b312b13960
commit
8af3fe81eb
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class Backend {
|
|||
std::unique_ptr<InstrBuilder> IB;
|
||||
std::unique_ptr<Scheduler> HWS;
|
||||
std::unique_ptr<DispatchUnit> DU;
|
||||
std::unique_ptr<SourceMgr> SM;
|
||||
SourceMgr &SM;
|
||||
unsigned Cycles;
|
||||
|
||||
llvm::DenseMap<unsigned, std::unique_ptr<Instruction>> Instructions;
|
||||
|
@ -58,7 +58,7 @@ class Backend {
|
|||
|
||||
public:
|
||||
Backend(const llvm::MCSubtargetInfo &Subtarget, const llvm::MCInstrInfo &MCII,
|
||||
const llvm::MCRegisterInfo &MRI, std::unique_ptr<SourceMgr> 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<DispatchUnit>(
|
||||
this, MRI, Subtarget.getSchedModel().MicroOpBufferSize,
|
||||
RegisterFileSize, MaxRetirePerCycle, DispatchWidth, HWS.get())),
|
||||
SM(std::move(Source)), Cycles(0) {
|
||||
SM(Source), Cycles(0) {
|
||||
IB = llvm::make_unique<InstrBuilder>(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);
|
||||
|
|
|
@ -13,25 +13,15 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "BackendPrinter.h"
|
||||
#include "View.h"
|
||||
#include "llvm/CodeGen/TargetSchedule.h"
|
||||
|
||||
namespace mca {
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
std::unique_ptr<ToolOutputFile>
|
||||
BackendPrinter::getOutputStream(std::string OutputFile) {
|
||||
if (OutputFile == "")
|
||||
OutputFile = "-";
|
||||
std::error_code EC;
|
||||
auto Out = llvm::make_unique<ToolOutputFile>(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;
|
||||
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<BufferUsageEntry> &Usage) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nScheduler's queue usage:\n";
|
||||
const ArrayRef<uint64_t> 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;
|
||||
}
|
||||
|
||||
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<BufferUsageEntry> 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<ResourcePressureView>(
|
||||
B.getSTI(), *MCIP, B.getSourceMgr(), B.getProcResourceMasks());
|
||||
B.addEventListener(RPV.get());
|
||||
}
|
||||
}
|
||||
|
||||
void BackendPrinter::addTimelineView(unsigned MaxIterations,
|
||||
unsigned MaxCycles) {
|
||||
if (!TV) {
|
||||
TV = llvm::make_unique<TimelineView>(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<BackendStatistics>();
|
||||
B.addEventListener(BS.get());
|
||||
}
|
||||
for (const auto &V : Views)
|
||||
V->printView(OS);
|
||||
}
|
||||
|
||||
} // namespace mca.
|
||||
|
|
|
@ -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;
|
||||
const Backend &B;
|
||||
llvm::MCInstPrinter &MCIP;
|
||||
llvm::SmallVector<std::unique_ptr<View>, 8> Views;
|
||||
|
||||
std::unique_ptr<llvm::MCInstPrinter> MCIP;
|
||||
std::unique_ptr<llvm::ToolOutputFile> File;
|
||||
|
||||
std::unique_ptr<ResourcePressureView> RPV;
|
||||
std::unique_ptr<TimelineView> TV;
|
||||
std::unique_ptr<BackendStatistics> BS;
|
||||
|
||||
using Histogram = std::map<unsigned, unsigned>;
|
||||
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<BufferUsageEntry> &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<llvm::ToolOutputFile> 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<llvm::MCInstPrinter> IP, bool EnableVerbose)
|
||||
: B(backend), EnableVerboseOutput(EnableVerbose), MCIP(std::move(IP)) {
|
||||
initialize(OutputFileName);
|
||||
}
|
||||
BackendPrinter(const Backend &backend, llvm::MCInstPrinter &IP)
|
||||
: B(backend), MCIP(IP) {}
|
||||
|
||||
~BackendPrinter() {
|
||||
if (File)
|
||||
File->keep();
|
||||
}
|
||||
llvm::MCInstPrinter &getMCInstPrinter() const { return MCIP; }
|
||||
|
||||
bool isFileValid() const { return File.get(); }
|
||||
llvm::raw_ostream &getOStream() const {
|
||||
assert(isFileValid());
|
||||
return File->os();
|
||||
}
|
||||
|
||||
llvm::MCInstPrinter &getMCInstPrinter() const { return *MCIP; }
|
||||
|
||||
void addResourcePressureView();
|
||||
void addTimelineView(unsigned MaxIterations = 3, unsigned MaxCycles = 80);
|
||||
|
||||
void printReport() const;
|
||||
void addView(std::unique_ptr<View> V) { Views.emplace_back(std::move(V)); }
|
||||
void printReport(llvm::raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
} // namespace mca
|
||||
|
|
|
@ -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<BufferUsageEntry> &Usage) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nScheduler's queue usage:\n";
|
||||
const ArrayRef<uint64_t> 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
|
||||
|
||||
|
|
|
@ -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 <map>
|
||||
|
||||
namespace mca {
|
||||
|
||||
class BackendStatistics : public HWEventListener {
|
||||
class BackendStatistics : public View {
|
||||
// TODO: remove the dependency from Backend.
|
||||
const Backend &B;
|
||||
|
||||
using Histogram = std::map<unsigned, unsigned>;
|
||||
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<BufferUsageEntry> &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<BufferUsageEntry> Usage;
|
||||
B.getBuffersUsage(Usage);
|
||||
printSchedulerUsage(OS, B.getSchedModel(), Usage);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -22,4 +22,5 @@ add_llvm_tool(llvm-mca
|
|||
ResourcePressureView.cpp
|
||||
Scheduler.cpp
|
||||
TimelineView.cpp
|
||||
View.cpp
|
||||
)
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
|
||||
namespace mca {
|
||||
|
||||
struct HWEventListener {
|
||||
class HWEventListener {
|
||||
public:
|
||||
// Events generated by the Retire Control Unit.
|
||||
virtual void onInstructionRetired(unsigned Index) {};
|
||||
|
||||
|
|
|
@ -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<std::pair<ResourceRef, unsigned>> &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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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<std::string>
|
|||
|
||||
static cl::opt<std::string>
|
||||
TripleName("mtriple", cl::desc("Target triple to assemble for, "
|
||||
"see -version for available targets"));
|
||||
"see -version for available targets"));
|
||||
|
||||
static cl::opt<std::string>
|
||||
MCPU("mcpu",
|
||||
|
@ -101,10 +108,10 @@ static cl::opt<bool> PrintModeVerbose("verbose",
|
|||
cl::desc("Enable verbose output"),
|
||||
cl::init(false));
|
||||
|
||||
static cl::opt<bool>
|
||||
AssumeNoAlias("noalias",
|
||||
cl::desc("If set, it assumes that loads and stores do not alias"),
|
||||
cl::init(true));
|
||||
static cl::opt<bool> AssumeNoAlias(
|
||||
"noalias",
|
||||
cl::desc("If set, it assumes that loads and stores do not alias"),
|
||||
cl::init(true));
|
||||
|
||||
static cl::opt<unsigned>
|
||||
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<std::unique_ptr<ToolOutputFile>> getOutputStream() {
|
||||
if (OutputFilename == "")
|
||||
OutputFilename = "-";
|
||||
std::error_code EC;
|
||||
auto Out =
|
||||
llvm::make_unique<ToolOutputFile>(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<llvm::ToolOutputFile> 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<mca::Backend> B = llvm::make_unique<mca::Backend>(
|
||||
*STI, *MCII, *MRI, std::move(S), Width, RegisterFileSize, MaxRetirePerCycle,
|
||||
*STI, *MCII, *MRI, *S, Width, RegisterFileSize, MaxRetirePerCycle,
|
||||
LoadQueueSize, StoreQueueSize, AssumeNoAlias);
|
||||
|
||||
std::unique_ptr<mca::BackendPrinter> Printer =
|
||||
llvm::make_unique<mca::BackendPrinter>(*B, OutputFilename, std::move(IP),
|
||||
PrintModeVerbose);
|
||||
Printer->addResourcePressureView();
|
||||
if (PrintTimelineView)
|
||||
Printer->addTimelineView(TimelineMaxIterations, TimelineMaxCycles);
|
||||
llvm::make_unique<mca::BackendPrinter>(*B, *IP);
|
||||
|
||||
if (PrintModeVerbose) {
|
||||
std::unique_ptr<mca::BackendStatistics> BS =
|
||||
llvm::make_unique<mca::BackendStatistics>(*B);
|
||||
B->addEventListener(BS.get());
|
||||
Printer->addView(std::move(BS));
|
||||
}
|
||||
|
||||
std::unique_ptr<mca::ResourcePressureView> RPV =
|
||||
llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, *S,
|
||||
B->getProcResourceMasks());
|
||||
B->addEventListener(RPV.get());
|
||||
Printer->addView(std::move(RPV));
|
||||
|
||||
if (PrintTimelineView) {
|
||||
std::unique_ptr<mca::TimelineView> TV =
|
||||
llvm::make_unique<mca::TimelineView>(
|
||||
*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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue