Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===// |
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 | /// \file |
||
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 | #else |
||
41 | #define LLVM_ENABLE_STATS 0 |
||
42 | #endif |
||
43 | |||
44 | namespace llvm { |
||
45 | |||
46 | class raw_ostream; |
||
47 | class raw_fd_ostream; |
||
48 | class StringRef; |
||
49 | |||
50 | class TrackingStatistic { |
||
51 | public: |
||
52 | const char *const DebugType; |
||
53 | const char *const Name; |
||
54 | const char *const Desc; |
||
55 | |||
56 | std::atomic<uint64_t> Value; |
||
57 | std::atomic<bool> Initialized; |
||
58 | |||
59 | constexpr TrackingStatistic(const char *DebugType, const char *Name, |
||
60 | const char *Desc) |
||
61 | : DebugType(DebugType), Name(Name), Desc(Desc), Value(0), |
||
62 | Initialized(false) {} |
||
63 | |||
64 | const char *getDebugType() const { return DebugType; } |
||
65 | const char *getName() const { return Name; } |
||
66 | const char *getDesc() const { return Desc; } |
||
67 | |||
68 | uint64_t getValue() const { return Value.load(std::memory_order_relaxed); } |
||
69 | |||
70 | // Allow use of this class as the value itself. |
||
71 | operator uint64_t() const { return getValue(); } |
||
72 | |||
73 | const TrackingStatistic &operator=(uint64_t Val) { |
||
74 | Value.store(Val, std::memory_order_relaxed); |
||
75 | return init(); |
||
76 | } |
||
77 | |||
78 | const TrackingStatistic &operator++() { |
||
79 | Value.fetch_add(1, std::memory_order_relaxed); |
||
80 | return init(); |
||
81 | } |
||
82 | |||
83 | uint64_t operator++(int) { |
||
84 | init(); |
||
85 | return Value.fetch_add(1, std::memory_order_relaxed); |
||
86 | } |
||
87 | |||
88 | const TrackingStatistic &operator--() { |
||
89 | Value.fetch_sub(1, std::memory_order_relaxed); |
||
90 | return init(); |
||
91 | } |
||
92 | |||
93 | uint64_t operator--(int) { |
||
94 | init(); |
||
95 | return Value.fetch_sub(1, std::memory_order_relaxed); |
||
96 | } |
||
97 | |||
98 | const TrackingStatistic &operator+=(uint64_t V) { |
||
99 | if (V == 0) |
||
100 | return *this; |
||
101 | Value.fetch_add(V, std::memory_order_relaxed); |
||
102 | return init(); |
||
103 | } |
||
104 | |||
105 | const TrackingStatistic &operator-=(uint64_t V) { |
||
106 | if (V == 0) |
||
107 | return *this; |
||
108 | Value.fetch_sub(V, std::memory_order_relaxed); |
||
109 | return init(); |
||
110 | } |
||
111 | |||
112 | void updateMax(uint64_t V) { |
||
113 | uint64_t PrevMax = Value.load(std::memory_order_relaxed); |
||
114 | // Keep trying to update max until we succeed or another thread produces |
||
115 | // a bigger max than us. |
||
116 | while (V > PrevMax && !Value.compare_exchange_weak( |
||
117 | PrevMax, V, std::memory_order_relaxed)) { |
||
118 | } |
||
119 | init(); |
||
120 | } |
||
121 | |||
122 | protected: |
||
123 | TrackingStatistic &init() { |
||
124 | if (!Initialized.load(std::memory_order_acquire)) |
||
125 | RegisterStatistic(); |
||
126 | return *this; |
||
127 | } |
||
128 | |||
129 | void RegisterStatistic(); |
||
130 | }; |
||
131 | |||
132 | class NoopStatistic { |
||
133 | public: |
||
134 | NoopStatistic(const char * /*DebugType*/, const char * /*Name*/, |
||
135 | const char * /*Desc*/) {} |
||
136 | |||
137 | uint64_t getValue() const { return 0; } |
||
138 | |||
139 | // Allow use of this class as the value itself. |
||
140 | operator uint64_t() const { return 0; } |
||
141 | |||
142 | const NoopStatistic &operator=(uint64_t Val) { return *this; } |
||
143 | |||
144 | const NoopStatistic &operator++() { return *this; } |
||
145 | |||
146 | uint64_t operator++(int) { return 0; } |
||
147 | |||
148 | const NoopStatistic &operator--() { return *this; } |
||
149 | |||
150 | uint64_t operator--(int) { return 0; } |
||
151 | |||
152 | const NoopStatistic &operator+=(const uint64_t &V) { return *this; } |
||
153 | |||
154 | const NoopStatistic &operator-=(const uint64_t &V) { return *this; } |
||
155 | |||
156 | void updateMax(uint64_t V) {} |
||
157 | }; |
||
158 | |||
159 | #if LLVM_ENABLE_STATS |
||
160 | using Statistic = TrackingStatistic; |
||
161 | #else |
||
162 | using Statistic = NoopStatistic; |
||
163 | #endif |
||
164 | |||
165 | // STATISTIC - A macro to make definition of statistics really simple. This |
||
166 | // automatically passes the DEBUG_TYPE of the file into the statistic. |
||
167 | #define STATISTIC(VARNAME, DESC) \ |
||
168 | static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC} |
||
169 | |||
170 | // ALWAYS_ENABLED_STATISTIC - A macro to define a statistic like STATISTIC but |
||
171 | // it is enabled even if LLVM_ENABLE_STATS is off. |
||
172 | #define ALWAYS_ENABLED_STATISTIC(VARNAME, DESC) \ |
||
173 | static llvm::TrackingStatistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC} |
||
174 | |||
175 | /// Enable the collection and printing of statistics. |
||
176 | void EnableStatistics(bool DoPrintOnExit = true); |
||
177 | |||
178 | /// Check if statistics are enabled. |
||
179 | bool AreStatisticsEnabled(); |
||
180 | |||
181 | /// Return a file stream to print our output on. |
||
182 | std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile(); |
||
183 | |||
184 | /// Print statistics to the file returned by CreateInfoOutputFile(). |
||
185 | void PrintStatistics(); |
||
186 | |||
187 | /// Print statistics to the given output stream. |
||
188 | void PrintStatistics(raw_ostream &OS); |
||
189 | |||
190 | /// Print statistics in JSON format. This does include all global timers (\see |
||
191 | /// Timer, TimerGroup). Note that the timers are cleared after printing and will |
||
192 | /// not be printed in human readable form or in a second call of |
||
193 | /// PrintStatisticsJSON(). |
||
194 | void PrintStatisticsJSON(raw_ostream &OS); |
||
195 | |||
196 | /// Get the statistics. This can be used to look up the value of |
||
197 | /// statistics without needing to parse JSON. |
||
198 | /// |
||
199 | /// This function does not prevent statistics being updated by other threads |
||
200 | /// during it's execution. It will return the value at the point that it is |
||
201 | /// read. However, it will prevent new statistics from registering until it |
||
202 | /// completes. |
||
203 | std::vector<std::pair<StringRef, uint64_t>> GetStatistics(); |
||
204 | |||
205 | /// Reset the statistics. This can be used to zero and de-register the |
||
206 | /// statistics in order to measure a compilation. |
||
207 | /// |
||
208 | /// When this function begins to call destructors prior to returning, all |
||
209 | /// statistics will be zero and unregistered. However, that might not remain the |
||
210 | /// case by the time this function finishes returning. Whether update from other |
||
211 | /// threads are lost or merely deferred until during the function return is |
||
212 | /// timing sensitive. |
||
213 | /// |
||
214 | /// Callers who intend to use this to measure statistics for a single |
||
215 | /// compilation should ensure that no compilations are in progress at the point |
||
216 | /// this function is called and that only one compilation executes until calling |
||
217 | /// GetStatistics(). |
||
218 | void ResetStatistics(); |
||
219 | |||
220 | } // end namespace llvm |
||
221 | |||
222 | #endif // LLVM_ADT_STATISTIC_H |