diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:51:42 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-10-23 17:51:42 +0000 |
commit | 1d5ae1026e831016fc29fd927877c86af904481f (patch) | |
tree | 2cdfd12620fcfa5d9e4a0389f85368e8e36f63f9 /tools/llvm-mca | |
parent | e6d1592492a3a379186bfb02bd0f4eda0669c0d5 (diff) |
Notes
Diffstat (limited to 'tools/llvm-mca')
-rw-r--r-- | tools/llvm-mca/CodeRegion.cpp | 6 | ||||
-rw-r--r-- | tools/llvm-mca/CodeRegionGenerator.cpp | 2 | ||||
-rw-r--r-- | tools/llvm-mca/Views/BottleneckAnalysis.cpp | 40 | ||||
-rw-r--r-- | tools/llvm-mca/Views/BottleneckAnalysis.h | 8 | ||||
-rw-r--r-- | tools/llvm-mca/Views/InstructionInfoView.cpp | 31 | ||||
-rw-r--r-- | tools/llvm-mca/Views/InstructionInfoView.h | 13 | ||||
-rw-r--r-- | tools/llvm-mca/Views/TimelineView.cpp | 50 | ||||
-rw-r--r-- | tools/llvm-mca/Views/TimelineView.h | 1 | ||||
-rw-r--r-- | tools/llvm-mca/llvm-mca.cpp | 113 |
9 files changed, 193 insertions, 71 deletions
diff --git a/tools/llvm-mca/CodeRegion.cpp b/tools/llvm-mca/CodeRegion.cpp index bf592f67245e..e05517c1ac95 100644 --- a/tools/llvm-mca/CodeRegion.cpp +++ b/tools/llvm-mca/CodeRegion.cpp @@ -18,7 +18,7 @@ namespace mca { CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) { // Create a default region for the input code sequence. - Regions.emplace_back(make_unique<CodeRegion>("", SMLoc())); + Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc())); } bool CodeRegion::isLocInRange(SMLoc Loc) const { @@ -36,7 +36,7 @@ void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) { if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) { ActiveRegions[Description] = 0; - Regions[0] = make_unique<CodeRegion>(Description, Loc); + Regions[0] = std::make_unique<CodeRegion>(Description, Loc); return; } } else { @@ -62,7 +62,7 @@ void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) { } ActiveRegions[Description] = Regions.size(); - Regions.emplace_back(make_unique<CodeRegion>(Description, Loc)); + Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc)); return; } diff --git a/tools/llvm-mca/CodeRegionGenerator.cpp b/tools/llvm-mca/CodeRegionGenerator.cpp index c793169e64e0..8ddcd2f4abe2 100644 --- a/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/tools/llvm-mca/CodeRegionGenerator.cpp @@ -118,6 +118,8 @@ Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions() { MCAsmLexer &Lexer = Parser->getLexer(); MCACommentConsumer CC(Regions); Lexer.setCommentConsumer(&CC); + // Enable support for MASM literal numbers (example: 05h, 101b). + Lexer.setLexMasmIntegers(true); std::unique_ptr<MCTargetAsmParser> TAP( TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts)); diff --git a/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/tools/llvm-mca/Views/BottleneckAnalysis.cpp index 560c6c6e8a33..feff0cd6d524 100644 --- a/tools/llvm-mca/Views/BottleneckAnalysis.cpp +++ b/tools/llvm-mca/Views/BottleneckAnalysis.cpp @@ -165,10 +165,33 @@ void DependencyGraph::dumpDependencyEdge(raw_ostream &OS, "Unsupported dependency type!"); OS << " - RESOURCE MASK: " << DE.ResourceOrRegID; } - OS << " - CYCLES: " << DE.Cost << '\n'; + OS << " - COST: " << DE.Cost << '\n'; } #endif // NDEBUG +void DependencyGraph::pruneEdges(unsigned Iterations) { + for (DGNode &N : Nodes) { + unsigned NumPruned = 0; + const unsigned Size = N.OutgoingEdges.size(); + // Use a cut-off threshold to prune edges with a low frequency. + for (unsigned I = 0, E = Size; I < E; ++I) { + DependencyEdge &Edge = N.OutgoingEdges[I]; + if (Edge.Frequency == Iterations) + continue; + double Factor = (double)Edge.Frequency / Iterations; + if (0.10 < Factor) + continue; + Nodes[Edge.ToIID].NumPredecessors--; + std::swap(Edge, N.OutgoingEdges[E - 1]); + --E; + ++NumPruned; + } + + if (NumPruned) + N.OutgoingEdges.resize(Size - NumPruned); + } +} + void DependencyGraph::initializeRootSet( SmallVectorImpl<unsigned> &RootSet) const { for (unsigned I = 0, E = Nodes.size(); I < E; ++I) { @@ -179,7 +202,7 @@ void DependencyGraph::initializeRootSet( } void DependencyGraph::propagateThroughEdges( - SmallVectorImpl<unsigned> &RootSet) { + SmallVectorImpl<unsigned> &RootSet, unsigned Iterations) { SmallVector<unsigned, 8> ToVisit; // A critical sequence is computed as the longest path from a node of the @@ -189,6 +212,10 @@ void DependencyGraph::propagateThroughEdges( // Each node of the graph starts with an initial default cost of zero. The // cost of a node is a measure of criticality: the higher the cost, the bigger // is the performance impact. + // For register and memory dependencies, the cost is a function of the write + // latency as well as the actual delay (in cycles) caused to users. + // For processor resource dependencies, the cost is a function of the resource + // pressure. Resource interferences with low frequency values are ignored. // // This algorithm is very similar to a (reverse) Dijkstra. Every iteration of // the inner loop selects (i.e. visits) a node N from a set of `unvisited @@ -277,6 +304,10 @@ static void printInstruction(formatted_raw_ostream &FOS, } void BottleneckAnalysis::printCriticalSequence(raw_ostream &OS) const { + // Early exit if no bottlenecks were found during the simulation. + if (!SeenStallCycles || !BPI.PressureIncreaseCycles) + return; + SmallVector<const DependencyEdge *, 16> Seq; DG.getCriticalSequence(Seq); if (Seq.empty()) @@ -432,7 +463,6 @@ void BottleneckAnalysis::addRegisterDep(unsigned From, unsigned To, bool IsLoopCarried = From >= To; unsigned SourceSize = Source.size(); if (IsLoopCarried) { - Cost *= Iterations / 2; DG.addRegisterDep(From, To + SourceSize, RegID, Cost); DG.addRegisterDep(From + SourceSize, To + (SourceSize * 2), RegID, Cost); return; @@ -445,7 +475,6 @@ void BottleneckAnalysis::addMemoryDep(unsigned From, unsigned To, bool IsLoopCarried = From >= To; unsigned SourceSize = Source.size(); if (IsLoopCarried) { - Cost *= Iterations / 2; DG.addMemoryDep(From, To + SourceSize, Cost); DG.addMemoryDep(From + SourceSize, To + (SourceSize * 2), Cost); return; @@ -458,7 +487,6 @@ void BottleneckAnalysis::addResourceDep(unsigned From, unsigned To, bool IsLoopCarried = From >= To; unsigned SourceSize = Source.size(); if (IsLoopCarried) { - Cost *= Iterations / 2; DG.addResourceDep(From, To + SourceSize, Mask, Cost); DG.addResourceDep(From + SourceSize, To + (SourceSize * 2), Mask, Cost); return; @@ -514,7 +542,7 @@ void BottleneckAnalysis::onEvent(const HWInstructionEvent &Event) { // Check if this is the last simulated instruction. if (IID == ((Iterations * Source.size()) - 1)) - DG.finalizeGraph(); + DG.finalizeGraph(Iterations); } void BottleneckAnalysis::onEvent(const HWPressureEvent &Event) { diff --git a/tools/llvm-mca/Views/BottleneckAnalysis.h b/tools/llvm-mca/Views/BottleneckAnalysis.h index 7564b1a48206..9e3bd5978f09 100644 --- a/tools/llvm-mca/Views/BottleneckAnalysis.h +++ b/tools/llvm-mca/Views/BottleneckAnalysis.h @@ -236,8 +236,9 @@ class DependencyGraph { void addDependency(unsigned From, unsigned To, DependencyEdge::Dependency &&DE); + void pruneEdges(unsigned Iterations); void initializeRootSet(SmallVectorImpl<unsigned> &RootSet) const; - void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet); + void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet, unsigned Iterations); #ifndef NDEBUG void dumpDependencyEdge(raw_ostream &OS, const DependencyEdge &DE, @@ -263,10 +264,11 @@ public: // Called by the bottleneck analysis at the end of simulation to propagate // costs through the edges of the graph, and compute a critical path. - void finalizeGraph() { + void finalizeGraph(unsigned Iterations) { SmallVector<unsigned, 16> RootSet; + pruneEdges(Iterations); initializeRootSet(RootSet); - propagateThroughEdges(RootSet); + propagateThroughEdges(RootSet, Iterations); } // Returns a sequence of edges representing the critical sequence based on the diff --git a/tools/llvm-mca/Views/InstructionInfoView.cpp b/tools/llvm-mca/Views/InstructionInfoView.cpp index 1fbffa3e5b69..a6f9153b4945 100644 --- a/tools/llvm-mca/Views/InstructionInfoView.cpp +++ b/tools/llvm-mca/Views/InstructionInfoView.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Views/InstructionInfoView.h" +#include "llvm/Support/FormattedStream.h" namespace llvm { namespace mca { @@ -26,10 +27,17 @@ void InstructionInfoView::printView(raw_ostream &OS) const { TempStream << "\n\nInstruction Info:\n"; TempStream << "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n" - << "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n\n"; + << "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n"; + if (PrintEncodings) { + TempStream << "[7]: Encoding Size\n"; + TempStream << "\n[1] [2] [3] [4] [5] [6] [7] " + << "Encodings: Instructions:\n"; + } else { + TempStream << "\n[1] [2] [3] [4] [5] [6] Instructions:\n"; + } - TempStream << "[1] [2] [3] [4] [5] [6] Instructions:\n"; - for (const MCInst &Inst : Source) { + for (unsigned I = 0, E = Source.size(); I < E; ++I) { + const MCInst &Inst = Source[I]; const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode()); // Obtain the scheduling class information from the instruction. @@ -72,7 +80,20 @@ void InstructionInfoView::printView(raw_ostream &OS) const { } TempStream << (MCDesc.mayLoad() ? " * " : " "); TempStream << (MCDesc.mayStore() ? " * " : " "); - TempStream << (MCDesc.hasUnmodeledSideEffects() ? " U " : " "); + TempStream << (MCDesc.hasUnmodeledSideEffects() ? " U " : " "); + + if (PrintEncodings) { + StringRef Encoding(CE.getEncoding(I)); + unsigned EncodingSize = Encoding.size(); + TempStream << " " << EncodingSize + << (EncodingSize < 10 ? " " : " "); + TempStream.flush(); + formatted_raw_ostream FOS(TempStream); + for (unsigned i = 0, e = Encoding.size(); i != e; ++i) + FOS << format("%02x ", (uint8_t)Encoding[i]); + FOS.PadToColumn(30); + FOS.flush(); + } MCIP.printInst(&Inst, InstrStream, "", STI); InstrStream.flush(); @@ -80,7 +101,7 @@ void InstructionInfoView::printView(raw_ostream &OS) const { // Consume any tabs or spaces at the beginning of the string. StringRef Str(Instruction); Str = Str.ltrim(); - TempStream << " " << Str << '\n'; + TempStream << Str << '\n'; Instruction = ""; } diff --git a/tools/llvm-mca/Views/InstructionInfoView.h b/tools/llvm-mca/Views/InstructionInfoView.h index 640d87383436..0e948304119f 100644 --- a/tools/llvm-mca/Views/InstructionInfoView.h +++ b/tools/llvm-mca/Views/InstructionInfoView.h @@ -40,6 +40,7 @@ #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MCA/CodeEmitter.h" #include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "llvm-mca" @@ -51,14 +52,18 @@ namespace mca { class InstructionInfoView : public View { const llvm::MCSubtargetInfo &STI; const llvm::MCInstrInfo &MCII; + CodeEmitter &CE; + bool PrintEncodings; llvm::ArrayRef<llvm::MCInst> Source; llvm::MCInstPrinter &MCIP; public: - InstructionInfoView(const llvm::MCSubtargetInfo &sti, - const llvm::MCInstrInfo &mcii, - llvm::ArrayRef<llvm::MCInst> S, llvm::MCInstPrinter &IP) - : STI(sti), MCII(mcii), Source(S), MCIP(IP) {} + InstructionInfoView(const llvm::MCSubtargetInfo &ST, + const llvm::MCInstrInfo &II, CodeEmitter &C, + bool ShouldPrintEncodings, llvm::ArrayRef<llvm::MCInst> S, + llvm::MCInstPrinter &IP) + : STI(ST), MCII(II), CE(C), PrintEncodings(ShouldPrintEncodings), + Source(S), MCIP(IP) {} void printView(llvm::raw_ostream &OS) const override; }; diff --git a/tools/llvm-mca/Views/TimelineView.cpp b/tools/llvm-mca/Views/TimelineView.cpp index fe3f16ba344c..1e7caa297ac6 100644 --- a/tools/llvm-mca/Views/TimelineView.cpp +++ b/tools/llvm-mca/Views/TimelineView.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Views/TimelineView.h" +#include <numeric> namespace llvm { namespace mca { @@ -132,25 +133,38 @@ void TimelineView::printWaitTimeEntry(formatted_raw_ostream &OS, const WaitTimeEntry &Entry, unsigned SourceIndex, unsigned Executions) const { - OS << SourceIndex << '.'; + bool PrintingTotals = SourceIndex == Source.size(); + unsigned CumulativeExecutions = PrintingTotals ? Timeline.size() : Executions; + + if (!PrintingTotals) + OS << SourceIndex << '.'; + OS.PadToColumn(7); double AverageTime1, AverageTime2, AverageTime3; - AverageTime1 = (double)Entry.CyclesSpentInSchedulerQueue / Executions; - AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / Executions; - AverageTime3 = (double)Entry.CyclesSpentAfterWBAndBeforeRetire / Executions; + AverageTime1 = + (double)Entry.CyclesSpentInSchedulerQueue / CumulativeExecutions; + AverageTime2 = (double)Entry.CyclesSpentInSQWhileReady / CumulativeExecutions; + AverageTime3 = + (double)Entry.CyclesSpentAfterWBAndBeforeRetire / CumulativeExecutions; OS << Executions; OS.PadToColumn(13); - int BufferSize = UsedBuffer[SourceIndex].second; - tryChangeColor(OS, Entry.CyclesSpentInSchedulerQueue, Executions, BufferSize); + + int BufferSize = PrintingTotals ? 0 : UsedBuffer[SourceIndex].second; + if (!PrintingTotals) + tryChangeColor(OS, Entry.CyclesSpentInSchedulerQueue, CumulativeExecutions, + BufferSize); OS << format("%.1f", floor((AverageTime1 * 10) + 0.5) / 10); OS.PadToColumn(20); - tryChangeColor(OS, Entry.CyclesSpentInSQWhileReady, Executions, BufferSize); + if (!PrintingTotals) + tryChangeColor(OS, Entry.CyclesSpentInSQWhileReady, CumulativeExecutions, + BufferSize); OS << format("%.1f", floor((AverageTime2 * 10) + 0.5) / 10); OS.PadToColumn(27); - tryChangeColor(OS, Entry.CyclesSpentAfterWBAndBeforeRetire, Executions, - STI.getSchedModel().MicroOpBufferSize); + if (!PrintingTotals) + tryChangeColor(OS, Entry.CyclesSpentAfterWBAndBeforeRetire, + CumulativeExecutions, STI.getSchedModel().MicroOpBufferSize); OS << format("%.1f", floor((AverageTime3 * 10) + 0.5) / 10); if (OS.has_colors()) @@ -190,6 +204,24 @@ void TimelineView::printAverageWaitTimes(raw_ostream &OS) const { ++IID; } + + // If the timeline contains more than one instruction, + // let's also print global averages. + if (Source.size() != 1) { + WaitTimeEntry TotalWaitTime = std::accumulate( + WaitTime.begin(), WaitTime.end(), WaitTimeEntry{0, 0, 0}, + [](const WaitTimeEntry &A, const WaitTimeEntry &B) { + return WaitTimeEntry{ + A.CyclesSpentInSchedulerQueue + B.CyclesSpentInSchedulerQueue, + A.CyclesSpentInSQWhileReady + B.CyclesSpentInSQWhileReady, + A.CyclesSpentAfterWBAndBeforeRetire + + B.CyclesSpentAfterWBAndBeforeRetire}; + }); + printWaitTimeEntry(FOS, TotalWaitTime, IID, Executions); + FOS << " " + << "<total>" << '\n'; + InstrStream.flush(); + } } void TimelineView::printTimelineViewEntry(formatted_raw_ostream &OS, diff --git a/tools/llvm-mca/Views/TimelineView.h b/tools/llvm-mca/Views/TimelineView.h index b63b234293cd..9bec3b87db45 100644 --- a/tools/llvm-mca/Views/TimelineView.h +++ b/tools/llvm-mca/Views/TimelineView.h @@ -84,6 +84,7 @@ /// 3. 2 1.5 0.5 1.0 vaddss %xmm1, %xmm0, %xmm3 /// 4. 2 3.5 0.0 0.0 vaddss %xmm3, %xmm2, %xmm4 /// 5. 2 6.5 0.0 0.0 vaddss %xmm4, %xmm5, %xmm6 +/// 2 2.4 0.6 1.6 <total> /// /// By comparing column [2] with column [1], we get an idea about how many /// cycles were spent in the scheduler's queue due to data dependencies. diff --git a/tools/llvm-mca/llvm-mca.cpp b/tools/llvm-mca/llvm-mca.cpp index b3590b5910ec..99c45eebdd88 100644 --- a/tools/llvm-mca/llvm-mca.cpp +++ b/tools/llvm-mca/llvm-mca.cpp @@ -32,11 +32,17 @@ #include "Views/SchedulerStatistics.h" #include "Views/SummaryView.h" #include "Views/TimelineView.h" +#include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCTargetOptionsCommandFlags.inc" +#include "llvm/MCA/CodeEmitter.h" #include "llvm/MCA/Context.h" +#include "llvm/MCA/InstrBuilder.h" #include "llvm/MCA/Pipeline.h" #include "llvm/MCA/Stages/EntryStage.h" #include "llvm/MCA/Stages/InstructionTables.h" @@ -83,11 +89,20 @@ static cl::opt<std::string> cl::desc("Target a specific cpu type (-mcpu=help for details)"), cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native")); +static cl::opt<std::string> + MATTR("mattr", + cl::desc("Additional target features."), + cl::cat(ToolOptions)); + static cl::opt<int> OutputAsmVariant("output-asm-variant", cl::desc("Syntax variant to use for output printing"), cl::cat(ToolOptions), cl::init(-1)); +static cl::opt<bool> + PrintImmHex("print-imm-hex", cl::cat(ToolOptions), cl::init(false), + cl::desc("Prefer hex format when printing immediate values")); + static cl::opt<unsigned> Iterations("iterations", cl::desc("Number of iterations to run"), cl::cat(ToolOptions), cl::init(0)); @@ -193,6 +208,11 @@ static cl::opt<bool> EnableBottleneckAnalysis( cl::desc("Enable bottleneck analysis (disabled by default)"), cl::cat(ViewOptions), cl::init(false)); +static cl::opt<bool> ShowEncoding( + "show-encoding", + cl::desc("Print encoding information in the instruction info view"), + cl::cat(ViewOptions), cl::init(false)); + namespace { const Target *getTarget(const char *ProgName) { @@ -218,7 +238,7 @@ ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() { OutputFilename = "-"; std::error_code EC; auto Out = - llvm::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None); + std::make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::OF_Text); if (!EC) return std::move(Out); return EC; @@ -303,33 +323,11 @@ int main(int argc, char **argv) { // Apply overrides to llvm-mca specific options. processViewOptions(); - SourceMgr SrcMgr; - - // Tell SrcMgr about this buffer, which is what the parser will pick up. - SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); - - std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); - assert(MRI && "Unable to create target register info!"); - - std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); - assert(MAI && "Unable to create target asm info!"); - - MCObjectFileInfo MOFI; - MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); - MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx); - - std::unique_ptr<buffer_ostream> BOS; - - std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); - - std::unique_ptr<MCInstrAnalysis> MCIA( - TheTarget->createMCInstrAnalysis(MCII.get())); - if (!MCPU.compare("native")) MCPU = llvm::sys::getHostCPUName(); std::unique_ptr<MCSubtargetInfo> STI( - TheTarget->createMCSubtargetInfo(TripleName, MCPU, /* FeaturesStr */ "")); + TheTarget->createMCSubtargetInfo(TripleName, MCPU, MATTR)); if (!STI->isCPUStringValid(MCPU)) return 1; @@ -352,6 +350,29 @@ int main(int argc, char **argv) { return 1; } + std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName)); + assert(MRI && "Unable to create target register info!"); + + std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName)); + assert(MAI && "Unable to create target asm info!"); + + MCObjectFileInfo MOFI; + SourceMgr SrcMgr; + + // Tell SrcMgr about this buffer, which is what the parser will pick up. + SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc()); + + MCContext Ctx(MAI.get(), MRI.get(), &MOFI, &SrcMgr); + + MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx); + + std::unique_ptr<buffer_ostream> BOS; + + std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); + + std::unique_ptr<MCInstrAnalysis> MCIA( + TheTarget->createMCInstrAnalysis(MCII.get())); + // Parse the input and create CodeRegions that llvm-mca can analyze. mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII); Expected<const mca::CodeRegions &> RegionsOrErr = CRG.parseCodeRegions(); @@ -396,6 +417,9 @@ int main(int argc, char **argv) { return 1; } + // Set the display preference for hex vs. decimal immediates. + IP->setPrintImmHex(PrintImmHex); + std::unique_ptr<ToolOutputFile> TOF = std::move(*OF); const MCSchedModel &SM = STI->getSchedModel(); @@ -413,6 +437,12 @@ int main(int argc, char **argv) { // Number each region in the sequence. unsigned RegionIdx = 0; + std::unique_ptr<MCCodeEmitter> MCE( + TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); + + std::unique_ptr<MCAsmBackend> MAB(TheTarget->createMCAsmBackend( + *STI, *MRI, InitMCTargetOptionsFromFlags())); + for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) { // Skip empty code regions. if (Region->empty()) @@ -430,6 +460,7 @@ int main(int argc, char **argv) { // Lower the MCInst sequence into an mca::Instruction sequence. ArrayRef<MCInst> Insts = Region->getInstructions(); + mca::CodeEmitter CE(*STI, *MAB, *MCE, Insts); std::vector<std::unique_ptr<mca::Instruction>> LoweredSequence; for (const MCInst &MCI : Insts) { Expected<std::unique_ptr<mca::Instruction>> Inst = @@ -459,18 +490,18 @@ int main(int argc, char **argv) { if (PrintInstructionTables) { // Create a pipeline, stages, and a printer. - auto P = llvm::make_unique<mca::Pipeline>(); - P->appendStage(llvm::make_unique<mca::EntryStage>(S)); - P->appendStage(llvm::make_unique<mca::InstructionTables>(SM)); + auto P = std::make_unique<mca::Pipeline>(); + P->appendStage(std::make_unique<mca::EntryStage>(S)); + P->appendStage(std::make_unique<mca::InstructionTables>(SM)); mca::PipelinePrinter Printer(*P); // Create the views for this pipeline, execute, and emit a report. if (PrintInstructionInfoView) { - Printer.addView(llvm::make_unique<mca::InstructionInfoView>( - *STI, *MCII, Insts, *IP)); + Printer.addView(std::make_unique<mca::InstructionInfoView>( + *STI, *MCII, CE, ShowEncoding, Insts, *IP)); } Printer.addView( - llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); + std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); if (!runPipeline(*P)) return 1; @@ -480,42 +511,42 @@ int main(int argc, char **argv) { } // Create a basic pipeline simulating an out-of-order backend. - auto P = MCA.createDefaultPipeline(PO, IB, S); + auto P = MCA.createDefaultPipeline(PO, S); mca::PipelinePrinter Printer(*P); if (PrintSummaryView) Printer.addView( - llvm::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth)); + std::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth)); if (EnableBottleneckAnalysis) { - Printer.addView(llvm::make_unique<mca::BottleneckAnalysis>( + Printer.addView(std::make_unique<mca::BottleneckAnalysis>( *STI, *IP, Insts, S.getNumIterations())); } if (PrintInstructionInfoView) - Printer.addView( - llvm::make_unique<mca::InstructionInfoView>(*STI, *MCII, Insts, *IP)); + Printer.addView(std::make_unique<mca::InstructionInfoView>( + *STI, *MCII, CE, ShowEncoding, Insts, *IP)); if (PrintDispatchStats) - Printer.addView(llvm::make_unique<mca::DispatchStatistics>()); + Printer.addView(std::make_unique<mca::DispatchStatistics>()); if (PrintSchedulerStats) - Printer.addView(llvm::make_unique<mca::SchedulerStatistics>(*STI)); + Printer.addView(std::make_unique<mca::SchedulerStatistics>(*STI)); if (PrintRetireStats) - Printer.addView(llvm::make_unique<mca::RetireControlUnitStatistics>(SM)); + Printer.addView(std::make_unique<mca::RetireControlUnitStatistics>(SM)); if (PrintRegisterFileStats) - Printer.addView(llvm::make_unique<mca::RegisterFileStatistics>(*STI)); + Printer.addView(std::make_unique<mca::RegisterFileStatistics>(*STI)); if (PrintResourcePressureView) Printer.addView( - llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); + std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts)); if (PrintTimelineView) { unsigned TimelineIterations = TimelineMaxIterations ? TimelineMaxIterations : 10; - Printer.addView(llvm::make_unique<mca::TimelineView>( + Printer.addView(std::make_unique<mca::TimelineView>( *STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()), TimelineMaxCycles)); } |