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