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