Home | History | Annotate | Download | only in Support
      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/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/raw_ostream.h"
     30 #include "llvm/Support/Mutex.h"
     31 #include "llvm/ADT/StringExtras.h"
     32 #include <algorithm>
     33 #include <cstring>
     34 using namespace llvm;
     35 
     36 // CreateInfoOutputFile - Return a file stream to print our output on.
     37 namespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
     38 
     39 /// -stats - Command line option to cause transformations to emit stats about
     40 /// what they did.
     41 ///
     42 static cl::opt<bool>
     43 Enabled("stats", cl::desc("Enable statistics output from program"));
     44 
     45 
     46 namespace {
     47 /// StatisticInfo - This class is used in a ManagedStatic so that it is created
     48 /// on demand (when the first statistic is bumped) and destroyed only when
     49 /// llvm_shutdown is called.  We print statistics from the destructor.
     50 class StatisticInfo {
     51   std::vector<const Statistic*> Stats;
     52   friend void llvm::PrintStatistics();
     53   friend void llvm::PrintStatistics(raw_ostream &OS);
     54 public:
     55   ~StatisticInfo();
     56 
     57   void addStatistic(const Statistic *S) {
     58     Stats.push_back(S);
     59   }
     60 };
     61 }
     62 
     63 static ManagedStatic<StatisticInfo> StatInfo;
     64 static ManagedStatic<sys::SmartMutex<true> > StatLock;
     65 
     66 /// RegisterStatistic - The first time a statistic is bumped, this method is
     67 /// called.
     68 void Statistic::RegisterStatistic() {
     69   // If stats are enabled, inform StatInfo that this statistic should be
     70   // printed.
     71   sys::SmartScopedLock<true> Writer(*StatLock);
     72   if (!Initialized) {
     73     if (Enabled)
     74       StatInfo->addStatistic(this);
     75 
     76     TsanHappensBefore(this);
     77     sys::MemoryFence();
     78     // Remember we have been registered.
     79     TsanIgnoreWritesBegin();
     80     Initialized = true;
     81     TsanIgnoreWritesEnd();
     82   }
     83 }
     84 
     85 namespace {
     86 
     87 struct NameCompare {
     88   bool operator()(const Statistic *LHS, const Statistic *RHS) const {
     89     int Cmp = std::strcmp(LHS->getName(), RHS->getName());
     90     if (Cmp != 0) return Cmp < 0;
     91 
     92     // Secondary key is the description.
     93     return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
     94   }
     95 };
     96 
     97 }
     98 
     99 // Print information when destroyed, iff command line option is specified.
    100 StatisticInfo::~StatisticInfo() {
    101   llvm::PrintStatistics();
    102 }
    103 
    104 void llvm::EnableStatistics() {
    105   Enabled.setValue(true);
    106 }
    107 
    108 bool llvm::AreStatisticsEnabled() {
    109   return Enabled;
    110 }
    111 
    112 void llvm::PrintStatistics(raw_ostream &OS) {
    113   StatisticInfo &Stats = *StatInfo;
    114 
    115   // Figure out how long the biggest Value and Name fields are.
    116   unsigned MaxNameLen = 0, MaxValLen = 0;
    117   for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
    118     MaxValLen = std::max(MaxValLen,
    119                          (unsigned)utostr(Stats.Stats[i]->getValue()).size());
    120     MaxNameLen = std::max(MaxNameLen,
    121                           (unsigned)std::strlen(Stats.Stats[i]->getName()));
    122   }
    123 
    124   // Sort the fields by name.
    125   std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare());
    126 
    127   // Print out the statistics header...
    128   OS << "===" << std::string(73, '-') << "===\n"
    129      << "                          ... Statistics Collected ...\n"
    130      << "===" << std::string(73, '-') << "===\n\n";
    131 
    132   // Print all of the statistics.
    133   for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
    134     OS << format("%*u %-*s - %s\n",
    135                  MaxValLen, Stats.Stats[i]->getValue(),
    136                  MaxNameLen, Stats.Stats[i]->getName(),
    137                  Stats.Stats[i]->getDesc());
    138 
    139   OS << '\n';  // Flush the output stream.
    140   OS.flush();
    141 
    142 }
    143 
    144 void llvm::PrintStatistics() {
    145   StatisticInfo &Stats = *StatInfo;
    146 
    147   // Statistics not enabled?
    148   if (Stats.Stats.empty()) return;
    149 
    150   // Get the stream to write to.
    151   raw_ostream &OutStream = *CreateInfoOutputFile();
    152   PrintStatistics(OutStream);
    153   delete &OutStream;   // Close the file.
    154 }
    155