[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:
Andrea Di Biagio 2018-03-08 16:08:43 +00:00
parent b312b13960
commit 8af3fe81eb
13 changed files with 280 additions and 217 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);
}
};

View File

@ -22,4 +22,5 @@ add_llvm_tool(llvm-mca
ResourcePressureView.cpp
Scheduler.cpp
TimelineView.cpp
View.cpp
)

View File

@ -21,7 +21,8 @@
namespace mca {
struct HWEventListener {
class HWEventListener {
public:
// Events generated by the Retire Control Unit.
virtual void onInstructionRetired(unsigned Index) {};

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}