Line data Source code
1 : //===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file defines the 'Statistic' class, which is designed to be an easy way
11 : // to expose various metrics from passes. These statistics are printed at the
12 : // end of a run (from llvm_shutdown), when the -stats command line option is
13 : // passed on the command line.
14 : //
15 : // This is useful for reporting information like the number of instructions
16 : // simplified, optimized or removed by various transformations, like this:
17 : //
18 : // static Statistic NumInstsKilled("gcse", "Number of instructions killed");
19 : //
20 : // Later, in the code: ++NumInstsKilled;
21 : //
22 : // NOTE: Statistics *must* be declared as global variables.
23 : //
24 : //===----------------------------------------------------------------------===//
25 :
26 : #ifndef LLVM_ADT_STATISTIC_H
27 : #define LLVM_ADT_STATISTIC_H
28 :
29 : #include "llvm/Config/llvm-config.h"
30 : #include "llvm/Support/Compiler.h"
31 : #include <atomic>
32 : #include <memory>
33 : #include <vector>
34 :
35 : // Determine whether statistics should be enabled. We must do it here rather
36 : // than in CMake because multi-config generators cannot determine this at
37 : // configure time.
38 : #if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS
39 : #define LLVM_ENABLE_STATS 1
40 : #endif
41 :
42 : namespace llvm {
43 :
44 : class raw_ostream;
45 : class raw_fd_ostream;
46 : class StringRef;
47 :
48 : class Statistic {
49 : public:
50 : const char *DebugType;
51 : const char *Name;
52 : const char *Desc;
53 : std::atomic<unsigned> Value;
54 : std::atomic<bool> Initialized;
55 :
56 : unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
57 0 : const char *getDebugType() const { return DebugType; }
58 0 : const char *getName() const { return Name; }
59 0 : const char *getDesc() const { return Desc; }
60 :
61 : /// construct - This should only be called for non-global statistics.
62 : void construct(const char *debugtype, const char *name, const char *desc) {
63 : DebugType = debugtype;
64 : Name = name;
65 : Desc = desc;
66 : Value = 0;
67 : Initialized = false;
68 : }
69 :
70 : // Allow use of this class as the value itself.
71 : operator unsigned() const { return getValue(); }
72 :
73 : #if LLVM_ENABLE_STATS
74 : const Statistic &operator=(unsigned Val) {
75 : Value.store(Val, std::memory_order_relaxed);
76 : return init();
77 : }
78 :
79 : const Statistic &operator++() {
80 : Value.fetch_add(1, std::memory_order_relaxed);
81 : return init();
82 : }
83 :
84 : unsigned operator++(int) {
85 : init();
86 : return Value.fetch_add(1, std::memory_order_relaxed);
87 : }
88 :
89 : const Statistic &operator--() {
90 : Value.fetch_sub(1, std::memory_order_relaxed);
91 : return init();
92 : }
93 :
94 : unsigned operator--(int) {
95 : init();
96 : return Value.fetch_sub(1, std::memory_order_relaxed);
97 : }
98 :
99 : const Statistic &operator+=(unsigned V) {
100 : if (V == 0)
101 : return *this;
102 : Value.fetch_add(V, std::memory_order_relaxed);
103 : return init();
104 : }
105 :
106 : const Statistic &operator-=(unsigned V) {
107 : if (V == 0)
108 : return *this;
109 : Value.fetch_sub(V, std::memory_order_relaxed);
110 : return init();
111 : }
112 :
113 : void updateMax(unsigned V) {
114 : unsigned PrevMax = Value.load(std::memory_order_relaxed);
115 : // Keep trying to update max until we succeed or another thread produces
116 : // a bigger max than us.
117 : while (V > PrevMax && !Value.compare_exchange_weak(
118 : PrevMax, V, std::memory_order_relaxed)) {
119 : }
120 : init();
121 : }
122 :
123 : #else // Statistics are disabled in release builds.
124 :
125 0 : const Statistic &operator=(unsigned Val) {
126 0 : return *this;
127 : }
128 :
129 : const Statistic &operator++() {
130 : return *this;
131 : }
132 :
133 0 : unsigned operator++(int) {
134 0 : return 0;
135 : }
136 :
137 : const Statistic &operator--() {
138 : return *this;
139 : }
140 :
141 : unsigned operator--(int) {
142 : return 0;
143 : }
144 :
145 0 : const Statistic &operator+=(const unsigned &V) {
146 0 : return *this;
147 : }
148 :
149 0 : const Statistic &operator-=(const unsigned &V) {
150 0 : return *this;
151 : }
152 :
153 0 : void updateMax(unsigned V) {}
154 :
155 : #endif // LLVM_ENABLE_STATS
156 :
157 : protected:
158 : Statistic &init() {
159 : if (!Initialized.load(std::memory_order_acquire))
160 : RegisterStatistic();
161 : return *this;
162 : }
163 :
164 : void RegisterStatistic();
165 : };
166 :
167 : // STATISTIC - A macro to make definition of statistics really simple. This
168 : // automatically passes the DEBUG_TYPE of the file into the statistic.
169 : #define STATISTIC(VARNAME, DESC) \
170 : static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, {false}}
171 :
172 : /// Enable the collection and printing of statistics.
173 : void EnableStatistics(bool PrintOnExit = true);
174 :
175 : /// Check if statistics are enabled.
176 : bool AreStatisticsEnabled();
177 :
178 : /// Return a file stream to print our output on.
179 : std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
180 :
181 : /// Print statistics to the file returned by CreateInfoOutputFile().
182 : void PrintStatistics();
183 :
184 : /// Print statistics to the given output stream.
185 : void PrintStatistics(raw_ostream &OS);
186 :
187 : /// Print statistics in JSON format. This does include all global timers (\see
188 : /// Timer, TimerGroup). Note that the timers are cleared after printing and will
189 : /// not be printed in human readable form or in a second call of
190 : /// PrintStatisticsJSON().
191 : void PrintStatisticsJSON(raw_ostream &OS);
192 :
193 : /// Get the statistics. This can be used to look up the value of
194 : /// statistics without needing to parse JSON.
195 : ///
196 : /// This function does not prevent statistics being updated by other threads
197 : /// during it's execution. It will return the value at the point that it is
198 : /// read. However, it will prevent new statistics from registering until it
199 : /// completes.
200 : const std::vector<std::pair<StringRef, unsigned>> GetStatistics();
201 :
202 : /// Reset the statistics. This can be used to zero and de-register the
203 : /// statistics in order to measure a compilation.
204 : ///
205 : /// When this function begins to call destructors prior to returning, all
206 : /// statistics will be zero and unregistered. However, that might not remain the
207 : /// case by the time this function finishes returning. Whether update from other
208 : /// threads are lost or merely deferred until during the function return is
209 : /// timing sensitive.
210 : ///
211 : /// Callers who intend to use this to measure statistics for a single
212 : /// compilation should ensure that no compilations are in progress at the point
213 : /// this function is called and that only one compilation executes until calling
214 : /// GetStatistics().
215 : void ResetStatistics();
216 :
217 : } // end namespace llvm
218 :
219 : #endif // LLVM_ADT_STATISTIC_H
|