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