Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/Statistic.cpp
Line
Count
Source (jump to first uncovered line)
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
24
#include "llvm/ADT/Statistic.h"
25
#include "llvm/ADT/StringExtras.h"
26
#include "llvm/Support/CommandLine.h"
27
#include "llvm/Support/Compiler.h"
28
#include "llvm/Support/Debug.h"
29
#include "llvm/Support/Format.h"
30
#include "llvm/Support/ManagedStatic.h"
31
#include "llvm/Support/Mutex.h"
32
#include "llvm/Support/Timer.h"
33
#include "llvm/Support/YAMLTraits.h"
34
#include "llvm/Support/raw_ostream.h"
35
#include <algorithm>
36
#include <cstring>
37
using namespace llvm;
38
39
/// -stats - Command line option to cause transformations to emit stats about
40
/// what they did.
41
///
42
static cl::opt<bool> Stats("stats",
43
    cl::desc("Enable statistics output from program (available with Asserts)"));
44
45
46
static cl::opt<bool> StatsAsJSON("stats-json",
47
                                 cl::desc("Display statistics as json data"));
48
49
static bool Enabled;
50
static bool PrintOnExit;
51
52
namespace {
53
/// StatisticInfo - This class is used in a ManagedStatic so that it is created
54
/// on demand (when the first statistic is bumped) and destroyed only when
55
/// llvm_shutdown is called.  We print statistics from the destructor.
56
class StatisticInfo {
57
  std::vector<const Statistic*> Stats;
58
  friend void llvm::PrintStatistics();
59
  friend void llvm::PrintStatistics(raw_ostream &OS);
60
  friend void llvm::PrintStatisticsJSON(raw_ostream &OS);
61
62
  /// Sort statistics by debugtype,name,description.
63
  void sort();
64
public:
65
  StatisticInfo();
66
  ~StatisticInfo();
67
68
0
  void addStatistic(const Statistic *S) {
69
0
    Stats.push_back(S);
70
0
  }
71
};
72
}
73
74
static ManagedStatic<StatisticInfo> StatInfo;
75
static ManagedStatic<sys::SmartMutex<true> > StatLock;
76
77
/// RegisterStatistic - The first time a statistic is bumped, this method is
78
/// called.
79
0
void Statistic::RegisterStatistic() {
80
0
  // If stats are enabled, inform StatInfo that this statistic should be
81
0
  // printed.
82
0
  sys::SmartScopedLock<true> Writer(*StatLock);
83
0
  if (
!Initialized0
) {
84
0
    if (
Stats || 0
Enabled0
)
85
0
      StatInfo->addStatistic(this);
86
0
87
0
    TsanHappensBefore(this);
88
0
    sys::MemoryFence();
89
0
    // Remember we have been registered.
90
0
    TsanIgnoreWritesBegin();
91
0
    Initialized = true;
92
0
    TsanIgnoreWritesEnd();
93
0
  }
94
0
}
95
96
6
StatisticInfo::StatisticInfo() {
97
6
  // Ensure timergroup lists are created first so they are destructed after us.
98
6
  TimerGroup::ConstructTimerLists();
99
6
}
100
101
// Print information when destroyed, iff command line option is specified.
102
6
StatisticInfo::~StatisticInfo() {
103
6
  if (
::Stats || 6
PrintOnExit6
)
104
0
    llvm::PrintStatistics();
105
6
}
106
107
7
void llvm::EnableStatistics(bool PrintOnExit) {
108
7
  Enabled = true;
109
7
  ::PrintOnExit = PrintOnExit;
110
7
}
111
112
61
bool llvm::AreStatisticsEnabled() {
113
61
  return Enabled || Stats;
114
61
}
115
116
6
void StatisticInfo::sort() {
117
6
  std::stable_sort(Stats.begin(), Stats.end(),
118
0
                   [](const Statistic *LHS, const Statistic *RHS) {
119
0
    if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
120
0
      return Cmp < 0;
121
0
122
0
    
if (int 0
Cmp0
= std::strcmp(LHS->getName(), RHS->getName()))
123
0
      return Cmp < 0;
124
0
125
0
    return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
126
0
  });
127
6
}
128
129
5
void llvm::PrintStatistics(raw_ostream &OS) {
130
5
  StatisticInfo &Stats = *StatInfo;
131
5
132
5
  // Figure out how long the biggest Value and Name fields are.
133
5
  unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
134
5
  for (size_t i = 0, e = Stats.Stats.size(); 
i != e5
;
++i0
) {
135
0
    MaxValLen = std::max(MaxValLen,
136
0
                         (unsigned)utostr(Stats.Stats[i]->getValue()).size());
137
0
    MaxDebugTypeLen = std::max(MaxDebugTypeLen,
138
0
                         (unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
139
0
  }
140
5
141
5
  Stats.sort();
142
5
143
5
  // Print out the statistics header...
144
5
  OS << "===" << std::string(73, '-') << "===\n"
145
5
     << "                          ... Statistics Collected ...\n"
146
5
     << "===" << std::string(73, '-') << "===\n\n";
147
5
148
5
  // Print all of the statistics.
149
5
  for (size_t i = 0, e = Stats.Stats.size(); 
i != e5
;
++i0
)
150
0
    OS << format("%*u %-*s - %s\n",
151
0
                 MaxValLen, Stats.Stats[i]->getValue(),
152
0
                 MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
153
0
                 Stats.Stats[i]->getDesc());
154
5
155
5
  OS << '\n';  // Flush the output stream.
156
5
  OS.flush();
157
5
}
158
159
1
void llvm::PrintStatisticsJSON(raw_ostream &OS) {
160
1
  StatisticInfo &Stats = *StatInfo;
161
1
162
1
  Stats.sort();
163
1
164
1
  // Print all of the statistics.
165
1
  OS << "{\n";
166
1
  const char *delim = "";
167
0
  for (const Statistic *Stat : Stats.Stats) {
168
0
    OS << delim;
169
0
    assert(!yaml::needsQuotes(Stat->getDebugType()) &&
170
0
           "Statistic group/type name is simple.");
171
0
    assert(!yaml::needsQuotes(Stat->getName()) && "Statistic name is simple");
172
0
    OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
173
0
       << Stat->getValue();
174
0
    delim = ",\n";
175
0
  }
176
1
  // Print timers.
177
1
  TimerGroup::printAllJSONValues(OS, delim);
178
1
179
1
  OS << "\n}\n";
180
1
  OS.flush();
181
1
}
182
183
0
void llvm::PrintStatistics() {
184
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
185
  StatisticInfo &Stats = *StatInfo;
186
187
  // Statistics not enabled?
188
  if (Stats.Stats.empty()) return;
189
190
  // Get the stream to write to.
191
  std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
192
  if (StatsAsJSON)
193
    PrintStatisticsJSON(*OutStream);
194
  else
195
    PrintStatistics(*OutStream);
196
197
#else
198
  // Check if the -stats option is set instead of checking
199
0
  // !Stats.Stats.empty().  In release builds, Statistics operators
200
0
  // do nothing, so stats are never Registered.
201
0
  if (
Stats0
) {
202
0
    // Get the stream to write to.
203
0
    std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
204
0
    (*OutStream) << "Statistics are disabled.  "
205
0
                 << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
206
0
  }
207
0
#endif
208
0
}