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/Compiler.h"
     28 #include "llvm/Support/Debug.h"
     29 #include "llvm/Support/Format.h"
     30 #include "llvm/Support/ManagedStatic.h"
     31 #include "llvm/Support/Mutex.h"
     32 #include "llvm/Support/raw_ostream.h"
     33 #include <algorithm>
     34 #include <cstring>
     35 using namespace llvm;
     36 
     37 /// -stats - Command line option to cause transformations to emit stats about
     38 /// what they did.
     39 ///
     40 static cl::opt<bool>
     41 Enabled(
     42     "stats",
     43     cl::desc("Enable statistics output from program (available with Asserts)"));
     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 // Print information when destroyed, iff command line option is specified.
     86 StatisticInfo::~StatisticInfo() {
     87   llvm::PrintStatistics();
     88 }
     89 
     90 void llvm::EnableStatistics() {
     91   Enabled.setValue(true);
     92 }
     93 
     94 bool llvm::AreStatisticsEnabled() {
     95   return Enabled;
     96 }
     97 
     98 void llvm::PrintStatistics(raw_ostream &OS) {
     99   StatisticInfo &Stats = *StatInfo;
    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.Stats.size(); i != e; ++i) {
    104     MaxValLen = std::max(MaxValLen,
    105                          (unsigned)utostr(Stats.Stats[i]->getValue()).size());
    106     MaxNameLen = std::max(MaxNameLen,
    107                           (unsigned)std::strlen(Stats.Stats[i]->getName()));
    108   }
    109 
    110   // Sort the fields by name.
    111   std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(),
    112                    [](const Statistic *LHS, const Statistic *RHS) {
    113     if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
    114       return Cmp < 0;
    115 
    116     // Secondary key is the description.
    117     return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
    118   });
    119 
    120   // Print out the statistics header...
    121   OS << "===" << std::string(73, '-') << "===\n"
    122      << "                          ... Statistics Collected ...\n"
    123      << "===" << std::string(73, '-') << "===\n\n";
    124 
    125   // Print all of the statistics.
    126   for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
    127     OS << format("%*u %-*s - %s\n",
    128                  MaxValLen, Stats.Stats[i]->getValue(),
    129                  MaxNameLen, Stats.Stats[i]->getName(),
    130                  Stats.Stats[i]->getDesc());
    131 
    132   OS << '\n';  // Flush the output stream.
    133   OS.flush();
    134 
    135 }
    136 
    137 void llvm::PrintStatistics() {
    138 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
    139   StatisticInfo &Stats = *StatInfo;
    140 
    141   // Statistics not enabled?
    142   if (Stats.Stats.empty()) return;
    143 
    144   // Get the stream to write to.
    145   std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
    146   PrintStatistics(*OutStream);
    147 
    148 #else
    149   // Check if the -stats option is set instead of checking
    150   // !Stats.Stats.empty().  In release builds, Statistics operators
    151   // do nothing, so stats are never Registered.
    152   if (Enabled) {
    153     // Get the stream to write to.
    154     std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
    155     (*OutStream) << "Statistics are disabled.  "
    156                  << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
    157   }
    158 #endif
    159 }
    160