Statistic.cpp revision 195098
1232922Stheraven//===-- Statistic.cpp - Easy way to expose stats information --------------===//
2232922Stheraven//
3232922Stheraven//                     The LLVM Compiler Infrastructure
4232922Stheraven//
5232922Stheraven// This file is distributed under the University of Illinois Open Source
6232922Stheraven// License. See LICENSE.TXT for details.
7232922Stheraven//
8232922Stheraven//===----------------------------------------------------------------------===//
9232922Stheraven//
10232922Stheraven// This file implements the 'Statistic' class, which is designed to be an easy
11232922Stheraven// way to expose various success metrics from passes.  These statistics are
12232922Stheraven// printed at the end of a run, when the -stats command line option is enabled
13232922Stheraven// on the command line.
14232922Stheraven//
15232922Stheraven// This is useful for reporting information like the number of instructions
16232922Stheraven// simplified, optimized or removed by various transformations, like this:
17232922Stheraven//
18232922Stheraven// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
19232922Stheraven//
20232922Stheraven// Later, in the code: ++NumInstEliminated;
21232922Stheraven//
22232922Stheraven//===----------------------------------------------------------------------===//
23232922Stheraven
24232922Stheraven#include "llvm/ADT/Statistic.h"
25232922Stheraven#include "llvm/Support/CommandLine.h"
26232922Stheraven#include "llvm/Support/ManagedStatic.h"
27227825Stheraven#include "llvm/Support/Streams.h"
28227825Stheraven#include "llvm/System/Mutex.h"
29227825Stheraven#include "llvm/ADT/StringExtras.h"
30227825Stheraven#include <algorithm>
31227825Stheraven#include <ostream>
32227825Stheraven#include <cstring>
33227825Stheravenusing namespace llvm;
34227825Stheraven
35227825Stheraven// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
36227825Stheravennamespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }
37227825Stheraven
38227825Stheraven/// -stats - Command line option to cause transformations to emit stats about
39227825Stheraven/// what they did.
40227825Stheraven///
41227825Stheravenstatic cl::opt<bool>
42227825StheravenEnabled("stats", cl::desc("Enable statistics output from program"));
43227825Stheraven
44227825Stheraven
45227825Stheravennamespace {
46227825Stheraven/// StatisticInfo - This class is used in a ManagedStatic so that it is created
47227825Stheraven/// on demand (when the first statistic is bumped) and destroyed only when
48227825Stheraven/// llvm_shutdown is called.  We print statistics from the destructor.
49227825Stheravenclass StatisticInfo {
50227825Stheraven  std::vector<const Statistic*> Stats;
51227825Stheravenpublic:
52227825Stheraven  ~StatisticInfo();
53227825Stheraven
54227825Stheraven  void addStatistic(const Statistic *S) {
55227825Stheraven    Stats.push_back(S);
56227825Stheraven  }
57227825Stheraven};
58227825Stheraven}
59227825Stheraven
60227825Stheravenstatic ManagedStatic<StatisticInfo> StatInfo;
61227825Stheravenstatic ManagedStatic<sys::Mutex> StatLock;
62227825Stheraven
63227825Stheraven/// RegisterStatistic - The first time a statistic is bumped, this method is
64227825Stheraven/// called.
65227825Stheravenvoid Statistic::RegisterStatistic() {
66227825Stheraven  // If stats are enabled, inform StatInfo that this statistic should be
67227825Stheraven  // printed.
68227825Stheraven  sys::ScopedLock Writer(&*StatLock);
69227825Stheraven  if (!Initialized) {
70227825Stheraven    if (Enabled)
71227825Stheraven      StatInfo->addStatistic(this);
72227825Stheraven
73227825Stheraven    sys::MemoryFence();
74227825Stheraven    // Remember we have been registered.
75227825Stheraven    Initialized = true;
76227825Stheraven  }
77227825Stheraven}
78227825Stheraven
79227825Stheravennamespace {
80227825Stheraven
81227825Stheravenstruct NameCompare {
82227825Stheraven  bool operator()(const Statistic *LHS, const Statistic *RHS) const {
83227825Stheraven    int Cmp = std::strcmp(LHS->getName(), RHS->getName());
84276375Sdim    if (Cmp != 0) return Cmp < 0;
85276375Sdim
86276375Sdim    // Secondary key is the description.
87276375Sdim    return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
88276375Sdim  }
89276375Sdim};
90276375Sdim
91276375Sdim}
92276375Sdim
93227825Stheraven// Print information when destroyed, iff command line option is specified.
94227825StheravenStatisticInfo::~StatisticInfo() {
95227825Stheraven  // Statistics not enabled?
96227825Stheraven  if (Stats.empty()) return;
97
98  // Get the stream to write to.
99  std::ostream &OutStream = *GetLibSupportInfoOutputFile();
100
101  // Figure out how long the biggest Value and Name fields are.
102  unsigned MaxNameLen = 0, MaxValLen = 0;
103  for (size_t i = 0, e = Stats.size(); i != e; ++i) {
104    MaxValLen = std::max(MaxValLen,
105                         (unsigned)utostr(Stats[i]->getValue()).size());
106    MaxNameLen = std::max(MaxNameLen,
107                          (unsigned)std::strlen(Stats[i]->getName()));
108  }
109
110  // Sort the fields by name.
111  std::stable_sort(Stats.begin(), Stats.end(), NameCompare());
112
113  // Print out the statistics header...
114  OutStream << "===" << std::string(73, '-') << "===\n"
115            << "                          ... Statistics Collected ...\n"
116            << "===" << std::string(73, '-') << "===\n\n";
117
118  // Print all of the statistics.
119  for (size_t i = 0, e = Stats.size(); i != e; ++i) {
120    std::string CountStr = utostr(Stats[i]->getValue());
121    OutStream << std::string(MaxValLen-CountStr.size(), ' ')
122              << CountStr << " " << Stats[i]->getName()
123              << std::string(MaxNameLen-std::strlen(Stats[i]->getName()), ' ')
124              << " - " << Stats[i]->getDesc() << "\n";
125
126  }
127
128  OutStream << std::endl;  // Flush the output stream...
129
130  if (&OutStream != cerr.stream() && &OutStream != cout.stream())
131    delete &OutStream;   // Close the file.
132}
133