1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

Statistic: Add machine parseable json output

- We lacked a short unique identifier for a statistics, so I renamed the
  current "Name" field that just contained the DEBUG_TYPE name of the
  current file to DebugType and added a new "Name" field that contains
  the C++ identifier of the statistic variable.
- Add the -stats-json option which outputs statistics in json format.

Differential Revision: http://reviews.llvm.org/D20995

llvm-svn: 272826
This commit is contained in:
Matthias Braun 2016-06-15 20:19:16 +00:00
parent 0e9e7fc0b2
commit cf19d2a645
3 changed files with 88 additions and 18 deletions

View File

@ -37,19 +37,24 @@ class raw_fd_ostream;
class Statistic {
public:
const char *DebugType;
const char *Name;
const char *Desc;
std::atomic<unsigned> Value;
bool Initialized;
unsigned getValue() const { return Value.load(std::memory_order_relaxed); }
const char *getDebugType() const { return DebugType; }
const char *getName() const { return Name; }
const char *getDesc() const { return Desc; }
/// construct - This should only be called for non-global statistics.
void construct(const char *name, const char *desc) {
Name = name; Desc = desc;
Value = 0; Initialized = false;
void construct(const char *debugtype, const char *name, const char *desc) {
DebugType = debugtype;
Name = name;
Desc = desc;
Value = 0;
Initialized = false;
}
// Allow use of this class as the value itself.
@ -141,7 +146,7 @@ protected:
// STATISTIC - A macro to make definition of statistics really simple. This
// automatically passes the DEBUG_TYPE of the file into the statistic.
#define STATISTIC(VARNAME, DESC) \
static llvm::Statistic VARNAME = {DEBUG_TYPE, DESC, {0}, 0}
static llvm::Statistic VARNAME = {DEBUG_TYPE, #VARNAME, DESC, {0}, 0}
/// \brief Enable the collection and printing of statistics.
void EnableStatistics();
@ -158,6 +163,9 @@ void PrintStatistics();
/// \brief Print statistics to the given output stream.
void PrintStatistics(raw_ostream &OS);
/// Print statistics in JSON format.
void PrintStatisticsJSON(raw_ostream &OS);
} // end llvm namespace
#endif // LLVM_ADT_STATISTIC_H

View File

@ -43,6 +43,9 @@ Enabled(
cl::desc("Enable statistics output from program (available with Asserts)"));
static cl::opt<bool> StatsAsJSON("stats-json",
cl::desc("Display statistics as json data"));
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
@ -51,6 +54,10 @@ 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();
@ -95,27 +102,32 @@ bool llvm::AreStatisticsEnabled() {
return Enabled;
}
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 MaxNameLen = 0, MaxValLen = 0;
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());
MaxNameLen = std::max(MaxNameLen,
(unsigned)std::strlen(Stats.Stats[i]->getName()));
MaxDebugTypeLen = std::max(MaxDebugTypeLen,
(unsigned)std::strlen(Stats.Stats[i]->getDebugType()));
}
// Sort the fields by name.
std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(),
[](const Statistic *LHS, const Statistic *RHS) {
if (int Cmp = std::strcmp(LHS->getName(), RHS->getName()))
return Cmp < 0;
// Secondary key is the description.
return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
});
Stats.sort();
// Print out the statistics header...
OS << "===" << std::string(73, '-') << "===\n"
@ -126,12 +138,43 @@ void llvm::PrintStatistics(raw_ostream &OS) {
for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i)
OS << format("%*u %-*s - %s\n",
MaxValLen, Stats.Stats[i]->getValue(),
MaxNameLen, Stats.Stats[i]->getName(),
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() {
@ -143,6 +186,9 @@ void llvm::PrintStatistics() {
// Get the stream to write to.
std::unique_ptr<raw_ostream> OutStream = CreateInfoOutputFile();
if (StatsAsJSON)
PrintStatisticsJSON(*OutStream);
else
PrintStatistics(*OutStream);
#else

16
test/Other/statistic.ll Normal file
View File

@ -0,0 +1,16 @@
; RUN: opt < %s -o /dev/null -instsimplify -stats -stats-json 2>&1 | FileCheck %s --check-prefix=JSON
; RUN: opt < %s -o /dev/null -instsimplify -stats -stats-json -info-output-file %t && FileCheck %s < %t --check-prefix=JSON
; RUN: opt < %s -o /dev/null -instsimplify -stats 2>&1 | FileCheck %s --check-prefix=DEFAULT
; RUN: opt < %s -o /dev/null -instsimplify -stats -info-output-file %t && FileCheck %s < %t --check-prefix=DEFAULT
; REQUIRES: asserts
; JSON: {
; JSON: "instsimplify.NumSimplified": 1
; JSON: }
; DEFAULT: 1 instsimplify - Number of redundant instructions removed
define i32 @foo() {
%res = add i32 5, 4
ret i32 %res
}