Statistic.h 7.2 KB

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