llvm.org GIT mirror llvm / 975f058
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 Chris Lattner 13 years ago
2 changed file(s) with 98 addition(s) and 76 deletion(s). Raw diff Collapse all Expand all
3030 class Statistic {
3131 const char *Name;
3232 const char *Desc;
33 unsigned Value;
34 static unsigned NumStats;
33 unsigned Value : 31;
34 bool Initialized : 1;
3535 public:
3636 // Normal constructor, default initialize data item...
3737 Statistic(const char *name, const char *desc)
38 : Name(name), Desc(desc), Value(0) {
39 ++NumStats; // Keep track of how many stats are created...
38 : Name(name), Desc(desc), Value(0), Initialized(0) {
4039 }
4140
42 // Print information when destroyed, iff command line option is specified
43 ~Statistic();
44
45 // Allow use of this class as the value itself...
41 unsigned getValue() const { return Value; }
42 const char *getName() const { return Name; }
43 const char *getDesc() const { return Desc; }
44
45 // Allow use of this class as the value itself.
4646 operator unsigned() const { return Value; }
47 const Statistic &operator=(unsigned Val) { Value = Val; return *this; }
48 const Statistic &operator++() { ++Value; return *this; }
49 unsigned operator++(int) { return Value++; }
50 const Statistic &operator--() { --Value; return *this; }
51 unsigned operator--(int) { return Value--; }
52 const Statistic &operator+=(const unsigned &V) { Value += V; return *this; }
53 const Statistic &operator-=(const unsigned &V) { Value -= V; return *this; }
54 const Statistic &operator*=(const unsigned &V) { Value *= V; return *this; }
55 const Statistic &operator/=(const unsigned &V) { Value /= V; return *this; }
47 const Statistic &operator=(unsigned Val) { Value = Val; return init(); }
48 const Statistic &operator++() { ++Value; return init(); }
49 unsigned operator++(int) { init(); return Value++; }
50 const Statistic &operator--() { --Value; return init(); }
51 unsigned operator--(int) { init(); return Value--; }
52 const Statistic &operator+=(const unsigned &V) { Value += V; return init(); }
53 const Statistic &operator-=(const unsigned &V) { Value -= V; return init(); }
54 const Statistic &operator*=(const unsigned &V) { Value *= V; return init(); }
55 const Statistic &operator/=(const unsigned &V) { Value /= V; return init(); }
56
57 private:
58 Statistic &init() {
59 if (!Initialized) RegisterStatistic();
60 return *this;
61 }
62 void RegisterStatistic();
5663 };
5764
5865 } // End llvm namespace
1414 // This is useful for reporting information like the number of instructions
1515 // simplified, optimized or removed by various transformations, like this:
1616 //
17 // static Statistic NumInstEliminated("GCSE - Number of instructions killed");
17 // static Statistic NumInstEliminated("GCSE", "Number of instructions killed");
1818 //
1919 // Later, in the code: ++NumInstEliminated;
2020 //
2222
2323 #include "llvm/ADT/Statistic.h"
2424 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/ManagedStatic.h"
2526 #include "llvm/Support/Streams.h"
2627 #include "llvm/ADT/StringExtras.h"
2728 #include
2829 #include
2930 using namespace llvm;
3031
31 // GetLibSupportInfoOutputFile - Return a file stream to print our output on...
32 // GetLibSupportInfoOutputFile - Return a file stream to print our output on.
3233 namespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); }
3334
34 unsigned Statistic::NumStats = 0;
35
36 // -stats - Command line option to cause transformations to emit stats about
37 // what they did.
38 //
35 /// -stats - Command line option to cause transformations to emit stats about
36 /// what they did.
37 ///
3938 static cl::opt
4039 Enabled("stats", cl::desc("Enable statistics output from program"));
4140
42 struct StatRecord {
43 std::string Value;
44 const char *Name, *Desc;
4541
46 StatRecord(const std::string &V, const char *N, const char *D)
47 : Value(V), Name(N), Desc(D) {}
42 namespace {
43 /// StatisticInfo - This class is used in a ManagedStatic so that it is created
44 /// on demand (when the first statistic is bumped) and destroyed only when
45 /// llvm_shutdown is called. We print statistics from the destructor.
46 class StatisticInfo {
47 std::vector Stats;
48 public:
49 ~StatisticInfo();
50
51 void addStatistic(const Statistic *S) {
52 Stats.push_back(S);
53 }
54 };
55 }
4856
49 bool operator<(const StatRecord &SR) const {
50 return std::strcmp(Name, SR.Name) < 0;
51 }
57 static ManagedStatic StatInfo;
5258
53 void print(unsigned ValFieldSize, unsigned NameFieldSize,
54 std::ostream &OS) {
55 OS << std::string(ValFieldSize-Value.length(), ' ')
56 << Value << " " << Name
57 << std::string(NameFieldSize-std::strlen(Name), ' ')
58 << " - " << Desc << "\n";
59
60 /// RegisterStatistic - The first time a statistic is bumped, this method is
61 /// called.
62 void Statistic::RegisterStatistic() {
63 // If stats are enabled, inform StatInfo that this statistic should be
64 // printed.
65 if (Enabled)
66 StatInfo->addStatistic(this);
67 // Remember we have been registered.
68 Initialized = true;
69 }
70
71 struct NameCompare {
72 bool operator()(const Statistic *LHS, const Statistic *RHS) const {
73 int Cmp = std::strcmp(LHS->getName(), RHS->getName());
74 if (Cmp != 0) return Cmp < 0;
75
76 // Secondary key is the description.
77 return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0;
5978 }
6079 };
6180
62 static std::vector *AccumStats = 0;
81 // Print information when destroyed, iff command line option is specified.
82 StatisticInfo::~StatisticInfo() {
83 // Statistics not enabled?
84 if (Stats.empty()) return;
6385
64 // Print information when destroyed, iff command line option is specified
65 Statistic::~Statistic() {
66 if (Enabled && Value != 0) {
67 if (AccumStats == 0)
68 AccumStats = new std::vector();
86 // Get the stream to write to.
87 std::ostream &OutStream = *GetLibSupportInfoOutputFile();
6988
70 AccumStats->push_back(StatRecord(utostr(Value), Name, Desc));
89 // Figure out how long the biggest Value and Name fields are.
90 unsigned MaxNameLen = 0, MaxValLen = 0;
91 for (unsigned i = 0, e = Stats.size(); i != e; ++i) {
92 MaxValLen = std::max(MaxValLen,
93 (unsigned)utostr(Stats[i]->getValue()).size());
94 MaxNameLen = std::max(MaxNameLen,
95 (unsigned)std::strlen(Stats[i]->getName()));
7196 }
97
98 // Sort the fields by name.
99 std::stable_sort(Stats.begin(), Stats.end(), NameCompare());
72100
73 if (--NumStats == 0 && AccumStats) {
74 std::ostream *OutStream = GetLibSupportInfoOutputFile();
75
76 // Figure out how long the biggest Value and Name fields are...
77 unsigned MaxNameLen = 0, MaxValLen = 0;
78 for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) {
79 MaxValLen = std::max(MaxValLen,
80 (unsigned)(*AccumStats)[i].Value.length());
81 MaxNameLen = std::max(MaxNameLen,
82 (unsigned)std::strlen((*AccumStats)[i].Name));
83 }
84
85 // Sort the fields...
86 std::stable_sort(AccumStats->begin(), AccumStats->end());
87
88 // Print out the statistics header...
89 *OutStream << "===" << std::string(73, '-') << "===\n"
90 << " ... Statistics Collected ...\n"
91 << "===" << std::string(73, '-') << "===\n\n";
92
93 // Print all of the statistics accumulated...
94 for (unsigned i = 0, e = AccumStats->size(); i != e; ++i)
95 (*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream);
96
97 *OutStream << std::endl; // Flush the output stream...
98
99 // Free all accumulated statistics...
100 delete AccumStats;
101 AccumStats = 0;
102 if (OutStream != cerr.stream() && OutStream != cout.stream())
103 delete OutStream; // Close the file...
101 // Print out the statistics header...
102 OutStream << "===" << std::string(73, '-') << "===\n"
103 << " ... Statistics Collected ...\n"
104 << "===" << std::string(73, '-') << "===\n\n";
105
106 // Print all of the statistics.
107 for (unsigned i = 0, e = Stats.size(); i != e; ++i) {
108 std::string CountStr = utostr(Stats[i]->getValue());
109 OutStream << std::string(MaxValLen-CountStr.size(), ' ')
110 << CountStr << " " << Stats[i]->getName()
111 << std::string(MaxNameLen-std::strlen(Stats[i]->getName()), ' ')
112 << " - " << Stats[i]->getDesc() << "\n";
113
104114 }
115
116 OutStream << std::endl; // Flush the output stream...
117
118 if (&OutStream != cerr.stream() && &OutStream != cout.stream())
119 delete &OutStream; // Close the file.
105120 }