1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00
llvm-mirror/lib/Support/Statistic.cpp
Matthias Braun b39447d67c Statistic: Bring back printing on exit by default
Turns out several external projects relied on llvm printing statistics
on exit. Let's go back to this behaviour by default and have an optional
parameter to disable it.

llvm-svn: 282532
2016-09-27 19:38:55 +00:00

209 lines
6.4 KiB
C++

//===-- Statistic.cpp - Easy way to expose stats information --------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the 'Statistic' class, which is designed to be an easy
// way to expose various success metrics from passes. These statistics are
// printed at the end of a run, when the -stats command line option is enabled
// on the command line.
//
// This is useful for reporting information like the number of instructions
// simplified, optimized or removed by various transformations, like this:
//
// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
//
// Later, in the code: ++NumInstEliminated;
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstring>
using namespace llvm;
/// -stats - Command line option to cause transformations to emit stats about
/// what they did.
///
static cl::opt<bool> Stats("stats",
cl::desc("Enable statistics output from program (available with Asserts)"));
static cl::opt<bool> StatsAsJSON("stats-json",
cl::desc("Display statistics as json data"));
static bool Enabled;
static bool PrintOnExit;
namespace {
/// StatisticInfo - This class is used in a ManagedStatic so that it is created
/// on demand (when the first statistic is bumped) and destroyed only when
/// llvm_shutdown is called. We print statistics from the destructor.
class StatisticInfo {
std::vector<const Statistic*> Stats;
friend void llvm::PrintStatistics();
friend void llvm::PrintStatistics(raw_ostream &OS);
friend void llvm::PrintStatisticsJSON(raw_ostream &OS);
/// Sort statistics by debugtype,name,description.
void sort();
public:
~StatisticInfo();
void addStatistic(const Statistic *S) {
Stats.push_back(S);
}
};
}
static ManagedStatic<StatisticInfo> StatInfo;
static ManagedStatic<sys::SmartMutex<true> > StatLock;
/// RegisterStatistic - The first time a statistic is bumped, this method is
/// called.
void Statistic::RegisterStatistic() {
// If stats are enabled, inform StatInfo that this statistic should be
// printed.
sys::SmartScopedLock<true> Writer(*StatLock);
if (!Initialized) {
if (Stats || Enabled)
StatInfo->addStatistic(this);
TsanHappensBefore(this);
sys::MemoryFence();
// Remember we have been registered.
TsanIgnoreWritesBegin();
Initialized = true;
TsanIgnoreWritesEnd();
}
}
// Print information when destroyed, iff command line option is specified.
StatisticInfo::~StatisticInfo() {
if (::Stats || PrintOnExit)
llvm::PrintStatistics();
}
void llvm::EnableStatistics(bool PrintOnExit) {
Enabled = true;
::PrintOnExit = PrintOnExit;
}
bool llvm::AreStatisticsEnabled() {
return Enabled || Stats;
}
void StatisticInfo::sort() {
std::stable_sort(Stats.begin(), Stats.end(),
[](const Statistic *LHS, const Statistic *RHS) {
if (int Cmp = std::strcmp(LHS->getDebugType(), RHS->getDebugType()))
return Cmp < 0;
if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
return Cmp < 0;
return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
});
}
void llvm::PrintStatistics(raw_ostream &OS) {
StatisticInfo &Stats = *StatInfo;
// Figure out how long the biggest Value and Name fields are.
unsigned MaxDebugTypeLen = 0, MaxValLen = 0;
for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) {
MaxValLen = std::max(MaxValLen,
(unsigned)utostr(Stats.Stats[i]->getValue()).size());
MaxDebugTypeLen = std::max(MaxDebugTypeLen,
(unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
}
Stats.sort();
// Print out the statistics header...
OS << "===" << std::string(73, '-') << "===\n"
<< " ... Statistics Collected ...\n"
<< "===" << std::string(73, '-') << "===\n\n";
// Print all of the statistics.
for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
OS << format("%*u %-*s - %s\n",
MaxValLen, Stats.Stats[i]->getValue(),
MaxDebugTypeLen, Stats.Stats[i]->getDebugType(),
Stats.Stats[i]->getDesc());
OS << '\n'; // Flush the output stream.
OS.flush();
}
static void write_json_string_escaped(raw_ostream &OS, const char *string) {
// Out current usage should not need any escaping. Keep it simple and just
// check that the input is pure ASCII without special characers.
#ifndef NDEBUG
for (const unsigned char *c = (const unsigned char*)string; *c != '\0'; ++c) {
assert(*c != '\\' && *c != '\"' && *c >= 0x20 && *c < 0x80);
}
#endif
OS << string;
}
void llvm::PrintStatisticsJSON(raw_ostream &OS) {
StatisticInfo &Stats = *StatInfo;
Stats.sort();
// Print all of the statistics.
OS << "{\n";
const char *delim = "";
for (const Statistic *Stat : Stats.Stats) {
OS << delim;
OS << "\t\"";
write_json_string_escaped(OS, Stat->getDebugType());
OS << '.';
write_json_string_escaped(OS, Stat->getName());
OS << "\": " << Stat->getValue();
delim = ",\n";
}
OS << "\n}\n";
OS.flush();
}
void llvm::PrintStatistics() {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS)
StatisticInfo &Stats = *StatInfo;
// Statistics not enabled?
if (Stats.Stats.empty()) return;
// Get the stream to write to.
std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
if (StatsAsJSON)
PrintStatisticsJSON(*OutStream);
else
PrintStatistics(*OutStream);
#else
// Check if the -stats option is set instead of checking
// !Stats.Stats.empty(). In release builds, Statistics operators
// do nothing, so stats are never Registered.
if (Stats) {
// Get the stream to write to.
std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
(*OutStream) << "Statistics are disabled. "
<< "Build with asserts or with -DLLVM_ENABLE_STATS\n";
}
#endif
}