1 //===-- Statistic.cpp - Easy way to expose stats information --------------===// 2 // 3 // This file implements the 'Statistic' class, which is designed to be an easy 4 // way to expose various success metrics from passes. These statistics are 5 // printed at the end of a run, when the -stats command line option is enabled 6 // on the command line. 7 // 8 // This is useful for reporting information like the number of instructions 9 // simplified, optimized or removed by various transformations, like this: 10 // 11 // static Statistic<> NumInstEliminated("GCSE - Number of instructions killed"); 12 // 13 // Later, in the code: ++NumInstEliminated; 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "Support/Statistic.h" 18 #include "Support/CommandLine.h" 19 #include <iostream> 20 #include <sstream> 21 #include <algorithm> 22 23 bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option 24 25 unsigned StatisticBase::NumStats = 0; 26 27 // -stats - Command line option to cause transformations to emit stats about 28 // what they did. 29 // 30 static cl::opt<bool> 31 Enabled("stats", cl::desc("Enable statistics output from program")); 32 33 // -debug - Command line option to enable the DEBUG statements in the passes. 34 static cl::opt<bool, true> 35 Debug("debug", cl::desc("Enable debug output"), cl::Hidden, 36 cl::location(DebugFlag)); 37 38 struct StatRecord { 39 std::string Value; 40 const char *Name, *Desc; 41 42 StatRecord(const std::string V, const char *N, const char *D) 43 : Value(V), Name(N), Desc(D) {} 44 45 bool operator<(const StatRecord &SR) const { 46 return std::strcmp(Name, SR.Name) < 0; 47 } 48 49 void print(unsigned ValFieldSize, unsigned NameFieldSize) { 50 std::cerr << std::string(ValFieldSize-Value.length(), ' ') 51 << Value << " " << Name 52 << std::string(NameFieldSize-std::strlen(Name), ' ') 53 << " - " << Desc << "\n"; 54 } 55 }; 56 57 static std::vector<StatRecord> *AccumStats = 0; 58 59 // Print information when destroyed, iff command line option is specified 60 void StatisticBase::destroy() const { 61 if (Enabled && hasSomeData()) { 62 if (AccumStats == 0) 63 AccumStats = new std::vector<StatRecord>(); 64 65 std::ostringstream Out; 66 printValue(Out); 67 AccumStats->push_back(StatRecord(Out.str(), Name, Desc)); 68 } 69 70 if (--NumStats == 0 && AccumStats) { 71 // Figure out how long the biggest Value and Name fields are... 72 unsigned MaxNameLen = 0, MaxValLen = 0; 73 for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { 74 MaxValLen = std::max(MaxValLen, 75 (unsigned)(*AccumStats)[i].Value.length()); 76 MaxNameLen = std::max(MaxNameLen, 77 (unsigned)std::strlen((*AccumStats)[i].Name)); 78 } 79 80 // Sort the fields... 81 std::stable_sort(AccumStats->begin(), AccumStats->end()); 82 83 // Print out the statistics header... 84 std::cerr << "===" << std::string(73, '-') << "===\n" 85 << " ... Statistics Collected ...\n" 86 << "===" << std::string(73, '-') << "===\n\n"; 87 88 // Print all of the statistics accumulated... 89 for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) 90 (*AccumStats)[i].print(MaxValLen, MaxNameLen); 91 92 std::cerr << std::endl; // Flush the output stream... 93 94 // Free all accumulated statistics... 95 delete AccumStats; 96 AccumStats = 0; 97 } 98 } 99