LLVM 20.0.0git
Statistic.cpp
Go to the documentation of this file.
1//===-- Statistic.cpp - Easy way to expose stats information --------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the 'Statistic' class, which is designed to be an easy
10// way to expose various success metrics from passes. These statistics are
11// printed at the end of a run, when the -stats command line option is enabled
12// on the command line.
13//
14// This is useful for reporting information like the number of instructions
15// simplified, optimized or removed by various transformations, like this:
16//
17// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
18//
19// Later, in the code: ++NumInstEliminated;
20//
21//===----------------------------------------------------------------------===//
22
23#include "llvm/ADT/Statistic.h"
24
25#include "DebugOptions.h"
26
30#include "llvm/Support/Debug.h"
31#include "llvm/Support/Format.h"
33#include "llvm/Support/Mutex.h"
34#include "llvm/Support/Timer.h"
37#include <algorithm>
38#include <cstring>
39using namespace llvm;
40
41/// -stats - Command line option to cause transformations to emit stats about
42/// what they did.
43///
44static bool EnableStats;
45static bool StatsAsJSON;
46static bool Enabled;
47static bool PrintOnExit;
48
50 static cl::opt<bool, true> registerEnableStats{
51 "stats",
53 "Enable statistics output from program (available with Asserts)"),
55 static cl::opt<bool, true> registerStatsAsJson{
56 "stats-json", cl::desc("Display statistics as json data"),
58}
59
60namespace {
61/// This class is used in a ManagedStatic so that it is created on demand (when
62/// the first statistic is bumped) and destroyed only when llvm_shutdown is
63/// called. We print statistics from the destructor.
64/// This class is also used to look up statistic values from applications that
65/// use LLVM.
66class StatisticInfo {
67 std::vector<TrackingStatistic *> Stats;
68
69 friend void llvm::PrintStatistics();
72
73 /// Sort statistics by debugtype,name,description.
74 void sort();
75public:
76 using const_iterator = std::vector<TrackingStatistic *>::const_iterator;
77
78 StatisticInfo();
79 ~StatisticInfo();
80
81 void addStatistic(TrackingStatistic *S) { Stats.push_back(S); }
82
83 const_iterator begin() const { return Stats.begin(); }
84 const_iterator end() const { return Stats.end(); }
85 iterator_range<const_iterator> statistics() const {
86 return {begin(), end()};
87 }
88
89 void reset();
90};
91} // end anonymous namespace
92
95
96/// RegisterStatistic - The first time a statistic is bumped, this method is
97/// called.
99 // If stats are enabled, inform StatInfo that this statistic should be
100 // printed.
101 // llvm_shutdown calls destructors while holding the ManagedStatic mutex.
102 // These destructors end up calling PrintStatistics, which takes StatLock.
103 // Since dereferencing StatInfo and StatLock can require taking the
104 // ManagedStatic mutex, doing so with StatLock held would lead to a lock
105 // order inversion. To avoid that, we dereference the ManagedStatics first,
106 // and only take StatLock afterwards.
107 if (!Initialized.load(std::memory_order_relaxed)) {
109 StatisticInfo &SI = *StatInfo;
110 sys::SmartScopedLock<true> Writer(Lock);
111 // Check Initialized again after acquiring the lock.
112 if (Initialized.load(std::memory_order_relaxed))
113 return;
114 if (EnableStats || Enabled)
115 SI.addStatistic(this);
116
117 // Remember we have been registered.
118 Initialized.store(true, std::memory_order_release);
119 }
120}
121
122StatisticInfo::StatisticInfo() {
123 // Ensure that necessary timer global objects are created first so they are
124 // destructed after us.
126}
127
128// Print information when destroyed, iff command line option is specified.
129StatisticInfo::~StatisticInfo() {
132}
133
134void llvm::EnableStatistics(bool DoPrintOnExit) {
135 Enabled = true;
136 PrintOnExit = DoPrintOnExit;
137}
138
140
141void StatisticInfo::sort() {
143 Stats, [](const TrackingStatistic *LHS, const TrackingStatistic *RHS) {
144 if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
145 return Cmp < 0;
146
147 if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
148 return Cmp < 0;
149
150 return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
151 });
152}
153
154void StatisticInfo::reset() {
156
157 // Tell each statistic that it isn't registered so it has to register
158 // again. We're holding the lock so it won't be able to do so until we're
159 // finished. Once we've forced it to re-register (after we return), then zero
160 // the value.
161 for (auto *Stat : Stats) {
162 // Value updates to a statistic that complete before this statement in the
163 // iteration for that statistic will be lost as intended.
164 Stat->Initialized = false;
165 Stat->Value = 0;
166 }
167
168 // Clear the registration list and release the lock once we're done. Any
169 // pending updates from other threads will safely take effect after we return.
170 // That might not be what the user wants if they're measuring a compilation
171 // but it's their responsibility to prevent concurrent compilations to make
172 // a single compilation measurable.
173 Stats.clear();
174}
175
177 StatisticInfo &Stats = *StatInfo;
178
179 // Figure out how long the biggest Value and Name fields are.
180 unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
181 for (TrackingStatistic *Stat : Stats.Stats) {
182 MaxValLen = std::max(MaxValLen, (unsigned)utostr(Stat->getValue()).size());
183 MaxDebugTypeLen =
184 std::max(MaxDebugTypeLen, (unsigned)std::strlen(Stat->getDebugType()));
185 }
186
187 Stats.sort();
188
189 // Print out the statistics header...
190 OS << "===" << std::string(73, '-') << "===\n"
191 << " ... Statistics Collected ...\n"
192 << "===" << std::string(73, '-') << "===\n\n";
193
194 // Print all of the statistics.
195 for (TrackingStatistic *Stat : Stats.Stats)
196 OS << format("%*" PRIu64 " %-*s - %s\n", MaxValLen, Stat->getValue(),
197 MaxDebugTypeLen, Stat->getDebugType(), Stat->getDesc());
198
199 OS << '\n'; // Flush the output stream.
200 OS.flush();
201}
202
205 StatisticInfo &Stats = *StatInfo;
206
207 Stats.sort();
208
209 // Print all of the statistics.
210 OS << "{\n";
211 const char *delim = "";
212 for (const TrackingStatistic *Stat : Stats.Stats) {
213 OS << delim;
214 assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
215 "Statistic group/type name is simple.");
216 assert(yaml::needsQuotes(Stat->getName()) == yaml::QuotingType::None &&
217 "Statistic name is simple");
218 OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
219 << Stat->getValue();
220 delim = ",\n";
221 }
222 // Print timers.
224
225 OS << "\n}\n";
226 OS.flush();
227}
228
230#if LLVM_ENABLE_STATS
232 StatisticInfo &Stats = *StatInfo;
233
234 // Statistics not enabled?
235 if (Stats.Stats.empty()) return;
236
237 // Get the stream to write to.
238 std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
239 if (StatsAsJSON)
240 PrintStatisticsJSON(*OutStream);
241 else
242 PrintStatistics(*OutStream);
243
244#else
245 // Check if the -stats option is set instead of checking
246 // !Stats.Stats.empty(). In release builds, Statistics operators
247 // do nothing, so stats are never Registered.
248 if (EnableStats) {
249 // Get the stream to write to.
250 std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
251 (*OutStream) << "Statistics are disabled. "
252 << "Build with asserts or with -DLLVM_FORCE_ENABLE_STATS\n";
253 }
254#endif
255}
256
257std::vector<std::pair<StringRef, uint64_t>> llvm::GetStatistics() {
259 std::vector<std::pair<StringRef, uint64_t>> ReturnStats;
260
261 for (const auto &Stat : StatInfo->statistics())
262 ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
263 return ReturnStats;
264}
265
267 StatInfo->reset();
268}
block placement Basic Block Placement Stats
if(PassOpts->AAPipeline)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static bool EnableStats
-stats - Command line option to cause transformations to emit stats about what they did.
Definition: Statistic.cpp:44
static bool PrintOnExit
Definition: Statistic.cpp:47
static bool Enabled
Definition: Statistic.cpp:46
static ManagedStatic< StatisticInfo > StatInfo
Definition: Statistic.cpp:93
static bool StatsAsJSON
Definition: Statistic.cpp:45
static ManagedStatic< sys::SmartMutex< true > > StatLock
Definition: Statistic.cpp:94
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
This file contains some functions that are useful when dealing with strings.
Value * RHS
Value * LHS
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
static const char * printAllJSONValues(raw_ostream &OS, const char *delim)
Prints all timers as JSON key/value pairs.
Definition: Timer.cpp:495
static void constructForStatistics()
Ensure global objects required for statistics printing are initialized.
Definition: Timer.cpp:502
std::atomic< bool > Initialized
Definition: Statistic.h:56
void RegisterStatistic()
RegisterStatistic - The first time a statistic is bumped, this method is called.
Definition: Statistic.cpp:98
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
SmartMutex - A mutex with a compile time constant parameter that indicates whether this mutex should ...
Definition: Mutex.h:28
LocationClass< Ty > location(Ty &L)
Definition: CommandLine.h:463
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:235
std::lock_guard< SmartMutex< mt_only > > SmartScopedLock
Definition: Mutex.h:69
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void stable_sort(R &&Range)
Definition: STLExtras.h:2037
std::unique_ptr< raw_ostream > CreateInfoOutputFile()
Return a stream to print our output on.
Definition: Timer.cpp:96
void ResetStatistics()
Reset the statistics.
Definition: Statistic.cpp:266
void EnableStatistics(bool DoPrintOnExit=true)
Enable the collection and printing of statistics.
Definition: Statistic.cpp:134
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1664
bool AreStatisticsEnabled()
Check if statistics are enabled.
Definition: Statistic.cpp:139
void initStatisticOptions()
Definition: Statistic.cpp:49
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
void PrintStatistics()
Print statistics to the file returned by CreateInfoOutputFile().
Definition: Statistic.cpp:229
std::vector< std::pair< StringRef, uint64_t > > GetStatistics()
Get the statistics.
Definition: Statistic.cpp:257
void PrintStatisticsJSON(raw_ostream &OS)
Print statistics in JSON format.
Definition: Statistic.cpp:203