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 // GetLibSupportInfoOutputFile - Return a file stream to print our output on... 24 std::ostream *GetLibSupportInfoOutputFile(); 25 26 bool DebugFlag; // DebugFlag - Exported boolean set by the -debug option 27 28 unsigned StatisticBase::NumStats = 0; 29 30 // -stats - Command line option to cause transformations to emit stats about 31 // what they did. 32 // 33 static cl::opt<bool> 34 Enabled("stats", cl::desc("Enable statistics output from program")); 35 36 #ifndef NDEBUG 37 // -debug - Command line option to enable the DEBUG statements in the passes. 38 // This flag may only be enabled in debug builds. 39 static cl::opt<bool, true> 40 Debug("debug", cl::desc("Enable debug output"), cl::Hidden, 41 cl::location(DebugFlag)); 42 #endif 43 44 struct StatRecord { 45 std::string Value; 46 const char *Name, *Desc; 47 48 StatRecord(const std::string V, const char *N, const char *D) 49 : Value(V), Name(N), Desc(D) {} 50 51 bool operator<(const StatRecord &SR) const { 52 return std::strcmp(Name, SR.Name) < 0; 53 } 54 55 void print(unsigned ValFieldSize, unsigned NameFieldSize, 56 std::ostream &OS) { 57 OS << std::string(ValFieldSize-Value.length(), ' ') 58 << Value << " " << Name 59 << std::string(NameFieldSize-std::strlen(Name), ' ') 60 << " - " << Desc << "\n"; 61 } 62 }; 63 64 static std::vector<StatRecord> *AccumStats = 0; 65 66 // Print information when destroyed, iff command line option is specified 67 void StatisticBase::destroy() const { 68 if (Enabled && hasSomeData()) { 69 if (AccumStats == 0) 70 AccumStats = new std::vector<StatRecord>(); 71 72 std::ostringstream Out; 73 printValue(Out); 74 AccumStats->push_back(StatRecord(Out.str(), Name, Desc)); 75 } 76 77 if (--NumStats == 0 && AccumStats) { 78 std::ostream *OutStream = GetLibSupportInfoOutputFile(); 79 80 // Figure out how long the biggest Value and Name fields are... 81 unsigned MaxNameLen = 0, MaxValLen = 0; 82 for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) { 83 MaxValLen = std::max(MaxValLen, 84 (unsigned)(*AccumStats)[i].Value.length()); 85 MaxNameLen = std::max(MaxNameLen, 86 (unsigned)std::strlen((*AccumStats)[i].Name)); 87 } 88 89 // Sort the fields... 90 std::stable_sort(AccumStats->begin(), AccumStats->end()); 91 92 // Print out the statistics header... 93 *OutStream << "===" << std::string(73, '-') << "===\n" 94 << " ... Statistics Collected ...\n" 95 << "===" << std::string(73, '-') << "===\n\n"; 96 97 // Print all of the statistics accumulated... 98 for (unsigned i = 0, e = AccumStats->size(); i != e; ++i) 99 (*AccumStats)[i].print(MaxValLen, MaxNameLen, *OutStream); 100 101 *OutStream << std::endl; // Flush the output stream... 102 103 // Free all accumulated statistics... 104 delete AccumStats; 105 AccumStats = 0; 106 if (OutStream != &std::cerr && OutStream != &std::cout) 107 delete OutStream; // Close the file... 108 } 109 } 110