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/Support/Atomic.h"
30#include "llvm/Support/Valgrind.h"
31
32namespace llvm {
33class raw_ostream;
34
35class Statistic {
36public:
37  const char *Name;
38  const char *Desc;
39  volatile llvm::sys::cas_flag Value;
40  bool Initialized;
41
42  llvm::sys::cas_flag getValue() const { return Value; }
43  const char *getName() const { return Name; }
44  const char *getDesc() const { return Desc; }
45
46  /// construct - This should only be called for non-global statistics.
47  void construct(const char *name, const char *desc) {
48    Name = name; Desc = desc;
49    Value = 0; Initialized = false;
50  }
51
52  // Allow use of this class as the value itself.
53  operator unsigned() const { return Value; }
54
55#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
56   const Statistic &operator=(unsigned Val) {
57    Value = Val;
58    return init();
59  }
60
61  const Statistic &operator++() {
62    // FIXME: This function and all those that follow carefully use an
63    // atomic operation to update the value safely in the presence of
64    // concurrent accesses, but not to read the return value, so the
65    // return value is not thread safe.
66    sys::AtomicIncrement(&Value);
67    return init();
68  }
69
70  unsigned operator++(int) {
71    init();
72    unsigned OldValue = Value;
73    sys::AtomicIncrement(&Value);
74    return OldValue;
75  }
76
77  const Statistic &operator--() {
78    sys::AtomicDecrement(&Value);
79    return init();
80  }
81
82  unsigned operator--(int) {
83    init();
84    unsigned OldValue = Value;
85    sys::AtomicDecrement(&Value);
86    return OldValue;
87  }
88
89  const Statistic &operator+=(const unsigned &V) {
90    if (!V) return *this;
91    sys::AtomicAdd(&Value, V);
92    return init();
93  }
94
95  const Statistic &operator-=(const unsigned &V) {
96    if (!V) return *this;
97    sys::AtomicAdd(&Value, -V);
98    return init();
99  }
100
101  const Statistic &operator*=(const unsigned &V) {
102    sys::AtomicMul(&Value, V);
103    return init();
104  }
105
106  const Statistic &operator/=(const unsigned &V) {
107    sys::AtomicDiv(&Value, V);
108    return init();
109  }
110
111#else  // Statistics are disabled in release builds.
112
113  const Statistic &operator=(unsigned Val) {
114    return *this;
115  }
116
117  const Statistic &operator++() {
118    return *this;
119  }
120
121  unsigned operator++(int) {
122    return 0;
123  }
124
125  const Statistic &operator--() {
126    return *this;
127  }
128
129  unsigned operator--(int) {
130    return 0;
131  }
132
133  const Statistic &operator+=(const unsigned &V) {
134    return *this;
135  }
136
137  const Statistic &operator-=(const unsigned &V) {
138    return *this;
139  }
140
141  const Statistic &operator*=(const unsigned &V) {
142    return *this;
143  }
144
145  const Statistic &operator/=(const unsigned &V) {
146    return *this;
147  }
148
149#endif  // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
150
151protected:
152  Statistic &init() {
153    bool tmp = Initialized;
154    sys::MemoryFence();
155    if (!tmp) RegisterStatistic();
156    TsanHappensAfter(this);
157    return *this;
158  }
159  void RegisterStatistic();
160};
161
162// STATISTIC - A macro to make definition of statistics really simple.  This
163// automatically passes the DEBUG_TYPE of the file into the statistic.
164#define STATISTIC(VARNAME, DESC) \
165  static llvm::Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 }
166
167/// \brief Enable the collection and printing of statistics.
168void EnableStatistics();
169
170/// \brief Check if statistics are enabled.
171bool AreStatisticsEnabled();
172
173/// \brief Print statistics to the file returned by CreateInfoOutputFile().
174void PrintStatistics();
175
176/// \brief Print statistics to the given output stream.
177void PrintStatistics(raw_ostream &OS);
178
179} // End llvm namespace
180
181#endif
182