Statistic.cpp revision 208954
119370Spst//===-- Statistic.cpp - Easy way to expose stats information --------------===//
219370Spst//
319370Spst//                     The LLVM Compiler Infrastructure
4130803Smarcel//
5130803Smarcel// This file is distributed under the University of Illinois Open Source
6130803Smarcel// License. See LICENSE.TXT for details.
798944Sobrien//
819370Spst//===----------------------------------------------------------------------===//
998944Sobrien//
1098944Sobrien// This file implements the 'Statistic' class, which is designed to be an easy
1198944Sobrien// way to expose various success metrics from passes.  These statistics are
1298944Sobrien// printed at the end of a run, when the -stats command line option is enabled
1319370Spst// on the command line.
1498944Sobrien//
1598944Sobrien// This is useful for reporting information like the number of instructions
1698944Sobrien// simplified, optimized or removed by various transformations, like this:
1798944Sobrien//
1819370Spst// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
1998944Sobrien//
2098944Sobrien// Later, in the code: ++NumInstEliminated;
2198944Sobrien//
2298944Sobrien//===----------------------------------------------------------------------===//
2319370Spst
2419370Spst#include "llvm/ADT/Statistic.h"
2519370Spst#include "llvm/Support/CommandLine.h"
2619370Spst#include "llvm/Support/Debug.h"
27130803Smarcel#include "llvm/Support/ManagedStatic.h"
28130803Smarcel#include "llvm/Support/raw_ostream.h"
29130803Smarcel#include "llvm/System/Mutex.h"
30130803Smarcel#include "llvm/ADT/StringExtras.h"
31130803Smarcel#include <algorithm>
32130803Smarcel#include <cstring>
33130803Smarcelusing namespace llvm;
3419370Spst
3519370Spst// CreateInfoOutputFile - Return a file stream to print our output on.
3619370Spstnamespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
3719370Spst
3819370Spst/// -stats - Command line option to cause transformations to emit stats about
3919370Spst/// what they did.
40130803Smarcel///
41130803Smarcelstatic cl::opt<bool>
42130803SmarcelEnabled("stats", cl::desc("Enable statistics output from program"));
4398944Sobrien
4419370Spst
4519370Spstnamespace {
4698944Sobrien/// StatisticInfo - This class is used in a ManagedStatic so that it is created
4719370Spst/// on demand (when the first statistic is bumped) and destroyed only when
4819370Spst/// llvm_shutdown is called.  We print statistics from the destructor.
4919370Spstclass StatisticInfo {
5019370Spst  std::vector<const Statistic*> Stats;
5198944Sobrien  friend void llvm::PrintStatistics();
5219370Spst  friend void llvm::PrintStatistics(raw_ostream &OS);
5398944Sobrienpublic:
5419370Spst  ~StatisticInfo();
5598944Sobrien
5619370Spst  void addStatistic(const Statistic *S) {
5798944Sobrien    Stats.push_back(S);
5819370Spst  }
5998944Sobrien};
6019370Spst}
6198944Sobrien
6298944Sobrienstatic ManagedStatic<StatisticInfo> StatInfo;
6398944Sobrienstatic ManagedStatic<sys::SmartMutex<true> > StatLock;
6419370Spst
6598944Sobrien/// RegisterStatistic - The first time a statistic is bumped, this method is
6698944Sobrien/// called.
6798944Sobrienvoid Statistic::RegisterStatistic() {
6819370Spst  // If stats are enabled, inform StatInfo that this statistic should be
6998944Sobrien  // printed.
7098944Sobrien  sys::SmartScopedLock<true> Writer(*StatLock);
7119370Spst  if (!Initialized) {
7298944Sobrien    if (Enabled)
7398944Sobrien      StatInfo->addStatistic(this);
7498944Sobrien
7598944Sobrien    sys::MemoryFence();
7619370Spst    // Remember we have been registered.
7798944Sobrien    Initialized = true;
7898944Sobrien  }
7919370Spst}
8098944Sobrien
8198944Sobriennamespace {
8219370Spst
8398944Sobrienstruct NameCompare {
8498944Sobrien  bool operator()(const Statistic *LHS, const Statistic *RHS) const {
8598944Sobrien    int Cmp = std::strcmp(LHS->getName(), RHS->getName());
8698944Sobrien    if (Cmp != 0) return Cmp < 0;
8798944Sobrien
8898944Sobrien    // Secondary key is the description.
8998944Sobrien    return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
9098944Sobrien  }
9198944Sobrien};
9298944Sobrien
9398944Sobrien}
9498944Sobrien
9598944Sobrien// Print information when destroyed, iff command line option is specified.
9698944SobrienStatisticInfo::~StatisticInfo() {
9798944Sobrien  llvm::PrintStatistics();
9898944Sobrien}
9998944Sobrien
10098944Sobrienvoid llvm::EnableStatistics() {
10198944Sobrien  Enabled.setValue(true);
10298944Sobrien}
10398944Sobrien
10498944Sobrienvoid llvm::PrintStatistics(raw_ostream &OS) {
10519370Spst  StatisticInfo &Stats = *StatInfo;
10619370Spst
10719370Spst  // Figure out how long the biggest Value and Name fields are.
10819370Spst  unsigned MaxNameLen = 0, MaxValLen = 0;
10998944Sobrien  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
11098944Sobrien    MaxValLen = std::max(MaxValLen,
11119370Spst                         (unsigned)utostr(Stats.Stats[i]->getValue()).size());
11298944Sobrien    MaxNameLen = std::max(MaxNameLen,
11319370Spst                          (unsigned)std::strlen(Stats.Stats[i]->getName()));
11498944Sobrien  }
11598944Sobrien
11698944Sobrien  // Sort the fields by name.
11798944Sobrien  std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare());
11898944Sobrien
11946283Sdfr  // Print out the statistics header...
12098944Sobrien  OS << "===" << std::string(73, '-') << "===\n"
12198944Sobrien     << "                          ... Statistics Collected ...\n"
12298944Sobrien     << "===" << std::string(73, '-') << "===\n\n";
12398944Sobrien
12498944Sobrien  // Print all of the statistics.
12598944Sobrien  for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
12698944Sobrien    std::string CountStr = utostr(Stats.Stats[i]->getValue());
12746283Sdfr    OS << std::string(MaxValLen-CountStr.size(), ' ')
12846283Sdfr       << CountStr << " " << Stats.Stats[i]->getName()
12946283Sdfr       << std::string(MaxNameLen-std::strlen(Stats.Stats[i]->getName()), ' ')
13046283Sdfr       << " - " << Stats.Stats[i]->getDesc() << "\n";
13146283Sdfr  }
13298944Sobrien
13346283Sdfr  OS << '\n';  // Flush the output stream.
13446283Sdfr  OS.flush();
13546283Sdfr
13646283Sdfr}
13746283Sdfr
13846283Sdfrvoid llvm::PrintStatistics() {
13946283Sdfr  StatisticInfo &Stats = *StatInfo;
14046283Sdfr
14146283Sdfr  // Statistics not enabled?
14246283Sdfr  if (Stats.Stats.empty()) return;
14398944Sobrien
14446283Sdfr  // Get the stream to write to.
14546283Sdfr  raw_ostream &OutStream = *CreateInfoOutputFile();
14619370Spst  PrintStatistics(OutStream);
14719370Spst  delete &OutStream;   // Close the file.
14819370Spst}
14919370Spst