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:
parent
0e9e7fc0b2
commit
cf19d2a645
@ -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
|
||||
|
@ -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
16
test/Other/statistic.ll
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user