2018-03-08 13:05:02 +00:00
|
|
|
//===-- llvm-mca.cpp - Machine Code Analyzer -------------------*- C++ -* -===//
|
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2018-03-08 13:05:02 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This utility is a simple driver that allows static performance analysis on
|
|
|
|
// machine code similarly to how IACA (Intel Architecture Code Analyzer) works.
|
|
|
|
//
|
|
|
|
// llvm-mca [options] <file-name>
|
|
|
|
// -march <type>
|
|
|
|
// -mcpu <cpu>
|
|
|
|
// -o <file>
|
|
|
|
//
|
|
|
|
// The target defaults to the host target.
|
2018-04-25 10:18:25 +00:00
|
|
|
// The cpu defaults to the 'native' host cpu.
|
2018-03-08 13:05:02 +00:00
|
|
|
// The output defaults to standard output.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
#include "CodeRegion.h"
|
2018-11-07 19:20:04 +00:00
|
|
|
#include "CodeRegionGenerator.h"
|
2018-06-25 16:53:00 +00:00
|
|
|
#include "PipelinePrinter.h"
|
2019-04-17 06:02:05 +00:00
|
|
|
#include "Views/BottleneckAnalysis.h"
|
2018-08-24 20:24:53 +00:00
|
|
|
#include "Views/DispatchStatistics.h"
|
|
|
|
#include "Views/InstructionInfoView.h"
|
|
|
|
#include "Views/RegisterFileStatistics.h"
|
|
|
|
#include "Views/ResourcePressureView.h"
|
|
|
|
#include "Views/RetireControlUnitStatistics.h"
|
|
|
|
#include "Views/SchedulerStatistics.h"
|
|
|
|
#include "Views/SummaryView.h"
|
|
|
|
#include "Views/TimelineView.h"
|
2019-08-09 11:26:27 +00:00
|
|
|
#include "llvm/MC/MCAsmBackend.h"
|
2018-03-08 13:05:02 +00:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2019-08-08 10:30:58 +00:00
|
|
|
#include "llvm/MC/MCCodeEmitter.h"
|
2019-08-09 11:26:27 +00:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2018-03-08 13:05:02 +00:00
|
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2019-08-08 10:30:58 +00:00
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2020-03-04 00:47:43 +01:00
|
|
|
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
|
2021-10-08 10:48:15 -07:00
|
|
|
#include "llvm/MC/TargetRegistry.h"
|
2019-08-09 11:26:27 +00:00
|
|
|
#include "llvm/MCA/CodeEmitter.h"
|
2018-12-17 08:08:31 +00:00
|
|
|
#include "llvm/MCA/Context.h"
|
2021-06-16 16:22:54 +01:00
|
|
|
#include "llvm/MCA/CustomBehaviour.h"
|
2019-08-08 10:30:58 +00:00
|
|
|
#include "llvm/MCA/InstrBuilder.h"
|
2018-12-17 08:08:31 +00:00
|
|
|
#include "llvm/MCA/Pipeline.h"
|
|
|
|
#include "llvm/MCA/Stages/EntryStage.h"
|
|
|
|
#include "llvm/MCA/Stages/InstructionTables.h"
|
|
|
|
#include "llvm/MCA/Support.h"
|
2018-03-08 13:05:02 +00:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2018-08-13 18:11:48 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2018-03-08 16:08:43 +00:00
|
|
|
#include "llvm/Support/ErrorOr.h"
|
|
|
|
#include "llvm/Support/FileSystem.h"
|
2018-04-13 18:26:06 +00:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2018-03-08 13:05:02 +00:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
#include "llvm/Support/TargetSelect.h"
|
2018-03-08 16:08:43 +00:00
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
2018-04-18 15:26:51 +00:00
|
|
|
#include "llvm/Support/WithColor.h"
|
2023-02-10 09:59:46 +00:00
|
|
|
#include "llvm/TargetParser/Host.h"
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2020-03-04 00:47:43 +01:00
|
|
|
static mc::RegisterMCTargetOptionsFlags MOF;
|
|
|
|
|
2018-05-17 15:35:14 +00:00
|
|
|
static cl::OptionCategory ToolOptions("Tool Options");
|
|
|
|
static cl::OptionCategory ViewOptions("View Options");
|
2018-04-25 11:33:14 +00:00
|
|
|
|
2018-05-17 15:35:14 +00:00
|
|
|
static cl::opt<std::string> InputFilename(cl::Positional,
|
|
|
|
cl::desc("<input file>"),
|
|
|
|
cl::cat(ToolOptions), cl::init("-"));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::init("-"), cl::cat(ToolOptions),
|
2018-03-08 13:05:02 +00:00
|
|
|
cl::value_desc("filename"));
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
2019-05-24 13:56:01 +00:00
|
|
|
ArchName("march",
|
|
|
|
cl::desc("Target architecture. "
|
|
|
|
"See -version for available targets"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::cat(ToolOptions));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
static cl::opt<std::string>
|
2018-10-22 15:36:15 +00:00
|
|
|
TripleName("mtriple",
|
2018-10-31 17:47:25 +00:00
|
|
|
cl::desc("Target triple. See -version for available targets"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::cat(ToolOptions));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
static cl::opt<std::string>
|
|
|
|
MCPU("mcpu",
|
|
|
|
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native"));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2022-07-12 07:55:55 +00:00
|
|
|
static cl::list<std::string>
|
|
|
|
MATTRS("mattr", cl::CommaSeparated,
|
|
|
|
cl::desc("Target specific attributes (-mattr=help for details)"),
|
|
|
|
cl::value_desc("a1,+a2,-a3,..."), cl::cat(ToolOptions));
|
2019-10-01 17:41:38 +00:00
|
|
|
|
2021-07-13 19:07:03 +02:00
|
|
|
static cl::opt<bool> PrintJson("json",
|
|
|
|
cl::desc("Print the output in json format"),
|
|
|
|
cl::cat(ToolOptions), cl::init(false));
|
2021-01-21 14:04:13 -08:00
|
|
|
|
2018-04-24 16:19:08 +00:00
|
|
|
static cl::opt<int>
|
2018-03-08 13:05:02 +00:00
|
|
|
OutputAsmVariant("output-asm-variant",
|
2018-04-24 16:19:08 +00:00
|
|
|
cl::desc("Syntax variant to use for output printing"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::cat(ToolOptions), cl::init(-1));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2019-08-02 10:38:25 +00:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintImmHex("print-imm-hex", cl::cat(ToolOptions), cl::init(false),
|
|
|
|
cl::desc("Prefer hex format when printing immediate values"));
|
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
static cl::opt<unsigned> Iterations("iterations",
|
|
|
|
cl::desc("Number of iterations to run"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2018-05-17 15:35:14 +00:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
DispatchWidth("dispatch", cl::desc("Override the processor dispatch width"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
static cl::opt<unsigned>
|
|
|
|
RegisterFileSize("register-file-size",
|
2018-07-31 20:05:08 +00:00
|
|
|
cl::desc("Maximum number of physical registers which can "
|
2018-03-08 13:05:02 +00:00
|
|
|
"be used for register mappings"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2019-03-29 12:15:37 +00:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
MicroOpQueue("micro-op-queue-size", cl::Hidden,
|
|
|
|
cl::desc("Number of entries in the micro-op queue"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
|
|
|
|
|
|
|
static cl::opt<unsigned>
|
|
|
|
DecoderThroughput("decoder-throughput", cl::Hidden,
|
|
|
|
cl::desc("Maximum throughput from the decoders "
|
|
|
|
"(instructions per cycle)"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
|
|
|
|
2018-04-03 16:46:23 +00:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintRegisterFileStats("register-file-stats",
|
|
|
|
cl::desc("Print register file statistics"),
|
2018-05-05 15:36:47 +00:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-03 16:46:23 +00:00
|
|
|
|
2018-04-25 10:27:30 +00:00
|
|
|
static cl::opt<bool> PrintDispatchStats("dispatch-stats",
|
|
|
|
cl::desc("Print dispatch statistics"),
|
2018-05-05 15:36:47 +00:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-10 14:55:14 +00:00
|
|
|
|
2018-06-15 14:01:43 +00:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintSummaryView("summary-view", cl::Hidden,
|
|
|
|
cl::desc("Print summary view (enabled by default)"),
|
|
|
|
cl::cat(ViewOptions), cl::init(true));
|
|
|
|
|
2018-04-25 10:27:30 +00:00
|
|
|
static cl::opt<bool> PrintSchedulerStats("scheduler-stats",
|
|
|
|
cl::desc("Print scheduler statistics"),
|
2018-05-05 15:36:47 +00:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-11 11:37:46 +00:00
|
|
|
|
2018-04-11 12:12:53 +00:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintRetireStats("retire-stats",
|
2018-04-25 10:27:30 +00:00
|
|
|
cl::desc("Print retire control unit statistics"),
|
2018-05-05 15:36:47 +00:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-11 12:12:53 +00:00
|
|
|
|
2018-05-05 15:36:47 +00:00
|
|
|
static cl::opt<bool> PrintResourcePressureView(
|
|
|
|
"resource-pressure",
|
|
|
|
cl::desc("Print the resource pressure view (enabled by default)"),
|
|
|
|
cl::cat(ViewOptions), cl::init(true));
|
2018-03-23 11:33:09 +00:00
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
static cl::opt<bool> PrintTimelineView("timeline",
|
|
|
|
cl::desc("Print the timeline view"),
|
2018-05-05 15:36:47 +00:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
static cl::opt<unsigned> TimelineMaxIterations(
|
|
|
|
"timeline-max-iterations",
|
|
|
|
cl::desc("Maximum number of iterations to print in timeline view"),
|
2018-05-05 15:36:47 +00:00
|
|
|
cl::cat(ViewOptions), cl::init(0));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2021-06-24 11:00:13 +01:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
TimelineMaxCycles("timeline-max-cycles",
|
|
|
|
cl::desc("Maximum number of cycles in the timeline view, "
|
|
|
|
"or 0 for unlimited. Defaults to 80 cycles"),
|
|
|
|
cl::cat(ViewOptions), cl::init(80));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2018-05-17 15:35:14 +00:00
|
|
|
static cl::opt<bool>
|
|
|
|
AssumeNoAlias("noalias",
|
|
|
|
cl::desc("If set, assume that loads and stores do not alias"),
|
|
|
|
cl::cat(ToolOptions), cl::init(true));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2018-12-19 18:27:05 +00:00
|
|
|
static cl::opt<unsigned> LoadQueueSize("lqueue",
|
|
|
|
cl::desc("Size of the load queue"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-26 12:04:53 +00:00
|
|
|
|
2018-12-19 18:27:05 +00:00
|
|
|
static cl::opt<unsigned> StoreQueueSize("squeue",
|
|
|
|
cl::desc("Size of the store queue"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2018-03-26 12:04:53 +00:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintInstructionTables("instruction-tables",
|
|
|
|
cl::desc("Print instruction tables"),
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::cat(ToolOptions), cl::init(false));
|
2018-03-26 12:04:53 +00:00
|
|
|
|
2018-05-05 15:36:47 +00:00
|
|
|
static cl::opt<bool> PrintInstructionInfoView(
|
|
|
|
"instruction-info",
|
|
|
|
cl::desc("Print the instruction info view (enabled by default)"),
|
|
|
|
cl::cat(ViewOptions), cl::init(true));
|
2018-03-26 13:44:54 +00:00
|
|
|
|
2018-05-17 12:27:03 +00:00
|
|
|
static cl::opt<bool> EnableAllStats("all-stats",
|
|
|
|
cl::desc("Print all hardware statistics"),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
|
|
|
static cl::opt<bool>
|
|
|
|
EnableAllViews("all-views",
|
|
|
|
cl::desc("Print all views including hardware statistics"),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
[MCA] Highlight kernel bottlenecks in the summary view.
This patch adds a new flag named -bottleneck-analysis to print out information
about throughput bottlenecks.
MCA knows how to identify and classify dynamic dispatch stalls. However, it
doesn't know how to analyze and highlight kernel bottlenecks. The goal of this
patch is to teach MCA how to correlate increases in backend pressure to backend
stalls (and therefore, the loss of throughput).
From a Scheduler point of view, backend pressure is a function of the scheduler
buffer usage (i.e. how the number of uOps in the scheduler buffers changes over
time). Backend pressure increases (or decreases) when there is a mismatch
between the number of opcodes dispatched, and the number of opcodes issued in
the same cycle. Since buffer resources are limited, continuous increases in
backend pressure would eventually leads to dispatch stalls. So, there is a
strong correlation between dispatch stalls, and how backpressure changed over
time.
This patch teaches how to identify situations where backend pressure increases
due to:
- unavailable pipeline resources.
- data dependencies.
Data dependencies may delay execution of instructions and therefore increase the
time that uOps have to spend in the scheduler buffers. That often translates to
an increase in backend pressure which may eventually lead to a bottleneck.
Contention on pipeline resources may also delay execution of instructions, and
lead to a temporary increase in backend pressure.
Internally, the Scheduler classifies instructions based on whether register /
memory operands are available or not.
An instruction is marked as "ready to execute" only if data dependencies are
fully resolved.
Every cycle, the Scheduler attempts to execute all instructions that are ready
to execute. If an instruction cannot execute because of unavailable pipeline
resources, then the Scheduler internally updates a BusyResourceUnits mask with
the ID of each unavailable resource.
ExecuteStage is responsible for tracking changes in backend pressure. If backend
pressure increases during a cycle because of contention on pipeline resources,
then ExecuteStage sends a "backend pressure" event to the listeners.
That event would contain information about instructions delayed by resource
pressure, as well as the BusyResourceUnits mask.
Note that ExecuteStage also knows how to identify situations where backpressure
increased because of delays introduced by data dependencies.
The SummaryView observes "backend pressure" events and prints out a "bottleneck
report".
Example of bottleneck report:
```
Cycles with backend pressure increase [ 99.89% ]
Throughput Bottlenecks:
Resource Pressure [ 0.00% ]
Data Dependencies: [ 99.89% ]
- Register Dependencies [ 0.00% ]
- Memory Dependencies [ 99.89% ]
```
A bottleneck report is printed out only if increases in backend pressure
eventually caused backend stalls.
About the time complexity:
Time complexity is linear in the number of instructions in the
Scheduler::PendingSet.
The average slowdown tends to be in the range of ~5-6%.
For memory intensive kernels, the slowdown can be significant if flag
-noalias=false is specified. In the worst case scenario I have observed a
slowdown of ~30% when flag -noalias=false was specified.
We can definitely recover part of that slowdown if we optimize class LSUnit (by
doing extra bookkeeping to speedup queries). For now, this new analysis is
disabled by default, and it can be enabled via flag -bottleneck-analysis. Users
of MCA as a library can enable the generation of pressure events through the
constructor of ExecuteStage.
This patch partially addresses https://bugs.llvm.org/show_bug.cgi?id=37494
Differential Revision: https://reviews.llvm.org/D58728
llvm-svn: 355308
2019-03-04 11:52:34 +00:00
|
|
|
static cl::opt<bool> EnableBottleneckAnalysis(
|
|
|
|
"bottleneck-analysis",
|
|
|
|
cl::desc("Enable bottleneck analysis (disabled by default)"),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
2019-08-09 11:26:27 +00:00
|
|
|
static cl::opt<bool> ShowEncoding(
|
|
|
|
"show-encoding",
|
|
|
|
cl::desc("Print encoding information in the instruction info view"),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
2022-01-02 16:37:14 -08:00
|
|
|
static cl::opt<bool> ShowBarriers(
|
|
|
|
"show-barriers",
|
|
|
|
cl::desc("Print memory barrier information in the instruction info view"),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
2021-06-16 16:22:54 +01:00
|
|
|
static cl::opt<bool> DisableCustomBehaviour(
|
|
|
|
"disable-cb",
|
|
|
|
cl::desc(
|
|
|
|
"Disable custom behaviour (use the default class which does nothing)."),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
2022-11-04 08:51:39 -07:00
|
|
|
static cl::opt<bool> DisableInstrumentManager(
|
|
|
|
"disable-im",
|
|
|
|
cl::desc("Disable instrumentation manager (use the default class which "
|
|
|
|
"ignores instruments.)."),
|
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
|
|
|
|
2018-04-08 15:10:19 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
const Target *getTarget(const char *ProgName) {
|
2018-03-08 13:05:02 +00:00
|
|
|
if (TripleName.empty())
|
|
|
|
TripleName = Triple::normalize(sys::getDefaultTargetTriple());
|
|
|
|
Triple TheTriple(TripleName);
|
|
|
|
|
|
|
|
// Get the target specific parser.
|
|
|
|
std::string Error;
|
|
|
|
const Target *TheTarget =
|
|
|
|
TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
|
|
|
|
if (!TheTarget) {
|
|
|
|
errs() << ProgName << ": " << Error;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
Fix the triple used in llvm-mca.
lookupTarget() can update the passed triple argument. This happens
when no triple is given on the command line, and the architecture
argument does not match the architecture in the default triple.
For example, passing -march=aarch64 on the command line, and the
default triple being x86_64-windows-msvc, the triple is changed
to aarch64-windows-msvc.
However, this triple is not saved, and later in the code, the
triple is constructed again from the triple name, which is the
default triple at this point. Thus the default triple is passed
to constructor of MCSubtargetInfo instance.
The triple is only used determine the object file format, and by
chance, the AArch64 target also uses the COFF file format, and
all is fine. Obviously, the AArch64 target does not support all
available binary file formats, e.g. XCOFF and GOFF, and llvm-mca
crashes in this case.
The fix is to update the triple name with the changed triple
name for the target lookup. Then the default object file format
for the architecture is used, in the example ELF.
Reviewed By: andreadb, abhina.sreeskantharajan
Differential Revision: https://reviews.llvm.org/D100992
2021-04-21 11:23:13 -04:00
|
|
|
// Update TripleName with the updated triple from the target lookup.
|
|
|
|
TripleName = TheTriple.str();
|
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
// Return the found target.
|
|
|
|
return TheTarget;
|
|
|
|
}
|
|
|
|
|
2018-04-08 15:10:19 +00:00
|
|
|
ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {
|
2018-03-08 16:08:43 +00:00
|
|
|
if (OutputFilename == "")
|
|
|
|
OutputFilename = "-";
|
|
|
|
std::error_code EC;
|
2021-04-06 07:22:41 -04:00
|
|
|
auto Out = std::make_unique<ToolOutputFile>(OutputFilename, EC,
|
|
|
|
sys::fs::OF_TextWithCRLF);
|
2018-03-08 16:08:43 +00:00
|
|
|
if (!EC)
|
2020-02-10 07:06:45 -08:00
|
|
|
return std::move(Out);
|
2018-03-08 16:08:43 +00:00
|
|
|
return EC;
|
|
|
|
}
|
2018-03-08 13:05:02 +00:00
|
|
|
} // end of anonymous namespace
|
|
|
|
|
2018-05-17 12:27:03 +00:00
|
|
|
static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) {
|
|
|
|
if (!O.getNumOccurrences() || O.getPosition() < Default.getPosition())
|
|
|
|
O = Default.getValue();
|
|
|
|
}
|
|
|
|
|
2020-12-29 19:49:09 +03:00
|
|
|
static void processViewOptions(bool IsOutOfOrder) {
|
2018-05-17 12:27:03 +00:00
|
|
|
if (!EnableAllViews.getNumOccurrences() &&
|
|
|
|
!EnableAllStats.getNumOccurrences())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (EnableAllViews.getNumOccurrences()) {
|
2018-06-15 14:01:43 +00:00
|
|
|
processOptionImpl(PrintSummaryView, EnableAllViews);
|
2020-12-29 19:49:09 +03:00
|
|
|
if (IsOutOfOrder)
|
|
|
|
processOptionImpl(EnableBottleneckAnalysis, EnableAllViews);
|
2018-05-17 12:27:03 +00:00
|
|
|
processOptionImpl(PrintResourcePressureView, EnableAllViews);
|
|
|
|
processOptionImpl(PrintTimelineView, EnableAllViews);
|
|
|
|
processOptionImpl(PrintInstructionInfoView, EnableAllViews);
|
|
|
|
}
|
|
|
|
|
|
|
|
const cl::opt<bool> &Default =
|
|
|
|
EnableAllViews.getPosition() < EnableAllStats.getPosition()
|
|
|
|
? EnableAllStats
|
|
|
|
: EnableAllViews;
|
|
|
|
processOptionImpl(PrintRegisterFileStats, Default);
|
|
|
|
processOptionImpl(PrintDispatchStats, Default);
|
|
|
|
processOptionImpl(PrintSchedulerStats, Default);
|
2021-03-15 01:25:51 +03:00
|
|
|
if (IsOutOfOrder)
|
|
|
|
processOptionImpl(PrintRetireStats, Default);
|
2018-05-17 12:27:03 +00:00
|
|
|
}
|
|
|
|
|
2018-10-24 10:56:47 +00:00
|
|
|
// Returns true on success.
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
static bool runPipeline(mca::Pipeline &P) {
|
2018-10-24 10:56:47 +00:00
|
|
|
// Handle pipeline errors here.
|
2018-11-28 19:31:19 +00:00
|
|
|
Expected<unsigned> Cycles = P.run();
|
|
|
|
if (!Cycles) {
|
|
|
|
WithColor::error() << toString(Cycles.takeError());
|
2018-10-24 10:56:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
int main(int argc, char **argv) {
|
2018-04-13 18:26:06 +00:00
|
|
|
InitLLVM X(argc, argv);
|
2018-03-08 13:05:02 +00:00
|
|
|
|
|
|
|
// Initialize targets and assembly parsers.
|
2018-11-08 17:32:45 +00:00
|
|
|
InitializeAllTargetInfos();
|
|
|
|
InitializeAllTargetMCs();
|
|
|
|
InitializeAllAsmParsers();
|
2021-07-24 20:27:41 -07:00
|
|
|
InitializeAllTargetMCAs();
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2022-12-13 22:02:58 +00:00
|
|
|
// Register the Target and CPU printer for --version.
|
|
|
|
cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
|
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
// Enable printing of available targets when flag --version is specified.
|
|
|
|
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
|
|
|
|
|
2018-05-17 15:35:14 +00:00
|
|
|
cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions});
|
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
// Parse flags and initialize target options.
|
|
|
|
cl::ParseCommandLineOptions(argc, argv,
|
|
|
|
"llvm machine code performance analyzer.\n");
|
2018-05-17 15:35:14 +00:00
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
// Get the target from the triple. If a triple is not specified, then select
|
|
|
|
// the default triple for the host. If the triple doesn't correspond to any
|
|
|
|
// registered target, then exit with an error message.
|
|
|
|
const char *ProgName = argv[0];
|
|
|
|
const Target *TheTarget = getTarget(ProgName);
|
|
|
|
if (!TheTarget)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
// GetTarget() may replaced TripleName with a default triple.
|
|
|
|
// For safety, reconstruct the Triple object.
|
|
|
|
Triple TheTriple(TripleName);
|
|
|
|
|
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
|
|
|
|
MemoryBuffer::getFileOrSTDIN(InputFilename);
|
|
|
|
if (std::error_code EC = BufferPtr.getError()) {
|
2018-04-18 15:26:51 +00:00
|
|
|
WithColor::error() << InputFilename << ": " << EC.message() << '\n';
|
2018-03-08 13:05:02 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-01-11 18:48:09 -08:00
|
|
|
if (MCPU == "native")
|
2020-01-28 20:23:46 +01:00
|
|
|
MCPU = std::string(llvm::sys::getHostCPUName());
|
2018-04-25 10:18:25 +00:00
|
|
|
|
2022-07-12 07:55:55 +00:00
|
|
|
// Package up features to be passed to target/subtarget
|
|
|
|
std::string FeaturesStr;
|
|
|
|
if (MATTRS.size()) {
|
|
|
|
SubtargetFeatures Features;
|
|
|
|
for (std::string &MAttr : MATTRS)
|
|
|
|
Features.AddFeature(MAttr);
|
|
|
|
FeaturesStr = Features.getString();
|
|
|
|
}
|
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
std::unique_ptr<MCSubtargetInfo> STI(
|
2022-07-12 07:55:55 +00:00
|
|
|
TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
|
2020-11-21 21:04:12 -08:00
|
|
|
assert(STI && "Unable to create subtarget info!");
|
2018-03-08 13:05:02 +00:00
|
|
|
if (!STI->isCPUStringValid(MCPU))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (!STI->getSchedModel().hasInstrSchedModel()) {
|
2018-04-18 15:26:51 +00:00
|
|
|
WithColor::error()
|
|
|
|
<< "unable to find instruction-level scheduling information for"
|
2018-03-08 13:05:02 +00:00
|
|
|
<< " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU
|
|
|
|
<< "'.\n";
|
|
|
|
|
|
|
|
if (STI->getSchedModel().InstrItineraries)
|
2018-04-18 15:26:51 +00:00
|
|
|
WithColor::note()
|
|
|
|
<< "cpu '" << MCPU << "' provides itineraries. However, "
|
|
|
|
<< "instruction itineraries are currently unsupported.\n";
|
2018-03-08 13:05:02 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-12-29 19:49:09 +03:00
|
|
|
// Apply overrides to llvm-mca specific options.
|
2021-11-29 15:59:45 +03:00
|
|
|
bool IsOutOfOrder = STI->getSchedModel().isOutOfOrder();
|
2020-12-29 19:49:09 +03:00
|
|
|
processViewOptions(IsOutOfOrder);
|
|
|
|
|
2019-08-08 10:30:58 +00:00
|
|
|
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
|
|
|
|
assert(MRI && "Unable to create target register info!");
|
|
|
|
|
2020-03-04 00:47:43 +01:00
|
|
|
MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
|
2019-10-23 12:24:35 +02:00
|
|
|
std::unique_ptr<MCAsmInfo> MAI(
|
|
|
|
TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
|
2019-08-08 10:30:58 +00:00
|
|
|
assert(MAI && "Unable to create target asm info!");
|
|
|
|
|
|
|
|
SourceMgr SrcMgr;
|
|
|
|
|
|
|
|
// Tell SrcMgr about this buffer, which is what the parser will pick up.
|
|
|
|
SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
|
|
|
|
|
|
|
|
std::unique_ptr<buffer_ostream> BOS;
|
|
|
|
|
|
|
|
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
|
2020-11-21 21:04:12 -08:00
|
|
|
assert(MCII && "Unable to create instruction info!");
|
2019-08-08 10:30:58 +00:00
|
|
|
|
|
|
|
std::unique_ptr<MCInstrAnalysis> MCIA(
|
|
|
|
TheTarget->createMCInstrAnalysis(MCII.get()));
|
|
|
|
|
[MCA] llvm-mca MCTargetStreamer segfault fix
In order to create the code regions for llvm-mca to analyze, llvm-mca creates an
AsmCodeRegionGenerator and calls AsmCodeRegionGenerator::parseCodeRegions().
Within this function, both an MCAsmParser and MCTargetAsmParser are created so
that MCAsmParser::Run() can be used to create the code regions for us.
These parser classes were created for llvm-mc so they are designed to emit code
with an MCStreamer and MCTargetStreamer that are expected to be setup and passed
into the MCAsmParser constructor. Because llvm-mca doesn’t want to emit any
code, an MCStreamerWrapper class gets created instead and passed into the
MCAsmParser constructor. This wrapper inherits from MCStreamer and overrides
many of the emit methods to just do nothing. The exception is the
emitInstruction() method which calls Regions.addInstruction(Inst).
This works well and allows llvm-mca to utilize llvm-mc’s MCAsmParser to build
our code regions, however there are a few directives which rely on the
MCTargetStreamer. llvm-mc assumes that the MCStreamer that gets passed into the
MCAsmParser’s constructor has a valid pointer to an MCTargetStreamer. Because
llvm-mca doesn’t setup an MCTargetStreamer, when the parser encounters one of
those directives, a segfault will occur.
In x86, each one of these 7 directives will cause this segfault if they exist in
the input assembly to llvm-mca:
.cv_fpo_proc
.cv_fpo_setframe
.cv_fpo_pushreg
.cv_fpo_stackalloc
.cv_fpo_stackalign
.cv_fpo_endprologue
.cv_fpo_endproc
I haven’t looked at other targets, but I wouldn’t be surprised if some of the
other ones also have certain directives which could result in this same
segfault.
My proposed solution is to simply initialize an MCTargetStreamer after we
initialize the MCStreamerWrapper. The MCTargetStreamer requires an ostream
object, but we don’t actually want any of these directives to be emitted
anywhere, so I use an ostream created with the nulls() function. Since this
needs to happen after the MCStreamerWrapper has been initialized, it needs to
happen within the AsmCodeRegionGenerator::parseCodeRegions() function. The
MCTargetStreamer also needs an MCInstPrinter which is easiest to initialize
within the main() function of llvm-mca. So this MCInstPrinter gets constructed
within main() then passed into the parseCodeRegions() function as a parameter.
(If you feel like it would be appropriate and possible to create the
MCInstPrinter within the parseCodeRegions() function, then feel free to modify
my solution. That would stop us from having to pass it into the function and
would limit its scope / lifetime.)
My solution stops the segfault from happening and still passes all of the
current (expected) llvm-mca tests. I also added a new test for x86 that checks
for this segfault on an input that includes one of the .cv_fpo directives (this
test fails without my solution, but passes with it).
As far as I can tell, all of the functions that I modified are only called from
within llvm-mca so there shouldn’t be any worries about breaking other tools.
Differential Revision: https://reviews.llvm.org/D102709
2021-05-19 10:29:41 +01:00
|
|
|
// Need to initialize an MCInstPrinter as it is
|
|
|
|
// required for initializing the MCTargetStreamer
|
2022-11-04 08:51:39 -07:00
|
|
|
// which needs to happen within the CRG.parseAnalysisRegions() call below.
|
[MCA] llvm-mca MCTargetStreamer segfault fix
In order to create the code regions for llvm-mca to analyze, llvm-mca creates an
AsmCodeRegionGenerator and calls AsmCodeRegionGenerator::parseCodeRegions().
Within this function, both an MCAsmParser and MCTargetAsmParser are created so
that MCAsmParser::Run() can be used to create the code regions for us.
These parser classes were created for llvm-mc so they are designed to emit code
with an MCStreamer and MCTargetStreamer that are expected to be setup and passed
into the MCAsmParser constructor. Because llvm-mca doesn’t want to emit any
code, an MCStreamerWrapper class gets created instead and passed into the
MCAsmParser constructor. This wrapper inherits from MCStreamer and overrides
many of the emit methods to just do nothing. The exception is the
emitInstruction() method which calls Regions.addInstruction(Inst).
This works well and allows llvm-mca to utilize llvm-mc’s MCAsmParser to build
our code regions, however there are a few directives which rely on the
MCTargetStreamer. llvm-mc assumes that the MCStreamer that gets passed into the
MCAsmParser’s constructor has a valid pointer to an MCTargetStreamer. Because
llvm-mca doesn’t setup an MCTargetStreamer, when the parser encounters one of
those directives, a segfault will occur.
In x86, each one of these 7 directives will cause this segfault if they exist in
the input assembly to llvm-mca:
.cv_fpo_proc
.cv_fpo_setframe
.cv_fpo_pushreg
.cv_fpo_stackalloc
.cv_fpo_stackalign
.cv_fpo_endprologue
.cv_fpo_endproc
I haven’t looked at other targets, but I wouldn’t be surprised if some of the
other ones also have certain directives which could result in this same
segfault.
My proposed solution is to simply initialize an MCTargetStreamer after we
initialize the MCStreamerWrapper. The MCTargetStreamer requires an ostream
object, but we don’t actually want any of these directives to be emitted
anywhere, so I use an ostream created with the nulls() function. Since this
needs to happen after the MCStreamerWrapper has been initialized, it needs to
happen within the AsmCodeRegionGenerator::parseCodeRegions() function. The
MCTargetStreamer also needs an MCInstPrinter which is easiest to initialize
within the main() function of llvm-mca. So this MCInstPrinter gets constructed
within main() then passed into the parseCodeRegions() function as a parameter.
(If you feel like it would be appropriate and possible to create the
MCInstPrinter within the parseCodeRegions() function, then feel free to modify
my solution. That would stop us from having to pass it into the function and
would limit its scope / lifetime.)
My solution stops the segfault from happening and still passes all of the
current (expected) llvm-mca tests. I also added a new test for x86 that checks
for this segfault on an input that includes one of the .cv_fpo directives (this
test fails without my solution, but passes with it).
As far as I can tell, all of the functions that I modified are only called from
within llvm-mca so there shouldn’t be any worries about breaking other tools.
Differential Revision: https://reviews.llvm.org/D102709
2021-05-19 10:29:41 +01:00
|
|
|
// Without an MCTargetStreamer, certain assembly directives can trigger a
|
|
|
|
// segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if
|
|
|
|
// we don't initialize the MCTargetStreamer.)
|
|
|
|
unsigned IPtempOutputAsmVariant =
|
|
|
|
OutputAsmVariant == -1 ? 0 : OutputAsmVariant;
|
|
|
|
std::unique_ptr<MCInstPrinter> IPtemp(TheTarget->createMCInstPrinter(
|
|
|
|
Triple(TripleName), IPtempOutputAsmVariant, *MAI, *MCII, *MRI));
|
|
|
|
if (!IPtemp) {
|
|
|
|
WithColor::error()
|
|
|
|
<< "unable to create instruction printer for target triple '"
|
|
|
|
<< TheTriple.normalize() << "' with assembly variant "
|
|
|
|
<< IPtempOutputAsmVariant << ".\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-11-07 19:20:04 +00:00
|
|
|
// Parse the input and create CodeRegions that llvm-mca can analyze.
|
2023-05-03 13:24:44 -07:00
|
|
|
MCContext ACtx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
|
|
|
|
std::unique_ptr<MCObjectFileInfo> AMOFI(
|
|
|
|
TheTarget->createMCObjectFileInfo(ACtx, /*PIC=*/false));
|
|
|
|
ACtx.setObjectFileInfo(AMOFI.get());
|
|
|
|
mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, ACtx, *MAI, *STI,
|
2022-11-04 08:51:39 -07:00
|
|
|
*MCII);
|
|
|
|
Expected<const mca::AnalysisRegions &> RegionsOrErr =
|
|
|
|
CRG.parseAnalysisRegions(std::move(IPtemp));
|
2018-12-19 18:27:05 +00:00
|
|
|
if (!RegionsOrErr) {
|
|
|
|
if (auto Err =
|
2018-12-19 18:57:43 +00:00
|
|
|
handleErrors(RegionsOrErr.takeError(), [](const StringError &E) {
|
|
|
|
WithColor::error() << E.getMessage() << '\n';
|
2018-12-19 18:27:05 +00:00
|
|
|
})) {
|
|
|
|
// Default case.
|
|
|
|
WithColor::error() << toString(std::move(Err)) << '\n';
|
|
|
|
}
|
2018-04-08 15:10:19 +00:00
|
|
|
return 1;
|
2018-11-07 19:20:04 +00:00
|
|
|
}
|
2022-11-04 08:51:39 -07:00
|
|
|
const mca::AnalysisRegions &Regions = *RegionsOrErr;
|
2019-05-09 15:18:09 +00:00
|
|
|
|
|
|
|
// Early exit if errors were found by the code region parsing logic.
|
|
|
|
if (!Regions.isValid())
|
|
|
|
return 1;
|
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
if (Regions.empty()) {
|
2018-04-18 15:26:51 +00:00
|
|
|
WithColor::error() << "no assembly instructions found.\n";
|
2018-03-08 13:05:02 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2022-11-04 08:51:39 -07:00
|
|
|
std::unique_ptr<mca::InstrumentManager> IM;
|
|
|
|
if (!DisableInstrumentManager) {
|
|
|
|
IM = std::unique_ptr<mca::InstrumentManager>(
|
|
|
|
TheTarget->createInstrumentManager(*STI, *MCII));
|
|
|
|
}
|
|
|
|
if (!IM) {
|
|
|
|
// If the target doesn't have its own IM implemented (or the -disable-cb
|
|
|
|
// flag is set) then we use the base class (which does nothing).
|
|
|
|
IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the input and create InstrumentRegion that llvm-mca
|
|
|
|
// can use to improve analysis.
|
2023-05-03 13:24:44 -07:00
|
|
|
MCContext ICtx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
|
|
|
|
std::unique_ptr<MCObjectFileInfo> IMOFI(
|
|
|
|
TheTarget->createMCObjectFileInfo(ICtx, /*PIC=*/false));
|
|
|
|
ICtx.setObjectFileInfo(IMOFI.get());
|
|
|
|
mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, ICtx, *MAI, *STI,
|
2022-11-04 08:51:39 -07:00
|
|
|
*MCII, *IM);
|
|
|
|
Expected<const mca::InstrumentRegions &> InstrumentRegionsOrErr =
|
|
|
|
IRG.parseInstrumentRegions(std::move(IPtemp));
|
|
|
|
if (!InstrumentRegionsOrErr) {
|
|
|
|
if (auto Err = handleErrors(InstrumentRegionsOrErr.takeError(),
|
|
|
|
[](const StringError &E) {
|
|
|
|
WithColor::error() << E.getMessage() << '\n';
|
|
|
|
})) {
|
|
|
|
// Default case.
|
|
|
|
WithColor::error() << toString(std::move(Err)) << '\n';
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
const mca::InstrumentRegions &InstrumentRegions = *InstrumentRegionsOrErr;
|
|
|
|
|
|
|
|
// Early exit if errors were found by the instrumentation parsing logic.
|
|
|
|
if (!InstrumentRegions.isValid())
|
|
|
|
return 1;
|
|
|
|
|
2018-03-08 16:08:43 +00:00
|
|
|
// Now initialize the output file.
|
|
|
|
auto OF = getOutputStream();
|
|
|
|
if (std::error_code EC = OF.getError()) {
|
2018-04-18 15:26:51 +00:00
|
|
|
WithColor::error() << EC.message() << '\n';
|
2018-03-08 16:08:43 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-11-07 19:20:04 +00:00
|
|
|
unsigned AssemblerDialect = CRG.getAssemblerDialect();
|
2018-04-24 16:19:08 +00:00
|
|
|
if (OutputAsmVariant >= 0)
|
|
|
|
AssemblerDialect = static_cast<unsigned>(OutputAsmVariant);
|
|
|
|
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
|
|
|
|
Triple(TripleName), AssemblerDialect, *MAI, *MCII, *MRI));
|
|
|
|
if (!IP) {
|
|
|
|
WithColor::error()
|
|
|
|
<< "unable to create instruction printer for target triple '"
|
|
|
|
<< TheTriple.normalize() << "' with assembly variant "
|
|
|
|
<< AssemblerDialect << ".\n";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-08-02 10:38:25 +00:00
|
|
|
// Set the display preference for hex vs. decimal immediates.
|
|
|
|
IP->setPrintImmHex(PrintImmHex);
|
|
|
|
|
2018-11-08 17:32:45 +00:00
|
|
|
std::unique_ptr<ToolOutputFile> TOF = std::move(*OF);
|
2018-03-08 16:08:43 +00:00
|
|
|
|
2018-03-08 13:05:02 +00:00
|
|
|
const MCSchedModel &SM = STI->getSchedModel();
|
|
|
|
|
2022-03-11 19:52:36 -08:00
|
|
|
std::unique_ptr<mca::InstrPostProcess> IPP;
|
|
|
|
if (!DisableCustomBehaviour) {
|
|
|
|
// TODO: It may be a good idea to separate CB and IPP so that they can
|
|
|
|
// be used independently of each other. What I mean by this is to add
|
|
|
|
// an extra command-line arg --disable-ipp so that CB and IPP can be
|
|
|
|
// toggled without needing to toggle both of them together.
|
|
|
|
IPP = std::unique_ptr<mca::InstrPostProcess>(
|
|
|
|
TheTarget->createInstrPostProcess(*STI, *MCII));
|
|
|
|
}
|
|
|
|
if (!IPP) {
|
|
|
|
// If the target doesn't have its own IPP implemented (or the -disable-cb
|
|
|
|
// flag is set) then we use the base class (which does nothing).
|
|
|
|
IPP = std::make_unique<mca::InstrPostProcess>(*STI, *MCII);
|
|
|
|
}
|
|
|
|
|
2018-03-23 11:50:43 +00:00
|
|
|
// Create an instruction builder.
|
2022-11-04 08:51:39 -07:00
|
|
|
mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);
|
2018-03-23 11:50:43 +00:00
|
|
|
|
2018-07-06 18:03:14 +00:00
|
|
|
// Create a context to control ownership of the pipeline hardware.
|
|
|
|
mca::Context MCA(*MRI, *STI);
|
|
|
|
|
2019-03-29 12:15:37 +00:00
|
|
|
mca::PipelineOptions PO(MicroOpQueue, DecoderThroughput, DispatchWidth,
|
|
|
|
RegisterFileSize, LoadQueueSize, StoreQueueSize,
|
|
|
|
AssumeNoAlias, EnableBottleneckAnalysis);
|
2018-07-06 18:03:14 +00:00
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
// Number each region in the sequence.
|
|
|
|
unsigned RegionIdx = 0;
|
2018-10-26 10:48:04 +00:00
|
|
|
|
2019-08-09 11:26:27 +00:00
|
|
|
std::unique_ptr<MCCodeEmitter> MCE(
|
2023-05-03 13:24:44 -07:00
|
|
|
TheTarget->createMCCodeEmitter(*MCII, ACtx));
|
2020-11-21 21:04:12 -08:00
|
|
|
assert(MCE && "Unable to create code emitter!");
|
2019-08-09 11:26:27 +00:00
|
|
|
|
|
|
|
std::unique_ptr<MCAsmBackend> MAB(TheTarget->createMCAsmBackend(
|
2020-03-04 00:47:43 +01:00
|
|
|
*STI, *MRI, mc::InitMCTargetOptionsFromFlags()));
|
2020-11-21 21:04:12 -08:00
|
|
|
assert(MAB && "Unable to create asm backend!");
|
2019-08-09 11:26:27 +00:00
|
|
|
|
2021-07-09 17:58:57 +02:00
|
|
|
json::Object JSONOutput;
|
2022-11-04 08:51:39 -07:00
|
|
|
for (const std::unique_ptr<mca::AnalysisRegion> &Region : Regions) {
|
2018-04-09 16:39:52 +00:00
|
|
|
// Skip empty code regions.
|
|
|
|
if (Region->empty())
|
|
|
|
continue;
|
|
|
|
|
2021-07-09 22:35:12 +01:00
|
|
|
IB.clear();
|
2018-03-26 13:44:54 +00:00
|
|
|
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
// Lower the MCInst sequence into an mca::Instruction sequence.
|
2018-10-26 10:48:04 +00:00
|
|
|
ArrayRef<MCInst> Insts = Region->getInstructions();
|
2019-08-09 11:26:27 +00:00
|
|
|
mca::CodeEmitter CE(*STI, *MAB, *MCE, Insts);
|
2021-07-24 20:27:41 -07:00
|
|
|
|
2022-03-11 19:52:36 -08:00
|
|
|
IPP->resetState();
|
2021-07-24 20:27:41 -07:00
|
|
|
|
2023-05-12 09:56:43 -07:00
|
|
|
DenseMap<const MCInst *, SmallVector<mca::Instrument *>>
|
|
|
|
InstToInstruments;
|
2022-01-02 16:37:14 -08:00
|
|
|
SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
for (const MCInst &MCI : Insts) {
|
2022-11-04 08:51:39 -07:00
|
|
|
SMLoc Loc = MCI.getLoc();
|
2023-05-17 13:48:18 -07:00
|
|
|
const SmallVector<mca::Instrument *> Instruments =
|
2022-11-04 08:51:39 -07:00
|
|
|
InstrumentRegions.getActiveInstruments(Loc);
|
2023-05-12 09:56:43 -07:00
|
|
|
InstToInstruments.insert({&MCI, Instruments});
|
2022-11-04 08:51:39 -07:00
|
|
|
|
2018-11-08 17:32:45 +00:00
|
|
|
Expected<std::unique_ptr<mca::Instruction>> Inst =
|
2022-11-04 08:51:39 -07:00
|
|
|
IB.createInstruction(MCI, Instruments);
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
if (!Inst) {
|
2018-10-31 17:47:25 +00:00
|
|
|
if (auto NewE = handleErrors(
|
|
|
|
Inst.takeError(),
|
|
|
|
[&IP, &STI](const mca::InstructionError<MCInst> &IE) {
|
|
|
|
std::string InstructionStr;
|
|
|
|
raw_string_ostream SS(InstructionStr);
|
|
|
|
WithColor::error() << IE.Message << '\n';
|
2020-01-03 10:55:30 -08:00
|
|
|
IP->printInst(&IE.Inst, 0, "", *STI, SS);
|
2018-10-31 17:47:25 +00:00
|
|
|
SS.flush();
|
2019-05-24 13:56:01 +00:00
|
|
|
WithColor::note()
|
|
|
|
<< "instruction: " << InstructionStr << '\n';
|
2018-10-31 17:47:25 +00:00
|
|
|
})) {
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
// Default case.
|
|
|
|
WithColor::error() << toString(std::move(NewE));
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-06-16 16:22:54 +01:00
|
|
|
IPP->postProcessInstruction(Inst.get(), MCI);
|
|
|
|
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
LoweredSequence.emplace_back(std::move(Inst.get()));
|
|
|
|
}
|
|
|
|
|
2022-05-30 16:50:09 -07:00
|
|
|
mca::CircularSourceMgr S(LoweredSequence,
|
|
|
|
PrintInstructionTables ? 1 : Iterations);
|
2018-04-09 16:39:52 +00:00
|
|
|
|
|
|
|
if (PrintInstructionTables) {
|
2018-07-14 23:52:50 +00:00
|
|
|
// Create a pipeline, stages, and a printer.
|
2019-08-15 15:54:37 +00:00
|
|
|
auto P = std::make_unique<mca::Pipeline>();
|
|
|
|
P->appendStage(std::make_unique<mca::EntryStage>(S));
|
|
|
|
P->appendStage(std::make_unique<mca::InstructionTables>(SM));
|
2021-07-09 22:35:12 +01:00
|
|
|
|
2021-07-16 09:10:50 +02:00
|
|
|
mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO);
|
2021-07-09 22:35:12 +01:00
|
|
|
if (PrintJson) {
|
2021-07-13 19:07:03 +02:00
|
|
|
Printer.addView(
|
|
|
|
std::make_unique<mca::InstructionView>(*STI, *IP, Insts));
|
2021-07-09 22:35:12 +01:00
|
|
|
}
|
2018-04-09 16:39:52 +00:00
|
|
|
|
2018-07-14 23:52:50 +00:00
|
|
|
// Create the views for this pipeline, execute, and emit a report.
|
2018-04-09 16:39:52 +00:00
|
|
|
if (PrintInstructionInfoView) {
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::InstructionInfoView>(
|
2022-01-02 16:37:14 -08:00
|
|
|
*STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,
|
2023-05-12 09:56:43 -07:00
|
|
|
ShowBarriers, *IM, InstToInstruments));
|
2018-04-09 16:39:52 +00:00
|
|
|
}
|
2018-11-08 18:08:43 +00:00
|
|
|
Printer.addView(
|
2019-08-15 15:54:37 +00:00
|
|
|
std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
|
2018-10-24 10:56:47 +00:00
|
|
|
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
if (!runPipeline(*P))
|
2018-10-24 10:56:47 +00:00
|
|
|
return 1;
|
|
|
|
|
2021-07-09 17:58:57 +02:00
|
|
|
if (PrintJson) {
|
2021-07-09 22:35:12 +01:00
|
|
|
Printer.printReport(JSONOutput);
|
2021-07-09 17:58:57 +02:00
|
|
|
} else {
|
|
|
|
Printer.printReport(TOF->os());
|
|
|
|
}
|
2021-07-09 22:35:12 +01:00
|
|
|
|
|
|
|
++RegionIdx;
|
2018-04-09 16:39:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-06-16 16:22:54 +01:00
|
|
|
// Create the CustomBehaviour object for enforcing Target Specific
|
|
|
|
// behaviours and dependencies that aren't expressed well enough
|
|
|
|
// in the tablegen. CB cannot depend on the list of MCInst or
|
|
|
|
// the source code (but it can depend on the list of
|
|
|
|
// mca::Instruction or any objects that can be reconstructed
|
|
|
|
// from the target information).
|
2021-07-24 20:27:41 -07:00
|
|
|
std::unique_ptr<mca::CustomBehaviour> CB;
|
|
|
|
if (!DisableCustomBehaviour)
|
|
|
|
CB = std::unique_ptr<mca::CustomBehaviour>(
|
|
|
|
TheTarget->createCustomBehaviour(*STI, S, *MCII));
|
|
|
|
if (!CB)
|
|
|
|
// If the target doesn't have its own CB implemented (or the -disable-cb
|
|
|
|
// flag is set) then we use the base class (which does nothing).
|
|
|
|
CB = std::make_unique<mca::CustomBehaviour>(*STI, S, *MCII);
|
2021-06-16 16:22:54 +01:00
|
|
|
|
2018-07-06 18:03:14 +00:00
|
|
|
// Create a basic pipeline simulating an out-of-order backend.
|
2021-06-16 16:22:54 +01:00
|
|
|
auto P = MCA.createDefaultPipeline(PO, S, *CB);
|
2021-07-09 22:35:12 +01:00
|
|
|
|
2021-07-16 09:10:50 +02:00
|
|
|
mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO);
|
2021-01-21 14:04:13 -08:00
|
|
|
|
2021-08-21 17:37:02 -07:00
|
|
|
// Targets can define their own custom Views that exist within their
|
|
|
|
// /lib/Target/ directory so that the View can utilize their CustomBehaviour
|
|
|
|
// or other backend symbols / functionality that are not already exposed
|
|
|
|
// through one of the MC-layer classes. These Views will be initialized
|
|
|
|
// using the CustomBehaviour::getViews() variants.
|
|
|
|
// If a target makes a custom View that does not depend on their target
|
|
|
|
// CB or their backend, they should put the View within
|
|
|
|
// /tools/llvm-mca/Views/ instead.
|
|
|
|
if (!DisableCustomBehaviour) {
|
|
|
|
std::vector<std::unique_ptr<mca::View>> CBViews =
|
|
|
|
CB->getStartViews(*IP, Insts);
|
|
|
|
for (auto &CBView : CBViews)
|
|
|
|
Printer.addView(std::move(CBView));
|
|
|
|
}
|
|
|
|
|
2021-01-21 14:04:13 -08:00
|
|
|
// When we output JSON, we add a view that contains the instructions
|
|
|
|
// and CPU resource information.
|
2021-07-09 17:58:57 +02:00
|
|
|
if (PrintJson) {
|
2021-07-09 22:35:12 +01:00
|
|
|
auto IV = std::make_unique<mca::InstructionView>(*STI, *IP, Insts);
|
2021-07-09 17:58:57 +02:00
|
|
|
Printer.addView(std::move(IV));
|
|
|
|
}
|
2018-03-09 13:52:03 +00:00
|
|
|
|
2018-06-15 14:01:43 +00:00
|
|
|
if (PrintSummaryView)
|
2019-05-24 13:56:01 +00:00
|
|
|
Printer.addView(
|
2019-08-15 15:54:37 +00:00
|
|
|
std::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth));
|
2019-04-17 06:02:05 +00:00
|
|
|
|
2019-06-18 12:59:46 +00:00
|
|
|
if (EnableBottleneckAnalysis) {
|
2020-12-29 19:49:09 +03:00
|
|
|
if (!IsOutOfOrder) {
|
|
|
|
WithColor::warning()
|
|
|
|
<< "bottleneck analysis is not supported for in-order CPU '" << MCPU
|
|
|
|
<< "'.\n";
|
|
|
|
}
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::BottleneckAnalysis>(
|
2019-06-18 12:59:46 +00:00
|
|
|
*STI, *IP, Insts, S.getNumIterations()));
|
|
|
|
}
|
2018-06-15 14:01:43 +00:00
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
if (PrintInstructionInfoView)
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::InstructionInfoView>(
|
2022-01-02 16:37:14 -08:00
|
|
|
*STI, *MCII, CE, ShowEncoding, Insts, *IP, LoweredSequence,
|
2023-05-12 09:56:43 -07:00
|
|
|
ShowBarriers, *IM, InstToInstruments));
|
2018-03-23 19:40:04 +00:00
|
|
|
|
2021-08-21 17:37:02 -07:00
|
|
|
// Fetch custom Views that are to be placed after the InstructionInfoView.
|
|
|
|
// Refer to the comment paired with the CB->getStartViews(*IP, Insts); line
|
|
|
|
// for more info.
|
|
|
|
if (!DisableCustomBehaviour) {
|
|
|
|
std::vector<std::unique_ptr<mca::View>> CBViews =
|
|
|
|
CB->getPostInstrInfoViews(*IP, Insts);
|
|
|
|
for (auto &CBView : CBViews)
|
|
|
|
Printer.addView(std::move(CBView));
|
|
|
|
}
|
|
|
|
|
2018-04-10 14:55:14 +00:00
|
|
|
if (PrintDispatchStats)
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::DispatchStatistics>());
|
2018-04-10 14:55:14 +00:00
|
|
|
|
2018-04-11 12:12:53 +00:00
|
|
|
if (PrintSchedulerStats)
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::SchedulerStatistics>(*STI));
|
2018-04-11 11:37:46 +00:00
|
|
|
|
2018-04-11 12:12:53 +00:00
|
|
|
if (PrintRetireStats)
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::RetireControlUnitStatistics>(SM));
|
2018-03-08 16:08:43 +00:00
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
if (PrintRegisterFileStats)
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::RegisterFileStatistics>(*STI));
|
2018-03-08 16:08:43 +00:00
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
if (PrintResourcePressureView)
|
2018-11-08 18:08:43 +00:00
|
|
|
Printer.addView(
|
2019-08-15 15:54:37 +00:00
|
|
|
std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
|
2018-04-03 16:46:23 +00:00
|
|
|
|
2018-04-09 16:39:52 +00:00
|
|
|
if (PrintTimelineView) {
|
2018-10-26 10:48:04 +00:00
|
|
|
unsigned TimelineIterations =
|
|
|
|
TimelineMaxIterations ? TimelineMaxIterations : 10;
|
2019-08-15 15:54:37 +00:00
|
|
|
Printer.addView(std::make_unique<mca::TimelineView>(
|
2018-10-26 10:48:04 +00:00
|
|
|
*STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()),
|
|
|
|
TimelineMaxCycles));
|
2018-04-09 16:39:52 +00:00
|
|
|
}
|
2018-03-08 16:08:43 +00:00
|
|
|
|
2021-08-21 17:37:02 -07:00
|
|
|
// Fetch custom Views that are to be placed after all other Views.
|
|
|
|
// Refer to the comment paired with the CB->getStartViews(*IP, Insts); line
|
|
|
|
// for more info.
|
|
|
|
if (!DisableCustomBehaviour) {
|
|
|
|
std::vector<std::unique_ptr<mca::View>> CBViews =
|
|
|
|
CB->getEndViews(*IP, Insts);
|
|
|
|
for (auto &CBView : CBViews)
|
|
|
|
Printer.addView(std::move(CBView));
|
|
|
|
}
|
|
|
|
|
[llvm-mca] Lower to mca::Instructon before the pipeline is run.
Before this change, the lowering of instructions from llvm::MCInst to
mca::Instruction was done as part of the first stage of the pipeline (i.e. the
FetchStage). In particular, FetchStage was responsible for picking the next
instruction from the source sequence, and lower it to an mca::Instruction with
the help of an object of class InstrBuilder.
The dependency on InstrBuilder was problematic for a number of reasons. Class
InstrBuilder only knows how to lower from llvm::MCInst to mca::Instruction.
That means, it is hard to support a different scenario where instructions
in input are not instances of class llvm::MCInst. Even if we managed to
specialize InstrBuilder, and generalize most of its internal logic, the
dependency on InstrBuilder in FetchStage would have caused more troubles (other
than complicating the pipeline logic).
With this patch, the lowering step is done before the pipeline is run. The
pipeline is no longer responsible for lowering from MCInst to mca::Instruction.
As a consequence of this, the FetchStage no longer needs to interact with an
InstrBuilder. The mca::SourceMgr class now simply wraps a reference to a
sequence of mca::Instruction objects.
This simplifies the logic of FetchStage, and increases the usability of it. As
a result, on a debug build, we see a 7-9% speedup; on a release build, the
speedup is around 3-4%.
llvm-svn: 345500
2018-10-29 13:29:22 +00:00
|
|
|
if (!runPipeline(*P))
|
2018-10-24 10:56:47 +00:00
|
|
|
return 1;
|
|
|
|
|
2021-07-09 17:58:57 +02:00
|
|
|
if (PrintJson) {
|
2021-07-09 22:35:12 +01:00
|
|
|
Printer.printReport(JSONOutput);
|
2021-07-09 17:58:57 +02:00
|
|
|
} else {
|
|
|
|
Printer.printReport(TOF->os());
|
|
|
|
}
|
2018-07-02 20:39:57 +00:00
|
|
|
|
2021-07-09 22:35:12 +01:00
|
|
|
++RegionIdx;
|
2018-03-08 16:08:43 +00:00
|
|
|
}
|
2018-03-08 13:05:02 +00:00
|
|
|
|
2021-07-09 17:58:57 +02:00
|
|
|
if (PrintJson)
|
|
|
|
TOF->os() << formatv("{0:2}", json::Value(std::move(JSONOutput))) << "\n";
|
|
|
|
|
2018-03-08 16:08:43 +00:00
|
|
|
TOF->keep();
|
2018-03-08 13:05:02 +00:00
|
|
|
return 0;
|
|
|
|
}
|