|
13 | 13 | //===----------------------------------------------------------------------===// |
14 | 14 |
|
15 | 15 | #include "llvm/CodeGen/CommandFlags.h" |
| 16 | +#include "llvm/ADT/SmallString.h" |
| 17 | +#include "llvm/ADT/Statistic.h" |
16 | 18 | #include "llvm/ADT/StringExtras.h" |
| 19 | +#include "llvm/ADT/StringRef.h" |
17 | 20 | #include "llvm/IR/Instructions.h" |
18 | 21 | #include "llvm/IR/Intrinsics.h" |
19 | 22 | #include "llvm/IR/Module.h" |
20 | 23 | #include "llvm/MC/MCTargetOptionsCommandFlags.h" |
21 | 24 | #include "llvm/MC/TargetRegistry.h" |
22 | 25 | #include "llvm/Support/CommandLine.h" |
| 26 | +#include "llvm/Support/FileSystem.h" |
23 | 27 | #include "llvm/Support/MemoryBuffer.h" |
| 28 | +#include "llvm/Support/Path.h" |
| 29 | +#include "llvm/Support/WithColor.h" |
| 30 | +#include "llvm/Support/raw_ostream.h" |
24 | 31 | #include "llvm/Target/TargetMachine.h" |
25 | 32 | #include "llvm/TargetParser/Host.h" |
26 | 33 | #include "llvm/TargetParser/SubtargetFeature.h" |
27 | 34 | #include "llvm/TargetParser/Triple.h" |
| 35 | +#include <cassert> |
| 36 | +#include <memory> |
28 | 37 | #include <optional> |
| 38 | +#include <system_error> |
29 | 39 |
|
30 | 40 | using namespace llvm; |
31 | 41 |
|
32 | 42 | #define CGOPT(TY, NAME) \ |
33 | 43 | static cl::opt<TY> *NAME##View; \ |
34 | 44 | TY codegen::get##NAME() { \ |
35 | | - assert(NAME##View && "RegisterCodeGenFlags not created."); \ |
| 45 | + assert(NAME##View && "Flag not registered."); \ |
36 | 46 | return *NAME##View; \ |
37 | 47 | } |
38 | 48 |
|
39 | 49 | #define CGLIST(TY, NAME) \ |
40 | 50 | static cl::list<TY> *NAME##View; \ |
41 | 51 | std::vector<TY> codegen::get##NAME() { \ |
42 | | - assert(NAME##View && "RegisterCodeGenFlags not created."); \ |
| 52 | + assert(NAME##View && "Flag not registered."); \ |
43 | 53 | return *NAME##View; \ |
44 | 54 | } |
45 | 55 |
|
@@ -110,13 +120,14 @@ CGOPT(bool, DebugStrictDwarf) |
110 | 120 | CGOPT(unsigned, AlignLoops) |
111 | 121 | CGOPT(bool, JMCInstrument) |
112 | 122 | CGOPT(bool, XCOFFReadOnlyPointers) |
| 123 | +CGOPT(codegen::SaveStatsMode, SaveStats) |
113 | 124 |
|
114 | | -codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { |
115 | 125 | #define CGBINDOPT(NAME) \ |
116 | 126 | do { \ |
117 | 127 | NAME##View = std::addressof(NAME); \ |
118 | 128 | } while (0) |
119 | 129 |
|
| 130 | +codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { |
120 | 131 | static cl::opt<std::string> MArch( |
121 | 132 | "march", cl::desc("Architecture to generate code for (see --version)")); |
122 | 133 | CGBINDOPT(MArch); |
@@ -518,11 +529,25 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { |
518 | 529 | cl::init(false)); |
519 | 530 | CGBINDOPT(DisableIntegratedAS); |
520 | 531 |
|
521 | | -#undef CGBINDOPT |
522 | | - |
523 | 532 | mc::RegisterMCTargetOptionsFlags(); |
524 | 533 | } |
525 | 534 |
|
| 535 | +codegen::RegisterSaveStatsFlag::RegisterSaveStatsFlag() { |
| 536 | + static cl::opt<SaveStatsMode> SaveStats( |
| 537 | + "save-stats", |
| 538 | + cl::desc( |
| 539 | + "Save LLVM statistics to a file in the current directory" |
| 540 | + "(`-save-stats`/`-save-stats=cwd`) or the directory of the output" |
| 541 | + "file (`-save-stats=obj`). (default: cwd)"), |
| 542 | + cl::values(clEnumValN(SaveStatsMode::Cwd, "cwd", |
| 543 | + "Save to the current working directory"), |
| 544 | + clEnumValN(SaveStatsMode::Cwd, "", ""), |
| 545 | + clEnumValN(SaveStatsMode::Obj, "obj", |
| 546 | + "Save to the output file directory")), |
| 547 | + cl::init(SaveStatsMode::None), cl::ValueOptional); |
| 548 | + CGBINDOPT(SaveStats); |
| 549 | +} |
| 550 | + |
526 | 551 | llvm::BasicBlockSection |
527 | 552 | codegen::getBBSectionsMode(llvm::TargetOptions &Options) { |
528 | 553 | if (getBBSections() == "all") |
@@ -768,3 +793,42 @@ codegen::createTargetMachineForTriple(StringRef TargetTriple, |
768 | 793 | TargetTriple); |
769 | 794 | return std::unique_ptr<TargetMachine>(Target); |
770 | 795 | } |
| 796 | + |
| 797 | +void codegen::MaybeEnableStatistics() { |
| 798 | + if (getSaveStats() == SaveStatsMode::None) |
| 799 | + return; |
| 800 | + |
| 801 | + llvm::EnableStatistics(false); |
| 802 | +} |
| 803 | + |
| 804 | +int codegen::MaybeSaveStatistics(StringRef OutputFilename, StringRef ToolName) { |
| 805 | + auto SaveStatsValue = getSaveStats(); |
| 806 | + if (SaveStatsValue == codegen::SaveStatsMode::None) |
| 807 | + return 0; |
| 808 | + |
| 809 | + SmallString<128> StatsFilename; |
| 810 | + if (SaveStatsValue == codegen::SaveStatsMode::Obj) { |
| 811 | + StatsFilename = OutputFilename; |
| 812 | + llvm::sys::path::remove_filename(StatsFilename); |
| 813 | + } else { |
| 814 | + assert(SaveStatsValue == codegen::SaveStatsMode::Cwd && |
| 815 | + "Should have been a valid --save-stats value"); |
| 816 | + } |
| 817 | + |
| 818 | + auto BaseName = llvm::sys::path::filename(OutputFilename); |
| 819 | + llvm::sys::path::append(StatsFilename, BaseName); |
| 820 | + llvm::sys::path::replace_extension(StatsFilename, "stats"); |
| 821 | + |
| 822 | + auto FileFlags = llvm::sys::fs::OF_TextWithCRLF; |
| 823 | + std::error_code EC; |
| 824 | + auto StatsOS = |
| 825 | + std::make_unique<llvm::raw_fd_ostream>(StatsFilename, EC, FileFlags); |
| 826 | + if (EC) { |
| 827 | + WithColor::error(errs(), ToolName) |
| 828 | + << "Unable to open statistics file: " << EC.message() << "\n"; |
| 829 | + return 1; |
| 830 | + } |
| 831 | + |
| 832 | + llvm::PrintStatisticsJSON(*StatsOS); |
| 833 | + return 0; |
| 834 | +} |
0 commit comments