Statistic.cpp revision 249423
1218885Sdim//===-- Statistic.cpp - Easy way to expose stats information --------------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file implements the 'Statistic' class, which is designed to be an easy
11218885Sdim// way to expose various success metrics from passes.  These statistics are
12218885Sdim// printed at the end of a run, when the -stats command line option is enabled
13224145Sdim// on the command line.
14224145Sdim//
15224145Sdim// This is useful for reporting information like the number of instructions
16224145Sdim// simplified, optimized or removed by various transformations, like this:
17218885Sdim//
18218885Sdim// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
19263508Sdim//
20224145Sdim// Later, in the code: ++NumInstEliminated;
21218885Sdim//
22218885Sdim//===----------------------------------------------------------------------===//
23218885Sdim
24224145Sdim#include "llvm/ADT/Statistic.h"
25224145Sdim#include "llvm/ADT/StringExtras.h"
26224145Sdim#include "llvm/Support/CommandLine.h"
27218885Sdim#include "llvm/Support/Debug.h"
28218885Sdim#include "llvm/Support/Format.h"
29218885Sdim#include "llvm/Support/ManagedStatic.h"
30218885Sdim#include "llvm/Support/Mutex.h"
31218885Sdim#include "llvm/Support/raw_ostream.h"
32218885Sdim#include <algorithm>
33218885Sdim#include <cstring>
34218885Sdimusing namespace llvm;
35218885Sdim
36218885Sdim// CreateInfoOutputFile - Return a file stream to print our output on.
37218885Sdimnamespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
38218885Sdim
39218885Sdim/// -stats - Command line option to cause transformations to emit stats about
40218885Sdim/// what they did.
41218885Sdim///
42218885Sdimstatic cl::opt<bool>
43218885SdimEnabled(
44218885Sdim    "stats",
45218885Sdim    cl::desc("Enable statistics output from program (available with Asserts)"));
46218885Sdim
47218885Sdim
48249423Sdimnamespace {
49249423Sdim/// StatisticInfo - This class is used in a ManagedStatic so that it is created
50249423Sdim/// on demand (when the first statistic is bumped) and destroyed only when
51249423Sdim/// llvm_shutdown is called.  We print statistics from the destructor.
52249423Sdimclass StatisticInfo {
53249423Sdim  std::vector<const Statistic*> Stats;
54249423Sdim  friend void llvm::PrintStatistics();
55218885Sdim  friend void llvm::PrintStatistics(raw_ostream &OS);
56218885Sdimpublic:
57218885Sdim  ~StatisticInfo();
58218885Sdim
59218885Sdim  void addStatistic(const Statistic *S) {
60218885Sdim    Stats.push_back(S);
61218885Sdim  }
62218885Sdim};
63218885Sdim}
64218885Sdim
65218885Sdimstatic ManagedStatic<StatisticInfo> StatInfo;
66218885Sdimstatic ManagedStatic<sys::SmartMutex<true> > StatLock;
67224145Sdim
68224145Sdim/// RegisterStatistic - The first time a statistic is bumped, this method is
69224145Sdim/// called.
70224145Sdimvoid Statistic::RegisterStatistic() {
71224145Sdim  // If stats are enabled, inform StatInfo that this statistic should be
72224145Sdim  // printed.
73224145Sdim  sys::SmartScopedLock<true> Writer(*StatLock);
74224145Sdim  if (!Initialized) {
75224145Sdim    if (Enabled)
76224145Sdim      StatInfo->addStatistic(this);
77224145Sdim
78224145Sdim    TsanHappensBefore(this);
79224145Sdim    sys::MemoryFence();
80218885Sdim    // Remember we have been registered.
81218885Sdim    TsanIgnoreWritesBegin();
82224145Sdim    Initialized = true;
83224145Sdim    TsanIgnoreWritesEnd();
84224145Sdim  }
85224145Sdim}
86224145Sdim
87224145Sdimnamespace {
88224145Sdim
89224145Sdimstruct NameCompare {
90224145Sdim  bool operator()(const Statistic *LHS, const Statistic *RHS) const {
91224145Sdim    int Cmp = std::strcmp(LHS->getName(), RHS->getName());
92224145Sdim    if (Cmp != 0) return Cmp < 0;
93224145Sdim
94224145Sdim    // Secondary key is the description.
95224145Sdim    return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
96224145Sdim  }
97224145Sdim};
98224145Sdim
99224145Sdim}
100224145Sdim
101263508Sdim// Print information when destroyed, iff command line option is specified.
102224145SdimStatisticInfo::~StatisticInfo() {
103224145Sdim  llvm::PrintStatistics();
104224145Sdim}
105224145Sdim
106224145Sdimvoid llvm::EnableStatistics() {
107224145Sdim  Enabled.setValue(true);
108224145Sdim}
109224145Sdim
110224145Sdimbool llvm::AreStatisticsEnabled() {
111224145Sdim  return Enabled;
112224145Sdim}
113224145Sdim
114224145Sdimvoid llvm::PrintStatistics(raw_ostream &OS) {
115224145Sdim  StatisticInfo &Stats = *StatInfo;
116224145Sdim
117224145Sdim  // Figure out how long the biggest Value and Name fields are.
118224145Sdim  unsigned MaxNameLen = 0, MaxValLen = 0;
119224145Sdim  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
120224145Sdim    MaxValLen = std::max(MaxValLen,
121249423Sdim                         (unsigned)utostr(Stats.Stats[i]->getValue()).size());
122249423Sdim    MaxNameLen = std::max(MaxNameLen,
123249423Sdim                          (unsigned)std::strlen(Stats.Stats[i]->getName()));
124249423Sdim  }
125249423Sdim
126249423Sdim  // Sort the fields by name.
127249423Sdim  std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare());
128224145Sdim
129224145Sdim  // Print out the statistics header...
130224145Sdim  OS << "===" << std::string(73, '-') << "===\n"
131224145Sdim     << "                          ... Statistics Collected ...\n"
132224145Sdim     << "===" << std::string(73, '-') << "===\n\n";
133224145Sdim
134224145Sdim  // Print all of the statistics.
135224145Sdim  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
136224145Sdim    OS << format("%*u %-*s - %s\n",
137224145Sdim                 MaxValLen, Stats.Stats[i]->getValue(),
138224145Sdim                 MaxNameLen, Stats.Stats[i]->getName(),
139224145Sdim                 Stats.Stats[i]->getDesc());
140224145Sdim
141224145Sdim  OS << '\n';  // Flush the output stream.
142224145Sdim  OS.flush();
143224145Sdim
144224145Sdim}
145224145Sdim
146224145Sdimvoid llvm::PrintStatistics() {
147224145Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
148224145Sdim  StatisticInfo &Stats = *StatInfo;
149224145Sdim
150224145Sdim  // Statistics not enabled?
151224145Sdim  if (Stats.Stats.empty()) return;
152224145Sdim
153224145Sdim  // Get the stream to write to.
154224145Sdim  raw_ostream &OutStream = *CreateInfoOutputFile();
155224145Sdim  PrintStatistics(OutStream);
156224145Sdim  delete &OutStream;   // Close the file.
157224145Sdim#else
158263508Sdim  // Check if the -stats option is set instead of checking
159263508Sdim  // !Stats.Stats.empty().  In release builds, Statistics operators
160224145Sdim  // do nothing, so stats are never Registered.
161224145Sdim  if (Enabled) {
162224145Sdim    // Get the stream to write to.
163224145Sdim    raw_ostream &OutStream = *CreateInfoOutputFile();
164224145Sdim    OutStream << "Statistics are disabled.  "
165224145Sdim            << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
166224145Sdim    OutStream.flush();
167224145Sdim    delete &OutStream;   // Close the file.
168224145Sdim  }
169243830Sdim#endif
170243830Sdim}
171224145Sdim