Statistic.cpp revision 195098
1232922Stheraven//===-- Statistic.cpp - Easy way to expose stats information --------------===// 2232922Stheraven// 3232922Stheraven// The LLVM Compiler Infrastructure 4232922Stheraven// 5232922Stheraven// This file is distributed under the University of Illinois Open Source 6232922Stheraven// License. See LICENSE.TXT for details. 7232922Stheraven// 8232922Stheraven//===----------------------------------------------------------------------===// 9232922Stheraven// 10232922Stheraven// This file implements the 'Statistic' class, which is designed to be an easy 11232922Stheraven// way to expose various success metrics from passes. These statistics are 12232922Stheraven// printed at the end of a run, when the -stats command line option is enabled 13232922Stheraven// on the command line. 14232922Stheraven// 15232922Stheraven// This is useful for reporting information like the number of instructions 16232922Stheraven// simplified, optimized or removed by various transformations, like this: 17232922Stheraven// 18232922Stheraven// static Statistic NumInstEliminated("GCSE", "Number of instructions killed"); 19232922Stheraven// 20232922Stheraven// Later, in the code: ++NumInstEliminated; 21232922Stheraven// 22232922Stheraven//===----------------------------------------------------------------------===// 23232922Stheraven 24232922Stheraven#include "llvm/ADT/Statistic.h" 25232922Stheraven#include "llvm/Support/CommandLine.h" 26232922Stheraven#include "llvm/Support/ManagedStatic.h" 27227825Stheraven#include "llvm/Support/Streams.h" 28227825Stheraven#include "llvm/System/Mutex.h" 29227825Stheraven#include "llvm/ADT/StringExtras.h" 30227825Stheraven#include <algorithm> 31227825Stheraven#include <ostream> 32227825Stheraven#include <cstring> 33227825Stheravenusing namespace llvm; 34227825Stheraven 35227825Stheraven// GetLibSupportInfoOutputFile - Return a file stream to print our output on. 36227825Stheravennamespace llvm { extern std::ostream *GetLibSupportInfoOutputFile(); } 37227825Stheraven 38227825Stheraven/// -stats - Command line option to cause transformations to emit stats about 39227825Stheraven/// what they did. 40227825Stheraven/// 41227825Stheravenstatic cl::opt<bool> 42227825StheravenEnabled("stats", cl::desc("Enable statistics output from program")); 43227825Stheraven 44227825Stheraven 45227825Stheravennamespace { 46227825Stheraven/// StatisticInfo - This class is used in a ManagedStatic so that it is created 47227825Stheraven/// on demand (when the first statistic is bumped) and destroyed only when 48227825Stheraven/// llvm_shutdown is called. We print statistics from the destructor. 49227825Stheravenclass StatisticInfo { 50227825Stheraven std::vector<const Statistic*> Stats; 51227825Stheravenpublic: 52227825Stheraven ~StatisticInfo(); 53227825Stheraven 54227825Stheraven void addStatistic(const Statistic *S) { 55227825Stheraven Stats.push_back(S); 56227825Stheraven } 57227825Stheraven}; 58227825Stheraven} 59227825Stheraven 60227825Stheravenstatic ManagedStatic<StatisticInfo> StatInfo; 61227825Stheravenstatic ManagedStatic<sys::Mutex> StatLock; 62227825Stheraven 63227825Stheraven/// RegisterStatistic - The first time a statistic is bumped, this method is 64227825Stheraven/// called. 65227825Stheravenvoid Statistic::RegisterStatistic() { 66227825Stheraven // If stats are enabled, inform StatInfo that this statistic should be 67227825Stheraven // printed. 68227825Stheraven sys::ScopedLock Writer(&*StatLock); 69227825Stheraven if (!Initialized) { 70227825Stheraven if (Enabled) 71227825Stheraven StatInfo->addStatistic(this); 72227825Stheraven 73227825Stheraven sys::MemoryFence(); 74227825Stheraven // Remember we have been registered. 75227825Stheraven Initialized = true; 76227825Stheraven } 77227825Stheraven} 78227825Stheraven 79227825Stheravennamespace { 80227825Stheraven 81227825Stheravenstruct NameCompare { 82227825Stheraven bool operator()(const Statistic *LHS, const Statistic *RHS) const { 83227825Stheraven int Cmp = std::strcmp(LHS->getName(), RHS->getName()); 84276375Sdim if (Cmp != 0) return Cmp < 0; 85276375Sdim 86276375Sdim // Secondary key is the description. 87276375Sdim return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0; 88276375Sdim } 89276375Sdim}; 90276375Sdim 91276375Sdim} 92276375Sdim 93227825Stheraven// Print information when destroyed, iff command line option is specified. 94227825StheravenStatisticInfo::~StatisticInfo() { 95227825Stheraven // Statistics not enabled? 96227825Stheraven if (Stats.empty()) return; 97 98 // Get the stream to write to. 99 std::ostream &OutStream = *GetLibSupportInfoOutputFile(); 100 101 // Figure out how long the biggest Value and Name fields are. 102 unsigned MaxNameLen = 0, MaxValLen = 0; 103 for (size_t i = 0, e = Stats.size(); i != e; ++i) { 104 MaxValLen = std::max(MaxValLen, 105 (unsigned)utostr(Stats[i]->getValue()).size()); 106 MaxNameLen = std::max(MaxNameLen, 107 (unsigned)std::strlen(Stats[i]->getName())); 108 } 109 110 // Sort the fields by name. 111 std::stable_sort(Stats.begin(), Stats.end(), NameCompare()); 112 113 // Print out the statistics header... 114 OutStream << "===" << std::string(73, '-') << "===\n" 115 << " ... Statistics Collected ...\n" 116 << "===" << std::string(73, '-') << "===\n\n"; 117 118 // Print all of the statistics. 119 for (size_t i = 0, e = Stats.size(); i != e; ++i) { 120 std::string CountStr = utostr(Stats[i]->getValue()); 121 OutStream << std::string(MaxValLen-CountStr.size(), ' ') 122 << CountStr << " " << Stats[i]->getName() 123 << std::string(MaxNameLen-std::strlen(Stats[i]->getName()), ' ') 124 << " - " << Stats[i]->getDesc() << "\n"; 125 126 } 127 128 OutStream << std::endl; // Flush the output stream... 129 130 if (&OutStream != cerr.stream() && &OutStream != cout.stream()) 131 delete &OutStream; // Close the file. 132} 133