#ifndef LLVM_ADT_STATISTIC_H
#define LLVM_ADT_STATISTIC_H
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/Compiler.h"
#include <atomic>
#include <memory>
#include <vector>
#if !defined(NDEBUG) || LLVM_FORCE_ENABLE_STATS
#define LLVM_ENABLE_STATS 1
#else
#define LLVM_ENABLE_STATS 0
#endif
namespace llvm {
class raw_ostream;
class raw_fd_ostream;
class StringRef;
class TrackingStatistic {
public:
const char *const DebugType;
const char *const Name;
const char *const Desc;
std::atomic<uint64_t> Value;
std::atomic<bool> Initialized;
constexpr TrackingStatistic(const char *DebugType, const char *Name,
const char *Desc)
: DebugType(DebugType), Name(Name), Desc(Desc), Value(0),
Initialized(false) {}
const char *getDebugType() const { return DebugType; }
const char *getName() const { return Name; }
const char *getDesc() const { return Desc; }
uint64_t getValue() const { return Value.load(std::memory_order_relaxed); }
operator uint64_t() const { return getValue(); }
const TrackingStatistic &operator=(uint64_t Val) {
Value.store(Val, std::memory_order_relaxed);
return init();
}
const TrackingStatistic &operator++() {
Value.fetch_add(1, std::memory_order_relaxed);
return init();
}
uint64_t operator++(int) {
init();
return Value.fetch_add(1, std::memory_order_relaxed);
}
const TrackingStatistic &operator--() {
Value.fetch_sub(1, std::memory_order_relaxed);
return init();
}
uint64_t operator--(int) {
init();
return Value.fetch_sub(1, std::memory_order_relaxed);
}
const TrackingStatistic &operator+=(uint64_t V) {
if (V == 0)
return *this;
Value.fetch_add(V, std::memory_order_relaxed);
return init();
}
const TrackingStatistic &operator-=(uint64_t V) {
if (V == 0)
return *this;
Value.fetch_sub(V, std::memory_order_relaxed);
return init();
}
void updateMax(uint64_t V) {
uint64_t PrevMax = Value.load(std::memory_order_relaxed);
while (V > PrevMax && !Value.compare_exchange_weak(
PrevMax, V, std::memory_order_relaxed)) {
}
init();
}
protected:
TrackingStatistic &init() {
if (!Initialized.load(std::memory_order_acquire))
RegisterStatistic();
return *this;
}
void RegisterStatistic();
};
class NoopStatistic {
public:
NoopStatistic(const char * , const char * ,
const char * ) {}
uint64_t getValue() const { return 0; }
operator uint64_t() const { return 0; }
const NoopStatistic &operator=(uint64_t Val) { return *this; }
const NoopStatistic &operator++() { return *this; }
uint64_t operator++(int) { return 0; }
const NoopStatistic &operator--() { return *this; }
uint64_t operator--(int) { return 0; }
const NoopStatistic &operator+=(const uint64_t &V) { return *this; }
const NoopStatistic &operator-=(const uint64_t &V) { return *this; }
void updateMax(uint64_t V) {}
};
#if LLVM_ENABLE_STATS
using Statistic = TrackingStatistic;
#else
using Statistic = NoopStatistic;
#endif
#define STATISTIC(VARNAME, DESC) \
static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC}
#define ALWAYS_ENABLED_STATISTIC(VARNAME, DESC) \
static llvm::TrackingStatistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC}
void EnableStatistics(bool DoPrintOnExit = true);
bool AreStatisticsEnabled();
std::unique_ptr<raw_fd_ostream> CreateInfoOutputFile();
void PrintStatistics();
void PrintStatistics(raw_ostream &OS);
void PrintStatisticsJSON(raw_ostream &OS);
const std::vector<std::pair<StringRef, uint64_t>> GetStatistics();
void ResetStatistics();
}
#endif