Statistic.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. //===-- Statistic.cpp - Easy way to expose stats information --------------===//
  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 implements the 'Statistic' class, which is designed to be an easy
  11. // way to expose various success metrics from passes. These statistics are
  12. // printed at the end of a run, when the -stats command line option is enabled
  13. // 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 NumInstEliminated("GCSE", "Number of instructions killed");
  19. //
  20. // Later, in the code: ++NumInstEliminated;
  21. //
  22. //===----------------------------------------------------------------------===//
  23. #include "llvm/ADT/Statistic.h"
  24. #include "llvm/ADT/StringExtras.h"
  25. #include "llvm/Support/CommandLine.h"
  26. #include "llvm/Support/Debug.h"
  27. #include "llvm/Support/Format.h"
  28. #include "llvm/Support/ManagedStatic.h"
  29. #include "llvm/Support/Mutex.h"
  30. #include "llvm/Support/raw_ostream.h"
  31. #include <algorithm>
  32. #include <cstring>
  33. using namespace llvm;
  34. // CreateInfoOutputFile - Return a file stream to print our output on.
  35. namespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
  36. /// -stats - Command line option to cause transformations to emit stats about
  37. /// what they did.
  38. ///
  39. static cl::opt<bool>
  40. Enabled(
  41. "stats",
  42. cl::desc("Enable statistics output from program (available with Asserts)"));
  43. namespace {
  44. /// StatisticInfo - This class is used in a ManagedStatic so that it is created
  45. /// on demand (when the first statistic is bumped) and destroyed only when
  46. /// llvm_shutdown is called. We print statistics from the destructor.
  47. class StatisticInfo {
  48. std::vector<const Statistic*> Stats;
  49. friend void llvm::PrintStatistics();
  50. friend void llvm::PrintStatistics(raw_ostream &OS);
  51. public:
  52. ~StatisticInfo();
  53. void addStatistic(const Statistic *S) {
  54. Stats.push_back(S);
  55. }
  56. };
  57. }
  58. static ManagedStatic<StatisticInfo> StatInfo;
  59. static ManagedStatic<sys::SmartMutex<true> > StatLock;
  60. /// RegisterStatistic - The first time a statistic is bumped, this method is
  61. /// called.
  62. void Statistic::RegisterStatistic() {
  63. // If stats are enabled, inform StatInfo that this statistic should be
  64. // printed.
  65. sys::SmartScopedLock<true> Writer(*StatLock);
  66. if (!Initialized) {
  67. if (Enabled)
  68. StatInfo->addStatistic(this);
  69. TsanHappensBefore(this);
  70. std::atomic_thread_fence(std::memory_order_seq_cst);
  71. // Remember we have been registered.
  72. TsanIgnoreWritesBegin();
  73. Initialized = true;
  74. TsanIgnoreWritesEnd();
  75. }
  76. }
  77. // Print information when destroyed, iff command line option is specified.
  78. StatisticInfo::~StatisticInfo() {
  79. llvm::PrintStatistics();
  80. }
  81. void llvm::EnableStatistics() {
  82. Enabled.setValue(true);
  83. }
  84. bool llvm::AreStatisticsEnabled() {
  85. return Enabled;
  86. }
  87. void llvm::PrintStatistics(raw_ostream &OS) {
  88. StatisticInfo &Stats = *StatInfo;
  89. // Figure out how long the biggest Value and Name fields are.
  90. unsigned MaxNameLen = 0, MaxValLen = 0;
  91. for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
  92. MaxValLen = std::max(MaxValLen,
  93. (unsigned)utostr(Stats.Stats[i]->getValue()).size());
  94. MaxNameLen = std::max(MaxNameLen,
  95. (unsigned)std::strlen(Stats.Stats[i]->getName()));
  96. }
  97. // Sort the fields by name.
  98. std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(),
  99. [](const Statistic *LHS, const Statistic *RHS) {
  100. if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
  101. return Cmp < 0;
  102. // Secondary key is the description.
  103. return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
  104. });
  105. // Print out the statistics header...
  106. OS << "===" << std::string(73, '-') << "===\n"
  107. << " ... Statistics Collected ...\n"
  108. << "===" << std::string(73, '-') << "===\n\n";
  109. // Print all of the statistics.
  110. for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
  111. OS << format("%*u %-*s - %s\n",
  112. MaxValLen, Stats.Stats[i]->getValue(),
  113. MaxNameLen, Stats.Stats[i]->getName(),
  114. Stats.Stats[i]->getDesc());
  115. OS << '\n'; // Flush the output stream.
  116. OS.flush();
  117. }
  118. void llvm::PrintStatistics() {
  119. #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
  120. StatisticInfo &Stats = *StatInfo;
  121. // Statistics not enabled?
  122. if (Stats.Stats.empty()) return;
  123. // Get the stream to write to.
  124. raw_ostream &OutStream = *CreateInfoOutputFile();
  125. PrintStatistics(OutStream);
  126. delete &OutStream; // Close the file.
  127. #else
  128. // Check if the -stats option is set instead of checking
  129. // !Stats.Stats.empty(). In release builds, Statistics operators
  130. // do nothing, so stats are never Registered.
  131. if (Enabled) {
  132. // Get the stream to write to.
  133. raw_ostream &OutStream = *CreateInfoOutputFile();
  134. OutStream << "Statistics are disabled. "
  135. << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
  136. OutStream.flush();
  137. delete &OutStream; // Close the file.
  138. }
  139. #endif
  140. }