2018-03-08 21:05:02 +08:00
|
|
|
//===-- llvm-mca.cpp - Machine Code Analyzer -------------------*- C++ -* -===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// 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 18:18:25 +08:00
|
|
|
// The cpu defaults to the 'native' host cpu.
|
2018-03-08 21:05:02 +08:00
|
|
|
// The output defaults to standard output.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
#include "CodeRegion.h"
|
2018-11-08 03:20:04 +08:00
|
|
|
#include "CodeRegionGenerator.h"
|
2018-06-26 00:53:00 +08:00
|
|
|
#include "PipelinePrinter.h"
|
[llvm-mca] Introduce the llvm-mca library and organize the directory accordingly. NFC.
Summary:
This patch introduces llvm-mca as a library. The driver (llvm-mca.cpp), views, and stats, are not part of the library.
Those are separate components that are not required for the functioning of llvm-mca.
The directory has been organized as follows:
All library source files now reside in:
- `lib/HardwareUnits/` - All subclasses of HardwareUnit (these represent the simulated hardware components of a backend).
(LSUnit does not inherit from HardwareUnit, but Scheduler does which uses LSUnit).
- `lib/Stages/` - All subclasses of the pipeline stages.
- `lib/` - This is the root of the library and contains library code that does not fit into the Stages or HardwareUnit subdirs.
All library header files now reside in the `include` directory and mimic the same layout as the `lib` directory mentioned above.
In the (near) future we would like to move the library (include and lib) contents from tools and into the core of llvm somewhere.
That change would allow various analysis and optimization passes to make use of MCA functionality for things like cost modeling.
I left all of the non-library code just where it has always been, in the root of the llvm-mca directory.
The include directives for the non-library source file have been updated to refer to the llvm-mca library headers.
I updated the llvm-mca/CMakeLists.txt file to include the library headers, but I made the non-library code
explicitly reference the library's 'include' directory. Once we eventually (hopefully) migrate the MCA library
components into llvm the include directives used by the non-library source files will be updated to point to the
proper location in llvm.
Reviewers: andreadb, courbet, RKSimon
Reviewed By: andreadb
Subscribers: mgorny, javed.absar, tschuett, gbedwell, llvm-commits
Differential Revision: https://reviews.llvm.org/D50929
llvm-svn: 340755
2018-08-28 01:16:32 +08:00
|
|
|
#include "Stages/FetchStage.h"
|
|
|
|
#include "Stages/InstructionTables.h"
|
2018-08-25 04:24:53 +08: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"
|
[llvm-mca] Introduce the llvm-mca library and organize the directory accordingly. NFC.
Summary:
This patch introduces llvm-mca as a library. The driver (llvm-mca.cpp), views, and stats, are not part of the library.
Those are separate components that are not required for the functioning of llvm-mca.
The directory has been organized as follows:
All library source files now reside in:
- `lib/HardwareUnits/` - All subclasses of HardwareUnit (these represent the simulated hardware components of a backend).
(LSUnit does not inherit from HardwareUnit, but Scheduler does which uses LSUnit).
- `lib/Stages/` - All subclasses of the pipeline stages.
- `lib/` - This is the root of the library and contains library code that does not fit into the Stages or HardwareUnit subdirs.
All library header files now reside in the `include` directory and mimic the same layout as the `lib` directory mentioned above.
In the (near) future we would like to move the library (include and lib) contents from tools and into the core of llvm somewhere.
That change would allow various analysis and optimization passes to make use of MCA functionality for things like cost modeling.
I left all of the non-library code just where it has always been, in the root of the llvm-mca directory.
The include directives for the non-library source file have been updated to refer to the llvm-mca library headers.
I updated the llvm-mca/CMakeLists.txt file to include the library headers, but I made the non-library code
explicitly reference the library's 'include' directory. Once we eventually (hopefully) migrate the MCA library
components into llvm the include directives used by the non-library source files will be updated to point to the
proper location in llvm.
Reviewers: andreadb, courbet, RKSimon
Reviewed By: andreadb
Subscribers: mgorny, javed.absar, tschuett, gbedwell, llvm-commits
Differential Revision: https://reviews.llvm.org/D50929
llvm-svn: 340755
2018-08-28 01:16:32 +08:00
|
|
|
#include "include/Context.h"
|
|
|
|
#include "include/Pipeline.h"
|
2018-10-24 18:56:47 +08:00
|
|
|
#include "include/Support.h"
|
2018-03-08 21:05:02 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
|
|
#include "llvm/MC/MCContext.h"
|
|
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
2018-08-14 02:11:48 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2018-03-09 00:08:43 +08:00
|
|
|
#include "llvm/Support/ErrorOr.h"
|
|
|
|
#include "llvm/Support/FileSystem.h"
|
2018-04-25 18:27:30 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
2018-04-14 02:26:06 +08:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
2018-03-08 21:05:02 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
|
|
|
#include "llvm/Support/SourceMgr.h"
|
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
|
|
#include "llvm/Support/TargetSelect.h"
|
2018-03-09 00:08:43 +08:00
|
|
|
#include "llvm/Support/ToolOutputFile.h"
|
2018-04-18 23:26:51 +08:00
|
|
|
#include "llvm/Support/WithColor.h"
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2018-05-17 23:35:14 +08:00
|
|
|
static cl::OptionCategory ToolOptions("Tool Options");
|
|
|
|
static cl::OptionCategory ViewOptions("View Options");
|
2018-04-25 19:33:14 +08:00
|
|
|
|
2018-05-17 23:35:14 +08:00
|
|
|
static cl::opt<std::string> InputFilename(cl::Positional,
|
|
|
|
cl::desc("<input file>"),
|
|
|
|
cl::cat(ToolOptions), cl::init("-"));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::init("-"), cl::cat(ToolOptions),
|
2018-03-08 21:05:02 +08:00
|
|
|
cl::value_desc("filename"));
|
|
|
|
|
|
|
|
static cl::opt<std::string>
|
2018-11-01 01:47:25 +08:00
|
|
|
ArchName("march", cl::desc("Target architecture. "
|
|
|
|
"See -version for available targets"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::cat(ToolOptions));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<std::string>
|
2018-10-22 23:36:15 +08:00
|
|
|
TripleName("mtriple",
|
2018-11-01 01:47:25 +08:00
|
|
|
cl::desc("Target triple. See -version for available targets"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::cat(ToolOptions));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<std::string>
|
|
|
|
MCPU("mcpu",
|
|
|
|
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native"));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
2018-04-25 00:19:08 +08:00
|
|
|
static cl::opt<int>
|
2018-03-08 21:05:02 +08:00
|
|
|
OutputAsmVariant("output-asm-variant",
|
2018-04-25 00:19:08 +08:00
|
|
|
cl::desc("Syntax variant to use for output printing"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::cat(ToolOptions), cl::init(-1));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<unsigned> Iterations("iterations",
|
|
|
|
cl::desc("Number of iterations to run"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
2018-05-17 23:35:14 +08:00
|
|
|
static cl::opt<unsigned>
|
|
|
|
DispatchWidth("dispatch", cl::desc("Override the processor dispatch width"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<unsigned>
|
|
|
|
RegisterFileSize("register-file-size",
|
2018-08-01 04:05:08 +08:00
|
|
|
cl::desc("Maximum number of physical registers which can "
|
2018-03-08 21:05:02 +08:00
|
|
|
"be used for register mappings"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
2018-04-04 00:46:23 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintRegisterFileStats("register-file-stats",
|
|
|
|
cl::desc("Print register file statistics"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-04 00:46:23 +08:00
|
|
|
|
2018-04-25 18:27:30 +08:00
|
|
|
static cl::opt<bool> PrintDispatchStats("dispatch-stats",
|
|
|
|
cl::desc("Print dispatch statistics"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-10 22:55:14 +08:00
|
|
|
|
2018-06-15 22:01:43 +08: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 18:27:30 +08:00
|
|
|
static cl::opt<bool> PrintSchedulerStats("scheduler-stats",
|
|
|
|
cl::desc("Print scheduler statistics"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-11 19:37:46 +08:00
|
|
|
|
2018-04-11 20:12:53 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintRetireStats("retire-stats",
|
2018-04-25 18:27:30 +08:00
|
|
|
cl::desc("Print retire control unit statistics"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-04-11 20:12:53 +08:00
|
|
|
|
2018-05-05 23:36:47 +08: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 19:33:09 +08:00
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
static cl::opt<bool> PrintTimelineView("timeline",
|
|
|
|
cl::desc("Print the timeline view"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(false));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<unsigned> TimelineMaxIterations(
|
|
|
|
"timeline-max-iterations",
|
|
|
|
cl::desc("Maximum number of iterations to print in timeline view"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(0));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<unsigned> TimelineMaxCycles(
|
|
|
|
"timeline-max-cycles",
|
|
|
|
cl::desc(
|
|
|
|
"Maximum number of cycles in the timeline view. Defaults to 80 cycles"),
|
2018-05-05 23:36:47 +08:00
|
|
|
cl::cat(ViewOptions), cl::init(80));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
2018-05-17 23:35:14 +08: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 21:05:02 +08:00
|
|
|
|
|
|
|
static cl::opt<unsigned>
|
2018-05-17 23:35:14 +08:00
|
|
|
LoadQueueSize("lqueue",
|
|
|
|
cl::desc("Size of the load queue (unbound by default)"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-26 20:04:53 +08:00
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
static cl::opt<unsigned>
|
2018-05-17 23:35:14 +08:00
|
|
|
StoreQueueSize("squeue",
|
|
|
|
cl::desc("Size of the store queue (unbound by default)"),
|
|
|
|
cl::cat(ToolOptions), cl::init(0));
|
2018-03-08 21:05:02 +08:00
|
|
|
|
2018-03-26 20:04:53 +08:00
|
|
|
static cl::opt<bool>
|
|
|
|
PrintInstructionTables("instruction-tables",
|
|
|
|
cl::desc("Print instruction tables"),
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::cat(ToolOptions), cl::init(false));
|
2018-03-26 20:04:53 +08:00
|
|
|
|
2018-05-05 23:36:47 +08: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 21:44:54 +08:00
|
|
|
|
2018-05-17 20:27:03 +08: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));
|
|
|
|
|
2018-04-08 23:10:19 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
const Target *getTarget(const char *ProgName) {
|
2018-03-08 21:05:02 +08: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;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the found target.
|
|
|
|
return TheTarget;
|
|
|
|
}
|
|
|
|
|
2018-04-08 23:10:19 +08:00
|
|
|
ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {
|
2018-03-09 00:08:43 +08:00
|
|
|
if (OutputFilename == "")
|
|
|
|
OutputFilename = "-";
|
|
|
|
std::error_code EC;
|
2018-11-09 01:32:45 +08:00
|
|
|
auto Out = make_unique<ToolOutputFile>(OutputFilename, EC, sys::fs::F_None);
|
2018-03-09 00:08:43 +08:00
|
|
|
if (!EC)
|
|
|
|
return std::move(Out);
|
|
|
|
return EC;
|
|
|
|
}
|
2018-03-08 21:05:02 +08:00
|
|
|
} // end of anonymous namespace
|
|
|
|
|
2018-05-17 20:27:03 +08:00
|
|
|
static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) {
|
|
|
|
if (!O.getNumOccurrences() || O.getPosition() < Default.getPosition())
|
|
|
|
O = Default.getValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void processViewOptions() {
|
|
|
|
if (!EnableAllViews.getNumOccurrences() &&
|
|
|
|
!EnableAllStats.getNumOccurrences())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (EnableAllViews.getNumOccurrences()) {
|
2018-06-15 22:01:43 +08:00
|
|
|
processOptionImpl(PrintSummaryView, EnableAllViews);
|
2018-05-17 20:27:03 +08: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);
|
|
|
|
processOptionImpl(PrintRetireStats, Default);
|
|
|
|
}
|
|
|
|
|
2018-10-24 18:56:47 +08: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 21:29:22 +08:00
|
|
|
static bool runPipeline(mca::Pipeline &P) {
|
2018-10-24 18:56:47 +08:00
|
|
|
// Handle pipeline errors here.
|
|
|
|
if (auto Err = P.run()) {
|
[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 21:29:22 +08:00
|
|
|
WithColor::error() << toString(std::move(Err));
|
2018-10-24 18:56:47 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
int main(int argc, char **argv) {
|
2018-04-14 02:26:06 +08:00
|
|
|
InitLLVM X(argc, argv);
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
// Initialize targets and assembly parsers.
|
2018-11-09 01:32:45 +08:00
|
|
|
InitializeAllTargetInfos();
|
|
|
|
InitializeAllTargetMCs();
|
|
|
|
InitializeAllAsmParsers();
|
2018-03-08 21:05:02 +08:00
|
|
|
|
|
|
|
// Enable printing of available targets when flag --version is specified.
|
|
|
|
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
|
|
|
|
|
2018-05-17 23:35:14 +08:00
|
|
|
cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions});
|
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
// Parse flags and initialize target options.
|
|
|
|
cl::ParseCommandLineOptions(argc, argv,
|
|
|
|
"llvm machine code performance analyzer.\n");
|
2018-05-17 23:35:14 +08:00
|
|
|
|
2018-03-08 21:05:02 +08: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 23:26:51 +08:00
|
|
|
WithColor::error() << InputFilename << ": " << EC.message() << '\n';
|
2018-03-08 21:05:02 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-05-17 20:27:03 +08:00
|
|
|
// Apply overrides to llvm-mca specific options.
|
|
|
|
processViewOptions();
|
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
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;
|
2018-03-26 20:04:53 +08:00
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
|
2018-04-25 18:18:25 +08:00
|
|
|
|
2018-06-20 18:08:11 +08:00
|
|
|
std::unique_ptr<MCInstrAnalysis> MCIA(
|
|
|
|
TheTarget->createMCInstrAnalysis(MCII.get()));
|
|
|
|
|
2018-04-25 18:18:25 +08:00
|
|
|
if (!MCPU.compare("native"))
|
2018-11-09 01:32:45 +08:00
|
|
|
MCPU = sys::getHostCPUName();
|
2018-04-25 18:18:25 +08:00
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
std::unique_ptr<MCSubtargetInfo> STI(
|
|
|
|
TheTarget->createMCSubtargetInfo(TripleName, MCPU, /* FeaturesStr */ ""));
|
|
|
|
if (!STI->isCPUStringValid(MCPU))
|
|
|
|
return 1;
|
|
|
|
|
2018-04-30 20:05:34 +08:00
|
|
|
if (!PrintInstructionTables && !STI->getSchedModel().isOutOfOrder()) {
|
2018-04-18 23:26:51 +08:00
|
|
|
WithColor::error() << "please specify an out-of-order cpu. '" << MCPU
|
|
|
|
<< "' is an in-order cpu.\n";
|
2018-03-08 21:05:02 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!STI->getSchedModel().hasInstrSchedModel()) {
|
2018-04-18 23:26:51 +08:00
|
|
|
WithColor::error()
|
|
|
|
<< "unable to find instruction-level scheduling information for"
|
2018-03-08 21:05:02 +08:00
|
|
|
<< " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU
|
|
|
|
<< "'.\n";
|
|
|
|
|
|
|
|
if (STI->getSchedModel().InstrItineraries)
|
2018-04-18 23:26:51 +08:00
|
|
|
WithColor::note()
|
|
|
|
<< "cpu '" << MCPU << "' provides itineraries. However, "
|
|
|
|
<< "instruction itineraries are currently unsupported.\n";
|
2018-03-08 21:05:02 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-11-08 03:20:04 +08:00
|
|
|
// 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();
|
|
|
|
if (auto Err = RegionsOrErr.takeError()) {
|
|
|
|
WithColor::error() << Err << "\n";
|
2018-04-08 23:10:19 +08:00
|
|
|
return 1;
|
2018-11-08 03:20:04 +08:00
|
|
|
}
|
|
|
|
const mca::CodeRegions &Regions = *RegionsOrErr;
|
2018-04-10 00:39:52 +08:00
|
|
|
if (Regions.empty()) {
|
2018-04-18 23:26:51 +08:00
|
|
|
WithColor::error() << "no assembly instructions found.\n";
|
2018-03-08 21:05:02 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-03-09 00:08:43 +08:00
|
|
|
// Now initialize the output file.
|
|
|
|
auto OF = getOutputStream();
|
|
|
|
if (std::error_code EC = OF.getError()) {
|
2018-04-18 23:26:51 +08:00
|
|
|
WithColor::error() << EC.message() << '\n';
|
2018-03-09 00:08:43 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-11-08 03:20:04 +08:00
|
|
|
unsigned AssemblerDialect = CRG.getAssemblerDialect();
|
2018-04-25 00:19:08 +08: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;
|
|
|
|
}
|
|
|
|
|
2018-11-09 01:32:45 +08:00
|
|
|
std::unique_ptr<ToolOutputFile> TOF = std::move(*OF);
|
2018-03-09 00:08:43 +08:00
|
|
|
|
2018-03-08 21:05:02 +08:00
|
|
|
const MCSchedModel &SM = STI->getSchedModel();
|
|
|
|
|
|
|
|
unsigned Width = SM.IssueWidth;
|
|
|
|
if (DispatchWidth)
|
|
|
|
Width = DispatchWidth;
|
|
|
|
|
2018-03-23 19:50:43 +08:00
|
|
|
// Create an instruction builder.
|
2018-10-24 18:56:47 +08:00
|
|
|
mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA);
|
2018-03-23 19:50:43 +08:00
|
|
|
|
2018-07-07 02:03:14 +08:00
|
|
|
// Create a context to control ownership of the pipeline hardware.
|
|
|
|
mca::Context MCA(*MRI, *STI);
|
|
|
|
|
|
|
|
mca::PipelineOptions PO(Width, RegisterFileSize, LoadQueueSize,
|
|
|
|
StoreQueueSize, AssumeNoAlias);
|
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
// Number each region in the sequence.
|
|
|
|
unsigned RegionIdx = 0;
|
2018-10-26 18:48:04 +08:00
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) {
|
|
|
|
// Skip empty code regions.
|
|
|
|
if (Region->empty())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Don't print the header of this region if it is the default region, and
|
|
|
|
// it doesn't have an end location.
|
|
|
|
if (Region->startLoc().isValid() || Region->endLoc().isValid()) {
|
|
|
|
TOF->os() << "\n[" << RegionIdx++ << "] Code Region";
|
|
|
|
StringRef Desc = Region->getDescription();
|
|
|
|
if (!Desc.empty())
|
|
|
|
TOF->os() << " - " << Desc;
|
|
|
|
TOF->os() << "\n\n";
|
2018-03-26 21:44:54 +08: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 21:29:22 +08:00
|
|
|
// Lower the MCInst sequence into an mca::Instruction sequence.
|
2018-10-26 18:48:04 +08:00
|
|
|
ArrayRef<MCInst> Insts = Region->getInstructions();
|
[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 21:29:22 +08:00
|
|
|
std::vector<std::unique_ptr<mca::Instruction>> LoweredSequence;
|
|
|
|
for (const MCInst &MCI : Insts) {
|
2018-11-09 01:32:45 +08:00
|
|
|
Expected<std::unique_ptr<mca::Instruction>> Inst =
|
2018-11-01 01:47:25 +08:00
|
|
|
IB.createInstruction(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 21:29:22 +08:00
|
|
|
if (!Inst) {
|
2018-11-01 01:47:25 +08: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';
|
|
|
|
IP->printInst(&IE.Inst, SS, "", *STI);
|
|
|
|
SS.flush();
|
|
|
|
WithColor::note() << "instruction: " << InstructionStr
|
|
|
|
<< '\n';
|
|
|
|
})) {
|
[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 21:29:22 +08:00
|
|
|
// Default case.
|
|
|
|
WithColor::error() << toString(std::move(NewE));
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
LoweredSequence.emplace_back(std::move(Inst.get()));
|
|
|
|
}
|
|
|
|
|
2018-11-01 01:47:25 +08:00
|
|
|
mca::SourceMgr S(LoweredSequence, PrintInstructionTables ? 1 : Iterations);
|
2018-04-10 00:39:52 +08:00
|
|
|
|
|
|
|
if (PrintInstructionTables) {
|
2018-07-15 07:52:50 +08:00
|
|
|
// Create a pipeline, stages, and a printer.
|
2018-11-09 01:32:45 +08:00
|
|
|
auto P = make_unique<mca::Pipeline>();
|
|
|
|
P->appendStage(make_unique<mca::FetchStage>(S));
|
|
|
|
P->appendStage(make_unique<mca::InstructionTables>(SM));
|
2018-07-15 07:52:50 +08:00
|
|
|
mca::PipelinePrinter Printer(*P);
|
2018-04-10 00:39:52 +08:00
|
|
|
|
2018-07-15 07:52:50 +08:00
|
|
|
// Create the views for this pipeline, execute, and emit a report.
|
2018-04-10 00:39:52 +08:00
|
|
|
if (PrintInstructionInfoView) {
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(
|
|
|
|
make_unique<mca::InstructionInfoView>(*STI, *MCII, Insts, *IP));
|
2018-04-10 00:39:52 +08:00
|
|
|
}
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
|
2018-10-24 18:56:47 +08: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 21:29:22 +08:00
|
|
|
if (!runPipeline(*P))
|
2018-10-24 18:56:47 +08:00
|
|
|
return 1;
|
|
|
|
|
2018-07-15 07:52:50 +08:00
|
|
|
Printer.printReport(TOF->os());
|
2018-04-10 00:39:52 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2018-07-07 02:03:14 +08:00
|
|
|
// Create a basic pipeline simulating an out-of-order backend.
|
|
|
|
auto P = MCA.createDefaultPipeline(PO, IB, S);
|
2018-06-26 00:53:00 +08:00
|
|
|
mca::PipelinePrinter Printer(*P);
|
2018-03-09 21:52:03 +08:00
|
|
|
|
2018-06-15 22:01:43 +08:00
|
|
|
if (PrintSummaryView)
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::SummaryView>(SM, Insts, Width));
|
2018-06-15 22:01:43 +08:00
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
if (PrintInstructionInfoView)
|
|
|
|
Printer.addView(
|
2018-11-09 01:32:45 +08:00
|
|
|
make_unique<mca::InstructionInfoView>(*STI, *MCII, Insts, *IP));
|
2018-03-24 03:40:04 +08:00
|
|
|
|
2018-04-10 22:55:14 +08:00
|
|
|
if (PrintDispatchStats)
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::DispatchStatistics>());
|
2018-04-10 22:55:14 +08:00
|
|
|
|
2018-04-11 20:12:53 +08:00
|
|
|
if (PrintSchedulerStats)
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::SchedulerStatistics>(*STI));
|
2018-04-11 19:37:46 +08:00
|
|
|
|
2018-04-11 20:12:53 +08:00
|
|
|
if (PrintRetireStats)
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::RetireControlUnitStatistics>());
|
2018-03-09 00:08:43 +08:00
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
if (PrintRegisterFileStats)
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::RegisterFileStatistics>(*STI));
|
2018-03-09 00:08:43 +08:00
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
if (PrintResourcePressureView)
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
|
2018-04-04 00:46:23 +08:00
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
if (PrintTimelineView) {
|
2018-10-26 18:48:04 +08:00
|
|
|
unsigned TimelineIterations =
|
|
|
|
TimelineMaxIterations ? TimelineMaxIterations : 10;
|
2018-11-09 01:32:45 +08:00
|
|
|
Printer.addView(make_unique<mca::TimelineView>(
|
2018-10-26 18:48:04 +08:00
|
|
|
*STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()),
|
|
|
|
TimelineMaxCycles));
|
2018-04-10 00:39:52 +08:00
|
|
|
}
|
2018-03-09 00:08:43 +08: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 21:29:22 +08:00
|
|
|
if (!runPipeline(*P))
|
2018-10-24 18:56:47 +08:00
|
|
|
return 1;
|
|
|
|
|
2018-04-10 00:39:52 +08:00
|
|
|
Printer.printReport(TOF->os());
|
2018-07-03 04:39:57 +08:00
|
|
|
|
|
|
|
// Clear the InstrBuilder internal state in preparation for another round.
|
|
|
|
IB.clear();
|
2018-03-09 00:08:43 +08:00
|
|
|
}
|
2018-03-08 21:05:02 +08:00
|
|
|
|
2018-03-09 00:08:43 +08:00
|
|
|
TOF->keep();
|
2018-03-08 21:05:02 +08:00
|
|
|
return 0;
|
|
|
|
}
|