Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/docs/CommandGuide/llc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,12 @@ End-user Options

Print statistics recorded by code-generation passes.

.. option:: --save-stats, --save-stats=cwd, --save-stats=obj

Save LLVM statistics to a file in the current directory
(:option:`--save-stats`/"--save-stats=cwd") or the directory
of the output file ("--save-stats=obj") in JSON format.

.. option:: --time-passes

Record the amount of time needed for each pass and print a report to standard
Expand Down
1 change: 1 addition & 0 deletions llvm/docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ Changes to the LLVM tools
* `llvm-readelf` now dumps all hex format values in lower-case mode.
* Some code paths for supporting Python 2.7 in `llvm-lit` have been removed.
* Support for `%T` in lit has been removed.
* Add `--save-stats` option to `llc` to save LLVM statistics to a file. Compatible with the Clang option.

Changes to LLDB
---------------------------------
Expand Down
15 changes: 15 additions & 0 deletions llvm/test/tools/llc/save-stats.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
; REQUIRES: asserts

; RUN: llc -mtriple=arm64-apple-macosx --save-stats=obj -o %t.s %s && cat %t.stats | FileCheck %s
; RUN: llc -mtriple=arm64-apple-macosx --save-stats=cwd -o %t.s %s && cat %{t:stem}.tmp.stats | FileCheck %s
; RUN: llc -mtriple=arm64-apple-macosx --save-stats -o %t.s %s && cat %{t:stem}.tmp.stats | FileCheck %s
; RUN: not llc -mtriple=arm64-apple-macosx --save-stats=invalid -o %t.s %s 2>&1 | FileCheck %s --check-prefix=INVALID_ARG

; CHECK: {
; CHECK: "asm-printer.EmittedInsts":
; CHECK: }

; INVALID_ARG: {{.*}}llc{{.*}}: for the --save-stats option: Cannot find option named 'invalid'!
define i32 @func() {
ret i32 0
}
74 changes: 70 additions & 4 deletions llvm/tools/llc/llc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "NewPMDriver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
Expand Down Expand Up @@ -45,6 +46,7 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/PGOOptions.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetSelect.h"
Expand All @@ -57,6 +59,7 @@
#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include <cassert>
#include <memory>
#include <optional>
using namespace llvm;
Expand Down Expand Up @@ -203,6 +206,20 @@ static cl::opt<std::string> RemarksFormat(
cl::desc("The format used for serializing remarks (default: YAML)"),
cl::value_desc("format"), cl::init("yaml"));

enum SaveStatsMode { None, Cwd, Obj };

static cl::opt<SaveStatsMode> SaveStats(
"save-stats",
cl::desc("Save LLVM statistics to a file in the current directory"
"(`-save-stats`/`-save-stats=cwd`) or the directory of the output"
"file (`-save-stats=obj`). (default: cwd)"),
cl::values(clEnumValN(SaveStatsMode::Cwd, "cwd",
"Save to the current working directory"),
clEnumValN(SaveStatsMode::Cwd, "", ""),
clEnumValN(SaveStatsMode::Obj, "obj",
"Save to the output file directory")),
cl::init(SaveStatsMode::None), cl::ValueOptional);

static cl::opt<bool> EnableNewPassManager(
"enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false));

Expand Down Expand Up @@ -276,7 +293,8 @@ static void setPGOOptions(TargetMachine &TM) {
TM.setPGOOption(PGOOpt);
}

static int compileModule(char **, LLVMContext &);
static int compileModule(char **argv, LLVMContext &Context,
std::string &OutputFilename);

[[noreturn]] static void reportError(Twine Msg, StringRef Filename = "") {
SmallString<256> Prefix;
Expand Down Expand Up @@ -355,6 +373,45 @@ static std::unique_ptr<ToolOutputFile> GetOutputStream(const char *TargetName,
return FDOut;
}

static int MaybeEnableStats() {
if (SaveStats == SaveStatsMode::None)
return 0;

llvm::EnableStatistics(false);
return 0;
}

static int MaybeSaveStats(std::string &&OutputFilename) {
if (SaveStats == SaveStatsMode::None)
return 0;

SmallString<128> StatsFilename;
if (SaveStats == SaveStatsMode::Obj) {
StatsFilename = OutputFilename;
llvm::sys::path::remove_filename(StatsFilename);
} else {
assert(SaveStats == SaveStatsMode::Cwd &&
"Should have been a valid --save-stats value");
}

auto BaseName = llvm::sys::path::filename(OutputFilename);
llvm::sys::path::append(StatsFilename, BaseName);
llvm::sys::path::replace_extension(StatsFilename, "stats");

auto FileFlags = llvm::sys::fs::OF_TextWithCRLF;
std::error_code EC;
auto StatsOS =
std::make_unique<llvm::raw_fd_ostream>(StatsFilename, EC, FileFlags);
if (EC) {
WithColor::error(errs(), "llc")
<< "Unable to open statistics file: " << EC.message() << "\n";
return 1;
}

llvm::PrintStatisticsJSON(*StatsOS);
return 0;
}

// main - Entry point for the llc compiler.
//
int main(int argc, char **argv) {
Expand Down Expand Up @@ -432,18 +489,23 @@ int main(int argc, char **argv) {
reportError(std::move(E), RemarksFilename);
LLVMRemarkFileHandle RemarksFile = std::move(*RemarksFileOrErr);

if (int RetVal = MaybeEnableStats())
return RetVal;
std::string OutputFilename;

if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir")
reportError("input language must be '', 'IR' or 'MIR'");

// Compile the module TimeCompilations times to give better compile time
// metrics.
for (unsigned I = TimeCompilations; I; --I)
if (int RetVal = compileModule(argv, Context))
if (int RetVal = compileModule(argv, Context, OutputFilename))
return RetVal;

if (RemarksFile)
RemarksFile->keep();
return 0;

return MaybeSaveStats(std::move(OutputFilename));
}

static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName,
Expand Down Expand Up @@ -475,7 +537,8 @@ static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName,
return false;
}

static int compileModule(char **argv, LLVMContext &Context) {
static int compileModule(char **argv, LLVMContext &Context,
std::string &OutputFilename) {
// Load the module to be compiled...
SMDiagnostic Err;
std::unique_ptr<Module> M;
Expand Down Expand Up @@ -659,6 +722,9 @@ static int compileModule(char **argv, LLVMContext &Context) {
// Ensure the filename is passed down to CodeViewDebug.
Target->Options.ObjectFilenameForDebug = Out->outputFilename();

// Return a copy of the output filename via the output param
OutputFilename = Out->outputFilename();

// Tell target that this tool is not necessarily used with argument ABI
// compliance (i.e. narrow integer argument extensions).
Target->Options.VerifyArgABICompliance = 0;
Expand Down