LCOV - code coverage report
Current view: top level - lib/Support - Statistic.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 41 66 62.1 %
Date: 2018-10-20 13:21:21 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/Timer.h"
      33             : #include "llvm/Support/YAMLTraits.h"
      34             : #include "llvm/Support/raw_ostream.h"
      35             : #include <algorithm>
      36             : #include <cstring>
      37             : using namespace llvm;
      38             : 
      39             : /// -stats - Command line option to cause transformations to emit stats about
      40             : /// what they did.
      41             : ///
      42             : static cl::opt<bool> Stats(
      43             :     "stats",
      44             :     cl::desc("Enable statistics output from program (available with Asserts)"),
      45             :     cl::Hidden);
      46             : 
      47             : static cl::opt<bool> StatsAsJSON("stats-json",
      48             :                                  cl::desc("Display statistics as json data"),
      49             :                                  cl::Hidden);
      50             : 
      51             : static bool Enabled;
      52             : static bool PrintOnExit;
      53             : 
      54             : namespace {
      55             : /// This class is used in a ManagedStatic so that it is created on demand (when
      56             : /// the first statistic is bumped) and destroyed only when llvm_shutdown is
      57             : /// called. We print statistics from the destructor.
      58             : /// This class is also used to look up statistic values from applications that
      59             : /// use LLVM.
      60             : class StatisticInfo {
      61             :   std::vector<Statistic*> Stats;
      62             : 
      63             :   friend void llvm::PrintStatistics();
      64             :   friend void llvm::PrintStatistics(raw_ostream &OS);
      65             :   friend void llvm::PrintStatisticsJSON(raw_ostream &OS);
      66             : 
      67             :   /// Sort statistics by debugtype,name,description.
      68             :   void sort();
      69             : public:
      70             :   using const_iterator = std::vector<Statistic *>::const_iterator;
      71             : 
      72             :   StatisticInfo();
      73             :   ~StatisticInfo();
      74             : 
      75             :   void addStatistic(Statistic *S) {
      76           0 :     Stats.push_back(S);
      77             :   }
      78             : 
      79           1 :   const_iterator begin() const { return Stats.begin(); }
      80           1 :   const_iterator end() const { return Stats.end(); }
      81             :   iterator_range<const_iterator> statistics() const {
      82             :     return {begin(), end()};
      83             :   }
      84             : 
      85             :   void reset();
      86             : };
      87             : } // end anonymous namespace
      88             : 
      89             : static ManagedStatic<StatisticInfo> StatInfo;
      90             : static ManagedStatic<sys::SmartMutex<true> > StatLock;
      91             : 
      92             : /// RegisterStatistic - The first time a statistic is bumped, this method is
      93             : /// called.
      94           0 : void Statistic::RegisterStatistic() {
      95             :   // If stats are enabled, inform StatInfo that this statistic should be
      96             :   // printed.
      97             :   // llvm_shutdown calls destructors while holding the ManagedStatic mutex.
      98             :   // These destructors end up calling PrintStatistics, which takes StatLock.
      99             :   // Since dereferencing StatInfo and StatLock can require taking the
     100             :   // ManagedStatic mutex, doing so with StatLock held would lead to a lock
     101             :   // order inversion. To avoid that, we dereference the ManagedStatics first,
     102             :   // and only take StatLock afterwards.
     103           0 :   if (!Initialized.load(std::memory_order_relaxed)) {
     104           0 :     sys::SmartMutex<true> &Lock = *StatLock;
     105           0 :     StatisticInfo &SI = *StatInfo;
     106             :     sys::SmartScopedLock<true> Writer(Lock);
     107             :     // Check Initialized again after acquiring the lock.
     108           0 :     if (Initialized.load(std::memory_order_relaxed))
     109             :       return;
     110           0 :     if (Stats || Enabled)
     111           0 :       SI.addStatistic(this);
     112             : 
     113             :     // Remember we have been registered.
     114             :     Initialized.store(true, std::memory_order_release);
     115             :   }
     116             : }
     117             : 
     118             : StatisticInfo::StatisticInfo() {
     119             :   // Ensure timergroup lists are created first so they are destructed after us.
     120           6 :   TimerGroup::ConstructTimerLists();
     121             : }
     122             : 
     123             : // Print information when destroyed, iff command line option is specified.
     124           5 : StatisticInfo::~StatisticInfo() {
     125           5 :   if (::Stats || PrintOnExit)
     126           0 :     llvm::PrintStatistics();
     127           5 : }
     128             : 
     129           9 : void llvm::EnableStatistics(bool PrintOnExit) {
     130           9 :   Enabled = true;
     131           9 :   ::PrintOnExit = PrintOnExit;
     132           9 : }
     133             : 
     134         117 : bool llvm::AreStatisticsEnabled() {
     135         117 :   return Enabled || Stats;
     136             : }
     137             : 
     138             : void StatisticInfo::sort() {
     139           5 :   std::stable_sort(Stats.begin(), Stats.end(),
     140             :                    [](const Statistic *LHS, const Statistic *RHS) {
     141             :     if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
     142             :       return Cmp < 0;
     143             : 
     144             :     if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
     145             :       return Cmp < 0;
     146             : 
     147             :     return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
     148             :   });
     149             : }
     150             : 
     151           1 : void StatisticInfo::reset() {
     152           1 :   sys::SmartScopedLock<true> Writer(*StatLock);
     153             : 
     154             :   // Tell each statistic that it isn't registered so it has to register
     155             :   // again. We're holding the lock so it won't be able to do so until we're
     156             :   // finished. Once we've forced it to re-register (after we return), then zero
     157             :   // the value.
     158           1 :   for (auto *Stat : Stats) {
     159             :     // Value updates to a statistic that complete before this statement in the
     160             :     // iteration for that statistic will be lost as intended.
     161             :     Stat->Initialized = false;
     162             :     Stat->Value = 0;
     163             :   }
     164             : 
     165             :   // Clear the registration list and release the lock once we're done. Any
     166             :   // pending updates from other threads will safely take effect after we return.
     167             :   // That might not be what the user wants if they're measuring a compilation
     168             :   // but it's their responsibility to prevent concurrent compilations to make
     169             :   // a single compilation measurable.
     170             :   Stats.clear();
     171           1 : }
     172             : 
     173           4 : void llvm::PrintStatistics(raw_ostream &OS) {
     174           4 :   StatisticInfo &Stats = *StatInfo;
     175             : 
     176             :   // Figure out how long the biggest Value and Name fields are.
     177           4 :   unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
     178           4 :   for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
     179           0 :     MaxValLen = std::max(MaxValLen,
     180           0 :                          (unsigned)utostr(Stats.Stats[i]->getValue()).size());
     181           0 :     MaxDebugTypeLen = std::max(MaxDebugTypeLen,
     182           0 :                          (unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
     183             :   }
     184             : 
     185             :   Stats.sort();
     186             : 
     187             :   // Print out the statistics header...
     188           8 :   OS << "===" << std::string(73, '-') << "===\n"
     189           4 :      << "                          ... Statistics Collected ...\n"
     190          12 :      << "===" << std::string(73, '-') << "===\n\n";
     191             : 
     192             :   // Print all of the statistics.
     193           4 :   for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
     194           0 :     OS << format("%*u %-*s - %s\n",
     195             :                  MaxValLen, Stats.Stats[i]->getValue(),
     196           0 :                  MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
     197           0 :                  Stats.Stats[i]->getDesc());
     198             : 
     199             :   OS << '\n';  // Flush the output stream.
     200             :   OS.flush();
     201           4 : }
     202             : 
     203           1 : void llvm::PrintStatisticsJSON(raw_ostream &OS) {
     204           1 :   sys::SmartScopedLock<true> Reader(*StatLock);
     205           1 :   StatisticInfo &Stats = *StatInfo;
     206             : 
     207             :   Stats.sort();
     208             : 
     209             :   // Print all of the statistics.
     210           1 :   OS << "{\n";
     211             :   const char *delim = "";
     212           1 :   for (const Statistic *Stat : Stats.Stats) {
     213           0 :     OS << delim;
     214             :     assert(yaml::needsQuotes(Stat->getDebugType()) == yaml::QuotingType::None &&
     215             :            "Statistic group/type name is simple.");
     216             :     assert(yaml::needsQuotes(Stat->getName()) == yaml::QuotingType::None &&
     217             :            "Statistic name is simple");
     218           0 :     OS << "\t\"" << Stat->getDebugType() << '.' << Stat->getName() << "\": "
     219             :        << Stat->getValue();
     220             :     delim = ",\n";
     221             :   }
     222             :   // Print timers.
     223           1 :   TimerGroup::printAllJSONValues(OS, delim);
     224             : 
     225           1 :   OS << "\n}\n";
     226             :   OS.flush();
     227           1 : }
     228             : 
     229           0 : void llvm::PrintStatistics() {
     230             : #if LLVM_ENABLE_STATS
     231             :   sys::SmartScopedLock<true> Reader(*StatLock);
     232             :   StatisticInfo &Stats = *StatInfo;
     233             : 
     234             :   // Statistics not enabled?
     235             :   if (Stats.Stats.empty()) return;
     236             : 
     237             :   // Get the stream to write to.
     238             :   std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
     239             :   if (StatsAsJSON)
     240             :     PrintStatisticsJSON(*OutStream);
     241             :   else
     242             :     PrintStatistics(*OutStream);
     243             : 
     244             : #else
     245             :   // Check if the -stats option is set instead of checking
     246             :   // !Stats.Stats.empty().  In release builds, Statistics operators
     247             :   // do nothing, so stats are never Registered.
     248           0 :   if (Stats) {
     249             :     // Get the stream to write to.
     250           0 :     std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
     251           0 :     (*OutStream) << "Statistics are disabled.  "
     252           0 :                  << "Build with asserts or with -DLLVM_ENABLE_STATS\n";
     253             :   }
     254             : #endif
     255           0 : }
     256             : 
     257           1 : const std::vector<std::pair<StringRef, unsigned>> llvm::GetStatistics() {
     258           1 :   sys::SmartScopedLock<true> Reader(*StatLock);
     259             :   std::vector<std::pair<StringRef, unsigned>> ReturnStats;
     260             : 
     261           1 :   for (const auto &Stat : StatInfo->statistics())
     262           0 :     ReturnStats.emplace_back(Stat->getName(), Stat->getValue());
     263           1 :   return ReturnStats;
     264             : }
     265             : 
     266           1 : void llvm::ResetStatistics() {
     267           1 :   StatInfo->reset();
     268           1 : }

Generated by: LCOV version 1.13