|
15 | 15 | #include "NewPMDriver.h" |
16 | 16 | #include "llvm/ADT/STLExtras.h" |
17 | 17 | #include "llvm/ADT/ScopeExit.h" |
| 18 | +#include "llvm/ADT/Statistic.h" |
18 | 19 | #include "llvm/Analysis/TargetLibraryInfo.h" |
19 | 20 | #include "llvm/CAS/ObjectStore.h" |
20 | 21 | #include "llvm/CodeGen/CommandFlags.h" |
|
45 | 46 | #include "llvm/Support/FileSystem.h" |
46 | 47 | #include "llvm/Support/FormattedStream.h" |
47 | 48 | #include "llvm/Support/InitLLVM.h" |
| 49 | +#include "llvm/Support/Path.h" |
48 | 50 | #include "llvm/Support/PluginLoader.h" |
49 | 51 | #include "llvm/Support/Process.h" |
50 | 52 | #include "llvm/Support/SourceMgr.h" |
|
58 | 60 | #include "llvm/TargetParser/SubtargetFeature.h" |
59 | 61 | #include "llvm/TargetParser/Triple.h" |
60 | 62 | #include "llvm/Transforms/Utils/Cloning.h" |
| 63 | +#include <cassert> |
61 | 64 | #include <memory> |
62 | 65 | #include <optional> |
63 | 66 | using namespace llvm; |
@@ -200,6 +203,20 @@ static cl::opt<std::string> RemarksFormat( |
200 | 203 | cl::desc("The format used for serializing remarks (default: YAML)"), |
201 | 204 | cl::value_desc("format"), cl::init("yaml")); |
202 | 205 |
|
| 206 | +enum SaveStatsMode { None, Cwd, Obj }; |
| 207 | + |
| 208 | +static cl::opt<SaveStatsMode> SaveStats( |
| 209 | + "save-stats", |
| 210 | + cl::desc("Save LLVM statistics to a file in the current directory" |
| 211 | + "(`-save-stats`/`-save-stats=cwd`) or the directory of the output" |
| 212 | + "file (`-save-stats=obj`). (default: cwd)"), |
| 213 | + cl::values(clEnumValN(SaveStatsMode::Cwd, "cwd", |
| 214 | + "Save to the current working directory"), |
| 215 | + clEnumValN(SaveStatsMode::Cwd, "", ""), |
| 216 | + clEnumValN(SaveStatsMode::Obj, "obj", |
| 217 | + "Save to the output file directory")), |
| 218 | + cl::init(SaveStatsMode::None), cl::ValueOptional); |
| 219 | + |
203 | 220 | static cl::opt<bool> EnableNewPassManager( |
204 | 221 | "enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false)); |
205 | 222 |
|
@@ -262,7 +279,8 @@ static cl::opt<RunPassOption, true, cl::parser<std::string>> RunPass( |
262 | 279 | cl::desc("Run compiler only for specified passes (comma separated list)"), |
263 | 280 | cl::value_desc("pass-name"), cl::location(RunPassOpt)); |
264 | 281 |
|
265 | | -static int compileModule(char **, LLVMContext &); |
| 282 | +static int compileModule(char **argv, LLVMContext &Context, |
| 283 | + std::string &OutputFilename); |
266 | 284 |
|
267 | 285 | [[noreturn]] static void reportError(Twine Msg, StringRef Filename = "") { |
268 | 286 | SmallString<256> Prefix; |
@@ -373,6 +391,45 @@ static void verifyCASOptions(const Triple &TheTriple) { |
373 | 391 | } |
374 | 392 | // END MCCAS |
375 | 393 |
|
| 394 | +static int MaybeEnableStats() { |
| 395 | + if (SaveStats == SaveStatsMode::None) |
| 396 | + return 0; |
| 397 | + |
| 398 | + llvm::EnableStatistics(false); |
| 399 | + return 0; |
| 400 | +} |
| 401 | + |
| 402 | +static int MaybeSaveStats(std::string &&OutputFilename) { |
| 403 | + if (SaveStats == SaveStatsMode::None) |
| 404 | + return 0; |
| 405 | + |
| 406 | + SmallString<128> StatsFilename; |
| 407 | + if (SaveStats == SaveStatsMode::Obj) { |
| 408 | + StatsFilename = OutputFilename; |
| 409 | + llvm::sys::path::remove_filename(StatsFilename); |
| 410 | + } else { |
| 411 | + assert(SaveStats == SaveStatsMode::Cwd && |
| 412 | + "Should have been a valid --save-stats value"); |
| 413 | + } |
| 414 | + |
| 415 | + auto BaseName = llvm::sys::path::filename(OutputFilename); |
| 416 | + llvm::sys::path::append(StatsFilename, BaseName); |
| 417 | + llvm::sys::path::replace_extension(StatsFilename, "stats"); |
| 418 | + |
| 419 | + auto FileFlags = llvm::sys::fs::OF_TextWithCRLF; |
| 420 | + std::error_code EC; |
| 421 | + auto StatsOS = |
| 422 | + std::make_unique<llvm::raw_fd_ostream>(StatsFilename, EC, FileFlags); |
| 423 | + if (EC) { |
| 424 | + WithColor::error(errs(), "llc") |
| 425 | + << "Unable to open statistics file: " << EC.message() << "\n"; |
| 426 | + return 1; |
| 427 | + } |
| 428 | + |
| 429 | + llvm::PrintStatisticsJSON(*StatsOS); |
| 430 | + return 0; |
| 431 | +} |
| 432 | + |
376 | 433 | // main - Entry point for the llc compiler. |
377 | 434 | // |
378 | 435 | int main(int argc, char **argv) { |
@@ -450,18 +507,23 @@ int main(int argc, char **argv) { |
450 | 507 | reportError(std::move(E), RemarksFilename); |
451 | 508 | std::unique_ptr<ToolOutputFile> RemarksFile = std::move(*RemarksFileOrErr); |
452 | 509 |
|
| 510 | + if (int RetVal = MaybeEnableStats()) |
| 511 | + return RetVal; |
| 512 | + std::string OutputFilename; |
| 513 | + |
453 | 514 | if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir") |
454 | 515 | reportError("input language must be '', 'IR' or 'MIR'"); |
455 | 516 |
|
456 | 517 | // Compile the module TimeCompilations times to give better compile time |
457 | 518 | // metrics. |
458 | 519 | for (unsigned I = TimeCompilations; I; --I) |
459 | | - if (int RetVal = compileModule(argv, Context)) |
| 520 | + if (int RetVal = compileModule(argv, Context, OutputFilename)) |
460 | 521 | return RetVal; |
461 | 522 |
|
462 | 523 | if (RemarksFile) |
463 | 524 | RemarksFile->keep(); |
464 | | - return 0; |
| 525 | + |
| 526 | + return MaybeSaveStats(std::move(OutputFilename)); |
465 | 527 | } |
466 | 528 |
|
467 | 529 | static bool addPass(PassManagerBase &PM, const char *argv0, |
@@ -493,7 +555,8 @@ static bool addPass(PassManagerBase &PM, const char *argv0, |
493 | 555 | return false; |
494 | 556 | } |
495 | 557 |
|
496 | | -static int compileModule(char **argv, LLVMContext &Context) { |
| 558 | +static int compileModule(char **argv, LLVMContext &Context, |
| 559 | + std::string &OutputFilename) { |
497 | 560 | // Load the module to be compiled... |
498 | 561 | SMDiagnostic Err; |
499 | 562 | std::unique_ptr<Module> M; |
@@ -678,6 +741,9 @@ static int compileModule(char **argv, LLVMContext &Context) { |
678 | 741 | // Ensure the filename is passed down to CodeViewDebug. |
679 | 742 | Target->Options.ObjectFilenameForDebug = Out->outputFilename(); |
680 | 743 |
|
| 744 | + // Return a copy of the output filename via the output param |
| 745 | + OutputFilename = Out->outputFilename(); |
| 746 | + |
681 | 747 | // Tell target that this tool is not necessarily used with argument ABI |
682 | 748 | // compliance (i.e. narrow integer argument extensions). |
683 | 749 | Target->Options.VerifyArgABICompliance = 0; |
|
0 commit comments