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