forked from OSchip/llvm-project
[BOLT] Refactor heatmap to be standalone tool
Separate heatmap from bolt and build it as standalone tool. Reviewed By: maksfb Differential Revision: https://reviews.llvm.org/D118946
This commit is contained in:
parent
0e7d7fe912
commit
5c2ae5f454
|
@ -23,11 +23,10 @@ $ perf record -e cycles:u -j any,u [-p PID|-a] -- sleep <interval>
|
|||
Note that at the moment running with LBR (`-j any,u` or `-b`) is
|
||||
a requirement.
|
||||
|
||||
Once the run is complete, and `perf.data` is generated, run BOLT in
|
||||
a heatmap mode:
|
||||
Once the run is complete, and `perf.data` is generated, run llvm-bolt-heatmap:
|
||||
|
||||
```bash
|
||||
$ llvm-bolt heatmap -p perf.data <executable>
|
||||
$ llvm-bolt-heatmap -p perf.data <executable>
|
||||
```
|
||||
|
||||
By default the heatmap will be dumped to *stdout*. You can change it
|
||||
|
|
|
@ -27,8 +27,7 @@ extern llvm::cl::OptionCategory BoltRelocCategory;
|
|||
extern llvm::cl::OptionCategory BoltOutputCategory;
|
||||
extern llvm::cl::OptionCategory AggregatorCategory;
|
||||
extern llvm::cl::OptionCategory BoltInstrCategory;
|
||||
|
||||
extern llvm::cl::SubCommand HeatmapCommand;
|
||||
extern llvm::cl::OptionCategory HeatmapCategory;
|
||||
|
||||
extern llvm::cl::opt<unsigned> AlignText;
|
||||
extern llvm::cl::opt<bool> AggregateOnly;
|
||||
|
@ -38,7 +37,6 @@ extern llvm::cl::opt<bool> EnableBAT;
|
|||
extern llvm::cl::opt<bool> RemoveSymtab;
|
||||
extern llvm::cl::opt<unsigned> ExecutionCountThreshold;
|
||||
extern llvm::cl::opt<unsigned> HeatmapBlock;
|
||||
extern llvm::cl::opt<std::string> HeatmapFile;
|
||||
extern llvm::cl::opt<unsigned long long> HeatmapMaxAddress;
|
||||
extern llvm::cl::opt<unsigned long long> HeatmapMinAddress;
|
||||
extern llvm::cl::opt<bool> HotData;
|
||||
|
|
|
@ -1348,11 +1348,11 @@ std::error_code DataAggregator::printLBRHeatMap() {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
HM.print(opts::HeatmapFile);
|
||||
if (opts::HeatmapFile == "-")
|
||||
HM.printCDF(opts::HeatmapFile);
|
||||
HM.print(opts::OutputFilename);
|
||||
if (opts::OutputFilename == "-")
|
||||
HM.printCDF(opts::OutputFilename);
|
||||
else
|
||||
HM.printCDF(opts::HeatmapFile + ".csv");
|
||||
HM.printCDF(opts::OutputFilename + ".csv");
|
||||
|
||||
return std::error_code();
|
||||
}
|
||||
|
|
|
@ -33,8 +33,7 @@ cl::OptionCategory BoltRelocCategory("BOLT options in relocation mode");
|
|||
cl::OptionCategory BoltOutputCategory("Output options");
|
||||
cl::OptionCategory AggregatorCategory("Data aggregation options");
|
||||
cl::OptionCategory BoltInstrCategory("BOLT instrumentation options");
|
||||
|
||||
cl::SubCommand HeatmapCommand("heatmap", "generate heatmap");
|
||||
cl::OptionCategory HeatmapCategory("Heatmap options");
|
||||
|
||||
cl::opt<unsigned>
|
||||
AlignText("align-text",
|
||||
|
@ -50,11 +49,9 @@ AggregateOnly("aggregate-only",
|
|||
cl::cat(AggregatorCategory));
|
||||
|
||||
cl::opt<unsigned>
|
||||
BucketsPerLine("line-size",
|
||||
cl::desc("number of entries per line (default 256)"),
|
||||
cl::init(256),
|
||||
cl::Optional,
|
||||
cl::sub(HeatmapCommand));
|
||||
BucketsPerLine("line-size",
|
||||
cl::desc("number of entries per line (default 256)"),
|
||||
cl::init(256), cl::Optional, cl::cat(HeatmapCategory));
|
||||
|
||||
cl::opt<bool>
|
||||
DiffOnly("diff-only",
|
||||
|
@ -83,31 +80,19 @@ ExecutionCountThreshold("execution-count-threshold",
|
|||
cl::cat(BoltOptCategory));
|
||||
|
||||
cl::opt<unsigned>
|
||||
HeatmapBlock("block-size",
|
||||
cl::desc("size of a heat map block in bytes (default 64)"),
|
||||
cl::init(64),
|
||||
cl::sub(HeatmapCommand));
|
||||
HeatmapBlock("block-size",
|
||||
cl::desc("size of a heat map block in bytes (default 64)"),
|
||||
cl::init(64), cl::cat(HeatmapCategory));
|
||||
|
||||
cl::opt<std::string>
|
||||
HeatmapFile("o",
|
||||
cl::init("-"),
|
||||
cl::desc("heatmap output file (default stdout)"),
|
||||
cl::Optional,
|
||||
cl::sub(HeatmapCommand));
|
||||
cl::opt<unsigned long long> HeatmapMaxAddress(
|
||||
"max-address", cl::init(0xffffffff),
|
||||
cl::desc("maximum address considered valid for heatmap (default 4GB)"),
|
||||
cl::Optional, cl::cat(HeatmapCategory));
|
||||
|
||||
cl::opt<unsigned long long>
|
||||
HeatmapMaxAddress("max-address",
|
||||
cl::init(0xffffffff),
|
||||
cl::desc("maximum address considered valid for heatmap (default 4GB)"),
|
||||
cl::Optional,
|
||||
cl::sub(HeatmapCommand));
|
||||
|
||||
cl::opt<unsigned long long>
|
||||
HeatmapMinAddress("min-address",
|
||||
cl::init(0x0),
|
||||
cl::desc("minimum address considered valid for heatmap (default 0)"),
|
||||
cl::Optional,
|
||||
cl::sub(HeatmapCommand));
|
||||
cl::opt<unsigned long long> HeatmapMinAddress(
|
||||
"min-address", cl::init(0x0),
|
||||
cl::desc("minimum address considered valid for heatmap (default 0)"),
|
||||
cl::Optional, cl::cat(HeatmapCategory));
|
||||
|
||||
cl::opt<bool>
|
||||
HotData("hot-data",
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
# Verifies basic functioning of heatmap mode
|
||||
|
||||
REQUIRES: system-linux
|
||||
XFAIL: *
|
||||
|
||||
RUN: llvm-bolt heatmap --help | FileCheck %s --check-prefix=CHECK-SUBCOMMAND
|
||||
CHECK-SUBCOMMAND: SUBCOMMAND 'heatmap': generate heatmap
|
||||
CHECK-SUBCOMMAND: USAGE: llvm-bolt heatmap [options] <executable>
|
||||
|
||||
RUN: llvm-bolt-heatmap --help | FileCheck %s --check-prefix=CHECK-STANDALONE
|
||||
CHECK-STANDALONE: SUBCOMMAND 'heatmap': generate heatmap
|
||||
CHECK-STANDALONE: USAGE: llvm-bolt-heatmap heatmap [options] <executable>
|
||||
RUN: llvm-bolt-heatmap --help | FileCheck %s
|
||||
CHECK: USAGE: llvm-bolt-heatmap [options] <executable>
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
add_subdirectory(driver)
|
||||
add_subdirectory(merge-fdata)
|
||||
add_subdirectory(heatmap)
|
||||
|
|
|
@ -23,13 +23,11 @@ add_llvm_tool(llvm-bolt
|
|||
|
||||
add_llvm_tool_symlink(perf2bolt llvm-bolt)
|
||||
add_llvm_tool_symlink(llvm-boltdiff llvm-bolt)
|
||||
add_llvm_tool_symlink(llvm-bolt-heatmap llvm-bolt)
|
||||
|
||||
set(BOLT_DEPENDS
|
||||
llvm-bolt
|
||||
perf2bolt
|
||||
llvm-boltdiff
|
||||
llvm-bolt-heatmap
|
||||
)
|
||||
|
||||
add_custom_target(bolt DEPENDS ${BOLT_DEPENDS})
|
||||
|
@ -37,7 +35,6 @@ install(PROGRAMS
|
|||
${CMAKE_BINARY_DIR}/bin/llvm-bolt
|
||||
${CMAKE_BINARY_DIR}/bin/perf2bolt
|
||||
${CMAKE_BINARY_DIR}/bin/llvm-boltdiff
|
||||
${CMAKE_BINARY_DIR}/bin/llvm-bolt-heatmap
|
||||
TYPE BIN
|
||||
COMPONENT bolt
|
||||
)
|
||||
|
|
|
@ -125,34 +125,6 @@ void perf2boltMode(int argc, char **argv) {
|
|||
opts::AggregateOnly = true;
|
||||
}
|
||||
|
||||
void heatmapMode(int argc, char **argv) {
|
||||
// Insert a fake subcommand if invoked via a command alias.
|
||||
std::unique_ptr<char *[]> FakeArgv;
|
||||
if (argc == 1 || strcmp(argv[1], "heatmap")) {
|
||||
++argc;
|
||||
FakeArgv.reset(new char *[argc + 1]);
|
||||
FakeArgv[0] = argv[0];
|
||||
FakeArgv[1] = const_cast<char *>("heatmap");
|
||||
for (int I = 2; I < argc; ++I)
|
||||
FakeArgv[I] = argv[I - 1];
|
||||
FakeArgv[argc] = nullptr;
|
||||
argv = FakeArgv.get();
|
||||
}
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv, "");
|
||||
|
||||
if (!sys::fs::exists(opts::InputFilename))
|
||||
report_error(opts::InputFilename, errc::no_such_file_or_directory);
|
||||
|
||||
if (opts::PerfData.empty()) {
|
||||
errs() << ToolName << ": expected -perfdata=<filename> option.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
opts::HeatmapMode = true;
|
||||
opts::AggregateOnly = true;
|
||||
}
|
||||
|
||||
void boltDiffMode(int argc, char **argv) {
|
||||
cl::HideUnrelatedOptions(makeArrayRef(opts::BoltDiffCategories));
|
||||
cl::AddExtraVersionPrinter(printBoltRevision);
|
||||
|
@ -194,8 +166,8 @@ void boltMode(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
std::string GetExecutablePath(const char *Argv0) {
|
||||
SmallString<128> ExecutablePath(Argv0);
|
||||
static std::string GetExecutablePath(const char *Argv0) {
|
||||
SmallString<256> ExecutablePath(Argv0);
|
||||
// Do a PATH lookup if Argv0 isn't a valid path.
|
||||
if (!llvm::sys::fs::exists(ExecutablePath))
|
||||
if (llvm::ErrorOr<std::string> P =
|
||||
|
@ -224,19 +196,10 @@ int main(int argc, char **argv) {
|
|||
|
||||
ToolName = argv[0];
|
||||
|
||||
// Pre-process subcommands.
|
||||
if (argc > 1 && *argv[1] != '-') {
|
||||
if (!strcmp(argv[1], "heatmap"))
|
||||
opts::HeatmapMode = true;
|
||||
}
|
||||
|
||||
if (llvm::sys::path::filename(ToolName) == "perf2bolt")
|
||||
perf2boltMode(argc, argv);
|
||||
else if (llvm::sys::path::filename(ToolName) == "llvm-boltdiff")
|
||||
boltDiffMode(argc, argv);
|
||||
else if (llvm::sys::path::filename(ToolName) == "llvm-bolt-heatmap" ||
|
||||
opts::HeatmapMode)
|
||||
heatmapMode(argc, argv);
|
||||
else
|
||||
boltMode(argc, argv);
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
set(LLVM_LINK_COMPONENTS
|
||||
${LLVM_TARGETS_TO_BUILD}
|
||||
BOLTProfile
|
||||
BOLTRewrite
|
||||
BOLTUtils
|
||||
MC
|
||||
Object
|
||||
Support
|
||||
)
|
||||
|
||||
add_llvm_tool(llvm-bolt-heatmap
|
||||
heatmap.cpp
|
||||
)
|
||||
|
||||
set_target_properties(llvm-bolt-heatmap PROPERTIES FOLDER "BOLT")
|
|
@ -0,0 +1,97 @@
|
|||
#include "bolt/Profile/DataAggregator.h"
|
||||
#include "bolt/Rewrite/RewriteInstance.h"
|
||||
#include "bolt/Utils/CommandLineOpts.h"
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace bolt;
|
||||
|
||||
namespace opts {
|
||||
|
||||
static cl::OptionCategory *HeatmapCategories[] = {&HeatmapCategory,
|
||||
&BoltOutputCategory};
|
||||
|
||||
static cl::opt<std::string> InputFilename(cl::Positional,
|
||||
cl::desc("<executable>"),
|
||||
cl::Required,
|
||||
cl::cat(HeatmapCategory));
|
||||
|
||||
} // namespace opts
|
||||
|
||||
static StringRef ToolName;
|
||||
|
||||
static void report_error(StringRef Message, std::error_code EC) {
|
||||
assert(EC);
|
||||
errs() << ToolName << ": '" << Message << "': " << EC.message() << ".\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void report_error(StringRef Message, Error E) {
|
||||
assert(E);
|
||||
errs() << ToolName << ": '" << Message << "': " << toString(std::move(E))
|
||||
<< ".\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static std::string GetExecutablePath(const char *Argv0) {
|
||||
SmallString<256> ExecutablePath(Argv0);
|
||||
// Do a PATH lookup if Argv0 isn't a valid path.
|
||||
if (!llvm::sys::fs::exists(ExecutablePath))
|
||||
if (llvm::ErrorOr<std::string> P =
|
||||
llvm::sys::findProgramByName(ExecutablePath))
|
||||
ExecutablePath = *P;
|
||||
return std::string(ExecutablePath.str());
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
cl::HideUnrelatedOptions(makeArrayRef(opts::HeatmapCategories));
|
||||
cl::ParseCommandLineOptions(argc, argv, "");
|
||||
|
||||
if (opts::PerfData.empty()) {
|
||||
errs() << ToolName << ": expected -perfdata=<filename> option.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
opts::HeatmapMode = true;
|
||||
opts::AggregateOnly = true;
|
||||
if (!sys::fs::exists(opts::InputFilename))
|
||||
report_error(opts::InputFilename, errc::no_such_file_or_directory);
|
||||
|
||||
// Output to stdout by default
|
||||
if (opts::OutputFilename.empty())
|
||||
opts::OutputFilename = "-";
|
||||
|
||||
// Initialize targets and assembly printers/parsers.
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllAsmParsers();
|
||||
llvm::InitializeAllDisassemblers();
|
||||
|
||||
llvm::InitializeAllTargets();
|
||||
llvm::InitializeAllAsmPrinters();
|
||||
|
||||
ToolName = argv[0];
|
||||
std::string ToolPath = GetExecutablePath(argv[0]);
|
||||
Expected<OwningBinary<Binary>> BinaryOrErr =
|
||||
createBinary(opts::InputFilename);
|
||||
if (Error E = BinaryOrErr.takeError())
|
||||
report_error(opts::InputFilename, std::move(E));
|
||||
Binary &Binary = *BinaryOrErr.get().getBinary();
|
||||
|
||||
if (auto *e = dyn_cast<ELFObjectFileBase>(&Binary)) {
|
||||
RewriteInstance RI(e, argc, argv, ToolPath);
|
||||
if (Error E = RI.setProfile(opts::PerfData))
|
||||
report_error(opts::PerfData, std::move(E));
|
||||
|
||||
RI.run();
|
||||
} else {
|
||||
report_error(opts::InputFilename, object_error::invalid_file_type);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue