Home | History | Annotate | Download | only in ADT
      1 //===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===//
      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 defines the 'Statistic' class, which is designed to be an easy way
     11 // to expose various metrics from passes.  These statistics are printed at the
     12 // end of a run (from llvm_shutdown), when the -stats command line option is
     13 // passed 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 NumInstsKilled("gcse", "Number of instructions killed");
     19 //
     20 // Later, in the code: ++NumInstsKilled;
     21 //
     22 // NOTE: Statistics *must* be declared as global variables.
     23 //
     24 //===----------------------------------------------------------------------===//
     25 
     26 #ifndef LLVM_ADT_STATISTIC_H
     27 #define LLVM_ADT_STATISTIC_H
     28 
     29 #include "llvm/Support/Atomic.h"
     30 #include "llvm/Support/Compiler.h"
     31 #include <atomic>
     32 #include <memory>
     33 
     34 namespace llvm {
     35 
     36 class raw_ostream;
     37 class raw_fd_ostream;
     38 
     39 class Statistic {
     40 public:
     41   const char *DebugType;
     42   const char *Name;
     43   const char *Desc;
     44   std::atomic<unsigned> Value;
     45   bool Initialized;
     46 
     47   unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
     48   const char *getDebugType() const { return DebugType; }
     49   const char *getName() const { return Name; }
     50   const char *getDesc() const { return Desc; }
     51 
     52   /// construct - This should only be called for non-global statistics.
     53   void construct(const char *debugtype, const char *name, const char *desc) {
     54     DebugType = debugtype;
     55     Name = name;
     56     Desc = desc;
     57     Value = 0;
     58     Initialized = false;
     59   }
     60 
     61   // Allow use of this class as the value itself.
     62   operator unsigned() const { return getValue(); }
     63 
     64 #if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
     65    const Statistic &operator=(unsigned Val) {
     66     Value.store(Val, std::memory_order_relaxed);
     67     return init();
     68   }
     69 
     70   const Statistic &operator++() {
     71     Value.fetch_add(1, std::memory_order_relaxed);
     72     return init();
     73   }
     74 
     75   unsigned operator++(int) {
     76     init();
     77     return Value.fetch_add(1, std::memory_order_relaxed);
     78   }
     79 
     80   const Statistic &operator--() {
     81     Value.fetch_sub(1, std::memory_order_relaxed);
     82     return init();
     83   }
     84 
     85   unsigned operator--(int) {
     86     init();
     87     return Value.fetch_sub(1, std::memory_order_relaxed);
     88   }
     89 
     90   const Statistic &operator+=(unsigned V) {
     91     if (V == 0)
     92       return *this;
     93     Value.fetch_add(V, std::memory_order_relaxed);
     94     return init();
     95   }
     96 
     97   const Statistic &operator-=(unsigned V) {
     98     if (V == 0)
     99       return *this;
    100     Value.fetch_sub(V, std::memory_order_relaxed);
    101     return init();
    102   }
    103 
    104 #else  // Statistics are disabled in release builds.
    105 
    106   const Statistic &operator=(unsigned Val) {
    107     return *this;
    108   }
    109 
    110   const Statistic &operator++() {
    111     return *this;
    112   }
    113 
    114   unsigned operator++(int) {
    115     return 0;
    116   }
    117 
    118   const Statistic &operator--() {
    119     return *this;
    120   }
    121 
    122   unsigned operator--(int) {
    123     return 0;
    124   }
    125 
    126   const Statistic &operator+=(const unsigned &V) {
    127     return *this;
    128   }
    129 
    130   const Statistic &operator-=(const unsigned &V) {
    131     return *this;
    132   }
    133 
    134 #endif  // !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
    135 
    136 protected:
    137   Statistic &init() {
    138     bool tmp = Initialized;
    139     sys::MemoryFence();
    140     if (!tmp) RegisterStatistic();
    141     TsanHappensAfter(this);
    142     return *this;
    143   }
    144 
    145   void RegisterStatistic();
    146 };
    147 
    148 // STATISTIC - A macro to make definition of statistics really simple.  This
    149 // automatically passes the DEBUG_TYPE of the file into the statistic.
    150 #define STATISTIC(VARNAME, DESC)                                               \
    151   static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, false}
    152 
    153 /// \brief Enable the collection and printing of statistics.
    154 void EnableStatistics(bool PrintOnExit = true);
    155 
    156 /// \brief Check if statistics are enabled.
    157 bool AreStatisticsEnabled();
    158 
    159 /// \brief Return a file stream to print our output on.
    160 std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
    161 
    162 /// \brief Print statistics to the file returned by CreateInfoOutputFile().
    163 void PrintStatistics();
    164 
    165 /// \brief Print statistics to the given output stream.
    166 void PrintStatistics(raw_ostream &OS);
    167 
    168 /// Print statistics in JSON format. This does include all global timers (\see
    169 /// Timer, TimerGroup). Note that the timers are cleared after printing and will
    170 /// not be printed in human readable form or in a second call of
    171 /// PrintStatisticsJSON().
    172 void PrintStatisticsJSON(raw_ostream &OS);
    173 
    174 } // end namespace llvm
    175 
    176 #endif // LLVM_ADT_STATISTIC_H
    177