Statistic.h revision 360784
1254721Semaste//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===//
2254721Semaste//
3254721Semaste// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4254721Semaste// See https://llvm.org/LICENSE.txt for license information.
5254721Semaste// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6254721Semaste//
7254721Semaste//===----------------------------------------------------------------------===//
8254721Semaste//
9254721Semaste// This file defines the 'Statistic' class, which is designed to be an easy way
10254721Semaste// to expose various metrics from passes.  These statistics are printed at the
11254721Semaste// end of a run (from llvm_shutdown), when the -stats command line option is
12254721Semaste// passed on the command line.
13254721Semaste//
14254721Semaste// This is useful for reporting information like the number of instructions
15254721Semaste// simplified, optimized or removed by various transformations, like this:
16254721Semaste//
17254721Semaste// static Statistic NumInstsKilled("gcse", "Number of instructions killed");
18254721Semaste//
19254721Semaste// Later, in the code: ++NumInstsKilled;
20254721Semaste//
21254721Semaste// NOTE: Statistics *must* be declared as global variables.
22254721Semaste//
23254721Semaste//===----------------------------------------------------------------------===//
24254721Semaste
25254721Semaste#ifndef LLVM_ADT_STATISTIC_H
26254721Semaste#define LLVM_ADT_STATISTIC_H
27254721Semaste
28254721Semaste#include "llvm/Config/llvm-config.h"
29254721Semaste#include "llvm/Support/Compiler.h"
30254721Semaste#include <atomic>
31254721Semaste#include <memory>
32254721Semaste#include <vector>
33254721Semaste
34254721Semaste// Determine whether statistics should be enabled. We must do it here rather
35254721Semaste// than in CMake because multi-config generators cannot determine this at
36254721Semaste// configure time.
37254721Semaste#if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS
38254721Semaste#define LLVM_ENABLE_STATS 1
39254721Semaste#endif
40254721Semaste
41254721Semastenamespace llvm {
42254721Semaste
43254721Semasteclass raw_ostream;
44254721Semasteclass raw_fd_ostream;
45254721Semasteclass StringRef;
46254721Semaste
47254721Semasteclass StatisticBase {
48254721Semastepublic:
49254721Semaste  const char *DebugType;
50254721Semaste  const char *Name;
51254721Semaste  const char *Desc;
52254721Semaste
53254721Semaste  StatisticBase(const char *DebugType, const char *Name, const char *Desc)
54254721Semaste      : DebugType(DebugType), Name(Name), Desc(Desc) {}
55254721Semaste
56254721Semaste  const char *getDebugType() const { return DebugType; }
57254721Semaste  const char *getName() const { return Name; }
58254721Semaste  const char *getDesc() const { return Desc; }
59254721Semaste};
60254721Semaste
61254721Semasteclass TrackingStatistic : public StatisticBase {
62254721Semastepublic:
63254721Semaste  std::atomic<unsigned> Value;
64254721Semaste  std::atomic<bool> Initialized;
65254721Semaste
66254721Semaste  TrackingStatistic(const char *DebugType, const char *Name, const char *Desc)
67254721Semaste      : StatisticBase(DebugType, Name, Desc), Value(0), Initialized(false) {}
68254721Semaste
69254721Semaste  unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
70254721Semaste
71254721Semaste  // Allow use of this class as the value itself.
72254721Semaste  operator unsigned() const { return getValue(); }
73254721Semaste
74254721Semaste  const TrackingStatistic &operator=(unsigned Val) {
75254721Semaste    Value.store(Val, std::memory_order_relaxed);
76254721Semaste    return init();
77254721Semaste  }
78254721Semaste
79254721Semaste  const TrackingStatistic &operator++() {
80254721Semaste    Value.fetch_add(1, std::memory_order_relaxed);
81254721Semaste    return init();
82254721Semaste  }
83254721Semaste
84254721Semaste  unsigned operator++(int) {
85254721Semaste    init();
86254721Semaste    return Value.fetch_add(1, std::memory_order_relaxed);
87254721Semaste  }
88254721Semaste
89254721Semaste  const TrackingStatistic &operator--() {
90254721Semaste    Value.fetch_sub(1, std::memory_order_relaxed);
91254721Semaste    return init();
92254721Semaste  }
93254721Semaste
94254721Semaste  unsigned operator--(int) {
95254721Semaste    init();
96254721Semaste    return Value.fetch_sub(1, std::memory_order_relaxed);
97254721Semaste  }
98254721Semaste
99254721Semaste  const TrackingStatistic &operator+=(unsigned V) {
100254721Semaste    if (V == 0)
101254721Semaste      return *this;
102254721Semaste    Value.fetch_add(V, std::memory_order_relaxed);
103254721Semaste    return init();
104254721Semaste  }
105254721Semaste
106254721Semaste  const TrackingStatistic &operator-=(unsigned V) {
107254721Semaste    if (V == 0)
108254721Semaste      return *this;
109254721Semaste    Value.fetch_sub(V, std::memory_order_relaxed);
110254721Semaste    return init();
111254721Semaste  }
112254721Semaste
113254721Semaste  void updateMax(unsigned V) {
114254721Semaste    unsigned PrevMax = Value.load(std::memory_order_relaxed);
115254721Semaste    // Keep trying to update max until we succeed or another thread produces
116254721Semaste    // a bigger max than us.
117254721Semaste    while (V > PrevMax && !Value.compare_exchange_weak(
118254721Semaste                              PrevMax, V, std::memory_order_relaxed)) {
119254721Semaste    }
120254721Semaste    init();
121254721Semaste  }
122254721Semaste
123254721Semasteprotected:
124254721Semaste  TrackingStatistic &init() {
125254721Semaste    if (!Initialized.load(std::memory_order_acquire))
126254721Semaste      RegisterStatistic();
127254721Semaste    return *this;
128254721Semaste  }
129254721Semaste
130254721Semaste  void RegisterStatistic();
131254721Semaste};
132254721Semaste
133254721Semasteclass NoopStatistic : public StatisticBase {
134254721Semastepublic:
135254721Semaste  using StatisticBase::StatisticBase;
136254721Semaste
137254721Semaste  unsigned getValue() const { return 0; }
138254721Semaste
139254721Semaste  // Allow use of this class as the value itself.
140254721Semaste  operator unsigned() const { return 0; }
141254721Semaste
142254721Semaste  const NoopStatistic &operator=(unsigned Val) { return *this; }
143254721Semaste
144254721Semaste  const NoopStatistic &operator++() { return *this; }
145254721Semaste
146254721Semaste  unsigned operator++(int) { return 0; }
147254721Semaste
148254721Semaste  const NoopStatistic &operator--() { return *this; }
149254721Semaste
150254721Semaste  unsigned operator--(int) { return 0; }
151254721Semaste
152254721Semaste  const NoopStatistic &operator+=(const unsigned &V) { return *this; }
153254721Semaste
154254721Semaste  const NoopStatistic &operator-=(const unsigned &V) { return *this; }
155254721Semaste
156254721Semaste  void updateMax(unsigned V) {}
157254721Semaste};
158254721Semaste
159254721Semaste#if LLVM_ENABLE_STATS
160254721Semasteusing Statistic = TrackingStatistic;
161254721Semaste#else
162254721Semasteusing Statistic = NoopStatistic;
163254721Semaste#endif
164254721Semaste
165254721Semaste// STATISTIC - A macro to make definition of statistics really simple.  This
166254721Semaste// automatically passes the DEBUG_TYPE of the file into the statistic.
167254721Semaste#define STATISTIC(VARNAME, DESC)                                               \
168254721Semaste  static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC}
169254721Semaste
170254721Semaste// ALWAYS_ENABLED_STATISTIC - A macro to define a statistic like STATISTIC but
171254721Semaste// it is enabled even if LLVM_ENABLE_STATS is off.
172254721Semaste#define ALWAYS_ENABLED_STATISTIC(VARNAME, DESC)                                \
173254721Semaste  static llvm::TrackingStatistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC}
174254721Semaste
175254721Semaste/// Enable the collection and printing of statistics.
176254721Semastevoid EnableStatistics(bool DoPrintOnExit = true);
177254721Semaste
178254721Semaste/// Check if statistics are enabled.
179254721Semastebool AreStatisticsEnabled();
180254721Semaste
181254721Semaste/// Return a file stream to print our output on.
182254721Semastestd::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
183254721Semaste
184254721Semaste/// Print statistics to the file returned by CreateInfoOutputFile().
185254721Semastevoid PrintStatistics();
186254721Semaste
187254721Semaste/// Print statistics to the given output stream.
188254721Semastevoid PrintStatistics(raw_ostream &OS);
189254721Semaste
190254721Semaste/// Print statistics in JSON format. This does include all global timers (\see
191254721Semaste/// Timer, TimerGroup). Note that the timers are cleared after printing and will
192254721Semaste/// not be printed in human readable form or in a second call of
193254721Semaste/// PrintStatisticsJSON().
194254721Semastevoid PrintStatisticsJSON(raw_ostream &OS);
195254721Semaste
196254721Semaste/// Get the statistics. This can be used to look up the value of
197254721Semaste/// statistics without needing to parse JSON.
198254721Semaste///
199254721Semaste/// This function does not prevent statistics being updated by other threads
200254721Semaste/// during it's execution. It will return the value at the point that it is
201254721Semaste/// read. However, it will prevent new statistics from registering until it
202254721Semaste/// completes.
203254721Semasteconst std::vector<std::pair<StringRef, unsigned>> GetStatistics();
204254721Semaste
205254721Semaste/// Reset the statistics. This can be used to zero and de-register the
206254721Semaste/// statistics in order to measure a compilation.
207254721Semaste///
208254721Semaste/// When this function begins to call destructors prior to returning, all
209254721Semaste/// statistics will be zero and unregistered. However, that might not remain the
210254721Semaste/// case by the time this function finishes returning. Whether update from other
211254721Semaste/// threads are lost or merely deferred until during the function return is
212254721Semaste/// timing sensitive.
213254721Semaste///
214254721Semaste/// Callers who intend to use this to measure statistics for a single
215254721Semaste/// compilation should ensure that no compilations are in progress at the point
216254721Semaste/// this function is called and that only one compilation executes until calling
217254721Semaste/// GetStatistics().
218254721Semastevoid ResetStatistics();
219254721Semaste
220254721Semaste} // end namespace llvm
221254721Semaste
222254721Semaste#endif // LLVM_ADT_STATISTIC_H
223254721Semaste