mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-27 15:22:29 +00:00
Change the implementation of statistic to not need destructors at all.
Instead, the stat info is printed when llvm_shutdown() is called. These also don't need static ctors, but getting rid of them is uglier: still investigating. This reduces the number of static dtors in llvm from ~1400 to ~750. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32372 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4d9a186b10
commit
975f05852d
@ -31,29 +31,36 @@ namespace llvm {
|
||||
class Statistic {
|
||||
const char *Name;
|
||||
const char *Desc;
|
||||
unsigned Value;
|
||||
static unsigned NumStats;
|
||||
unsigned Value : 31;
|
||||
bool Initialized : 1;
|
||||
public:
|
||||
// Normal constructor, default initialize data item...
|
||||
Statistic(const char *name, const char *desc)
|
||||
: Name(name), Desc(desc), Value(0) {
|
||||
++NumStats; // Keep track of how many stats are created...
|
||||
: Name(name), Desc(desc), Value(0), Initialized(0) {
|
||||
}
|
||||
|
||||
// Print information when destroyed, iff command line option is specified
|
||||
~Statistic();
|
||||
|
||||
// Allow use of this class as the value itself...
|
||||
unsigned getValue() const { return Value; }
|
||||
const char *getName() const { return Name; }
|
||||
const char *getDesc() const { return Desc; }
|
||||
|
||||
// Allow use of this class as the value itself.
|
||||
operator unsigned() const { return Value; }
|
||||
const Statistic &operator=(unsigned Val) { Value = Val; return *this; }
|
||||
const Statistic &operator++() { ++Value; return *this; }
|
||||
unsigned operator++(int) { return Value++; }
|
||||
const Statistic &operator--() { --Value; return *this; }
|
||||
unsigned operator--(int) { return Value--; }
|
||||
const Statistic &operator+=(const unsigned &V) { Value += V; return *this; }
|
||||
const Statistic &operator-=(const unsigned &V) { Value -= V; return *this; }
|
||||
const Statistic &operator*=(const unsigned &V) { Value *= V; return *this; }
|
||||
const Statistic &operator/=(const unsigned &V) { Value /= V; return *this; }
|
||||
const Statistic &operator=(unsigned Val) { Value = Val; return init(); }
|
||||
const Statistic &operator++() { ++Value; return init(); }
|
||||
unsigned operator++(int) { init(); return Value++; }
|
||||
const Statistic &operator--() { --Value; return init(); }
|
||||
unsigned operator--(int) { init(); return Value--; }
|
||||
const Statistic &operator+=(const unsigned &V) { Value += V; return init(); }
|
||||
const Statistic &operator-=(const unsigned &V) { Value -= V; return init(); }
|
||||
const Statistic &operator*=(const unsigned &V) { Value *= V; return init(); }
|
||||
const Statistic &operator/=(const unsigned &V) { Value /= V; return init(); }
|
||||
|
||||
private:
|
||||
Statistic &init() {
|
||||
if (!Initialized) RegisterStatistic();
|
||||
return *this;
|
||||
}
|
||||
void RegisterStatistic();
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -15,7 +15,7 @@
|
||||
// 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");
|
||||
// static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
|
||||
//
|
||||
// Later, in the code: ++NumInstEliminated;
|
||||
//
|
||||
@ -23,84 +23,99 @@
|
||||
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
|
||||
// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
|
||||
namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }
|
||||
|
||||
unsigned Statistic::NumStats = 0;
|
||||
|
||||
// -stats - Command line option to cause transformations to emit stats about
|
||||
// what they did.
|
||||
//
|
||||
/// -stats - Command line option to cause transformations to emit stats about
|
||||
/// what they did.
|
||||
///
|
||||
static cl::opt<bool>
|
||||
Enabled("stats", cl::desc("Enable statistics output from program"));
|
||||
|
||||
struct StatRecord {
|
||||
std::string Value;
|
||||
const char *Name, *Desc;
|
||||
|
||||
StatRecord(const std::string &V, const char *N, const char *D)
|
||||
: Value(V), Name(N), Desc(D) {}
|
||||
|
||||
bool operator<(const StatRecord &SR) const {
|
||||
return std::strcmp(Name, SR.Name) < 0;
|
||||
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;
|
||||
public:
|
||||
~StatisticInfo();
|
||||
|
||||
void addStatistic(const Statistic *S) {
|
||||
Stats.push_back(S);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void print(unsigned ValFieldSize, unsigned NameFieldSize,
|
||||
std::ostream &OS) {
|
||||
OS << std::string(ValFieldSize-Value.length(), ' ')
|
||||
<< Value << " " << Name
|
||||
<< std::string(NameFieldSize-std::strlen(Name), ' ')
|
||||
<< " - " << Desc << "\n";
|
||||
static ManagedStatic<StatisticInfo> StatInfo;
|
||||
|
||||
|
||||
/// 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.
|
||||
if (Enabled)
|
||||
StatInfo->addStatistic(this);
|
||||
// Remember we have been registered.
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
struct NameCompare {
|
||||
bool operator()(const Statistic *LHS, const Statistic *RHS) const {
|
||||
int Cmp = std::strcmp(LHS->getName(), RHS->getName());
|
||||
if (Cmp != 0) return Cmp < 0;
|
||||
|
||||
// Secondary key is the description.
|
||||
return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
static std::vector<StatRecord> *AccumStats = 0;
|
||||
// Print information when destroyed, iff command line option is specified.
|
||||
StatisticInfo::~StatisticInfo() {
|
||||
// Statistics not enabled?
|
||||
if (Stats.empty()) return;
|
||||
|
||||
// Print information when destroyed, iff command line option is specified
|
||||
Statistic::~Statistic() {
|
||||
if (Enabled && Value != 0) {
|
||||
if (AccumStats == 0)
|
||||
AccumStats = new std::vector<StatRecord>();
|
||||
// Get the stream to write to.
|
||||
std::ostream &OutStream = *GetLibSupportInfoOutputFile();
|
||||
|
||||
AccumStats->push_back(StatRecord(utostr(Value), Name, Desc));
|
||||
// Figure out how long the biggest Value and Name fields are.
|
||||
unsigned MaxNameLen = 0, MaxValLen = 0;
|
||||
for (unsigned i = 0, e = Stats.size(); i != e; ++i) {
|
||||
MaxValLen = std::max(MaxValLen,
|
||||
(unsigned)utostr(Stats[i]->getValue()).size());
|
||||
MaxNameLen = std::max(MaxNameLen,
|
||||
(unsigned)std::strlen(Stats[i]->getName()));
|
||||
}
|
||||
|
||||
// Sort the fields by name.
|
||||
std::stable_sort(Stats.begin(), Stats.end(), NameCompare());
|
||||
|
||||
if (--NumStats == 0 && AccumStats) {
|
||||
std::ostream *OutStream = GetLibSupportInfoOutputFile();
|
||||
|
||||
// Figure out how long the biggest Value and Name fields are...
|
||||
unsigned MaxNameLen = 0, MaxValLen = 0;
|
||||
for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) {
|
||||
MaxValLen = std::max(MaxValLen,
|
||||
(unsigned)(*AccumStats)[i].Value.length());
|
||||
MaxNameLen = std::max(MaxNameLen,
|
||||
(unsigned)std::strlen((*AccumStats)[i].Name));
|
||||
}
|
||||
|
||||
// Sort the fields...
|
||||
std::stable_sort(AccumStats->begin(), AccumStats->end());
|
||||
|
||||
// Print out the statistics header...
|
||||
*OutStream << "===" << std::string(73, '-') << "===\n"
|
||||
<< " ... Statistics Collected ...\n"
|
||||
<< "===" << std::string(73, '-') << "===\n\n";
|
||||
|
||||
// Print all of the statistics accumulated...
|
||||
for (unsigned i = 0, e = AccumStats->size(); i != e; ++i)
|
||||
(*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream);
|
||||
|
||||
*OutStream << std::endl; // Flush the output stream...
|
||||
|
||||
// Free all accumulated statistics...
|
||||
delete AccumStats;
|
||||
AccumStats = 0;
|
||||
if (OutStream != cerr.stream() && OutStream != cout.stream())
|
||||
delete OutStream; // Close the file...
|
||||
// Print out the statistics header...
|
||||
OutStream << "===" << std::string(73, '-') << "===\n"
|
||||
<< " ... Statistics Collected ...\n"
|
||||
<< "===" << std::string(73, '-') << "===\n\n";
|
||||
|
||||
// Print all of the statistics.
|
||||
for (unsigned i = 0, e = Stats.size(); i != e; ++i) {
|
||||
std::string CountStr = utostr(Stats[i]->getValue());
|
||||
OutStream << std::string(MaxValLen-CountStr.size(), ' ')
|
||||
<< CountStr << " " << Stats[i]->getName()
|
||||
<< std::string(MaxNameLen-std::strlen(Stats[i]->getName()), ' ')
|
||||
<< " - " << Stats[i]->getDesc() << "\n";
|
||||
|
||||
}
|
||||
|
||||
OutStream << std::endl; // Flush the output stream...
|
||||
|
||||
if (&OutStream != cerr.stream() && &OutStream != cout.stream())
|
||||
delete &OutStream; // Close the file.
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user