Statistic.cpp revision 249423
1218885Sdim//===-- Statistic.cpp - Easy way to expose stats information --------------===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file implements the 'Statistic' class, which is designed to be an easy 11218885Sdim// way to expose various success metrics from passes. These statistics are 12218885Sdim// printed at the end of a run, when the -stats command line option is enabled 13224145Sdim// on the command line. 14224145Sdim// 15224145Sdim// This is useful for reporting information like the number of instructions 16224145Sdim// simplified, optimized or removed by various transformations, like this: 17218885Sdim// 18218885Sdim// static Statistic NumInstEliminated("GCSE", "Number of instructions killed"); 19263508Sdim// 20224145Sdim// Later, in the code: ++NumInstEliminated; 21218885Sdim// 22218885Sdim//===----------------------------------------------------------------------===// 23218885Sdim 24224145Sdim#include "llvm/ADT/Statistic.h" 25224145Sdim#include "llvm/ADT/StringExtras.h" 26224145Sdim#include "llvm/Support/CommandLine.h" 27218885Sdim#include "llvm/Support/Debug.h" 28218885Sdim#include "llvm/Support/Format.h" 29218885Sdim#include "llvm/Support/ManagedStatic.h" 30218885Sdim#include "llvm/Support/Mutex.h" 31218885Sdim#include "llvm/Support/raw_ostream.h" 32218885Sdim#include <algorithm> 33218885Sdim#include <cstring> 34218885Sdimusing namespace llvm; 35218885Sdim 36218885Sdim// CreateInfoOutputFile - Return a file stream to print our output on. 37218885Sdimnamespace llvm { extern raw_ostream *CreateInfoOutputFile(); } 38218885Sdim 39218885Sdim/// -stats - Command line option to cause transformations to emit stats about 40218885Sdim/// what they did. 41218885Sdim/// 42218885Sdimstatic cl::opt<bool> 43218885SdimEnabled( 44218885Sdim "stats", 45218885Sdim cl::desc("Enable statistics output from program (available with Asserts)")); 46218885Sdim 47218885Sdim 48249423Sdimnamespace { 49249423Sdim/// StatisticInfo - This class is used in a ManagedStatic so that it is created 50249423Sdim/// on demand (when the first statistic is bumped) and destroyed only when 51249423Sdim/// llvm_shutdown is called. We print statistics from the destructor. 52249423Sdimclass StatisticInfo { 53249423Sdim std::vector<const Statistic*> Stats; 54249423Sdim friend void llvm::PrintStatistics(); 55218885Sdim friend void llvm::PrintStatistics(raw_ostream &OS); 56218885Sdimpublic: 57218885Sdim ~StatisticInfo(); 58218885Sdim 59218885Sdim void addStatistic(const Statistic *S) { 60218885Sdim Stats.push_back(S); 61218885Sdim } 62218885Sdim}; 63218885Sdim} 64218885Sdim 65218885Sdimstatic ManagedStatic<StatisticInfo> StatInfo; 66218885Sdimstatic ManagedStatic<sys::SmartMutex<true> > StatLock; 67224145Sdim 68224145Sdim/// RegisterStatistic - The first time a statistic is bumped, this method is 69224145Sdim/// called. 70224145Sdimvoid Statistic::RegisterStatistic() { 71224145Sdim // If stats are enabled, inform StatInfo that this statistic should be 72224145Sdim // printed. 73224145Sdim sys::SmartScopedLock<true> Writer(*StatLock); 74224145Sdim if (!Initialized) { 75224145Sdim if (Enabled) 76224145Sdim StatInfo->addStatistic(this); 77224145Sdim 78224145Sdim TsanHappensBefore(this); 79224145Sdim sys::MemoryFence(); 80218885Sdim // Remember we have been registered. 81218885Sdim TsanIgnoreWritesBegin(); 82224145Sdim Initialized = true; 83224145Sdim TsanIgnoreWritesEnd(); 84224145Sdim } 85224145Sdim} 86224145Sdim 87224145Sdimnamespace { 88224145Sdim 89224145Sdimstruct NameCompare { 90224145Sdim bool operator()(const Statistic *LHS, const Statistic *RHS) const { 91224145Sdim int Cmp = std::strcmp(LHS->getName(), RHS->getName()); 92224145Sdim if (Cmp != 0) return Cmp < 0; 93224145Sdim 94224145Sdim // Secondary key is the description. 95224145Sdim return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0; 96224145Sdim } 97224145Sdim}; 98224145Sdim 99224145Sdim} 100224145Sdim 101263508Sdim// Print information when destroyed, iff command line option is specified. 102224145SdimStatisticInfo::~StatisticInfo() { 103224145Sdim llvm::PrintStatistics(); 104224145Sdim} 105224145Sdim 106224145Sdimvoid llvm::EnableStatistics() { 107224145Sdim Enabled.setValue(true); 108224145Sdim} 109224145Sdim 110224145Sdimbool llvm::AreStatisticsEnabled() { 111224145Sdim return Enabled; 112224145Sdim} 113224145Sdim 114224145Sdimvoid llvm::PrintStatistics(raw_ostream &OS) { 115224145Sdim StatisticInfo &Stats = *StatInfo; 116224145Sdim 117224145Sdim // Figure out how long the biggest Value and Name fields are. 118224145Sdim unsigned MaxNameLen = 0, MaxValLen = 0; 119224145Sdim for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) { 120224145Sdim MaxValLen = std::max(MaxValLen, 121249423Sdim (unsigned)utostr(Stats.Stats[i]->getValue()).size()); 122249423Sdim MaxNameLen = std::max(MaxNameLen, 123249423Sdim (unsigned)std::strlen(Stats.Stats[i]->getName())); 124249423Sdim } 125249423Sdim 126249423Sdim // Sort the fields by name. 127249423Sdim std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare()); 128224145Sdim 129224145Sdim // Print out the statistics header... 130224145Sdim OS << "===" << std::string(73, '-') << "===\n" 131224145Sdim << " ... Statistics Collected ...\n" 132224145Sdim << "===" << std::string(73, '-') << "===\n\n"; 133224145Sdim 134224145Sdim // Print all of the statistics. 135224145Sdim for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) 136224145Sdim OS << format("%*u %-*s - %s\n", 137224145Sdim MaxValLen, Stats.Stats[i]->getValue(), 138224145Sdim MaxNameLen, Stats.Stats[i]->getName(), 139224145Sdim Stats.Stats[i]->getDesc()); 140224145Sdim 141224145Sdim OS << '\n'; // Flush the output stream. 142224145Sdim OS.flush(); 143224145Sdim 144224145Sdim} 145224145Sdim 146224145Sdimvoid llvm::PrintStatistics() { 147224145Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 148224145Sdim StatisticInfo &Stats = *StatInfo; 149224145Sdim 150224145Sdim // Statistics not enabled? 151224145Sdim if (Stats.Stats.empty()) return; 152224145Sdim 153224145Sdim // Get the stream to write to. 154224145Sdim raw_ostream &OutStream = *CreateInfoOutputFile(); 155224145Sdim PrintStatistics(OutStream); 156224145Sdim delete &OutStream; // Close the file. 157224145Sdim#else 158263508Sdim // Check if the -stats option is set instead of checking 159263508Sdim // !Stats.Stats.empty(). In release builds, Statistics operators 160224145Sdim // do nothing, so stats are never Registered. 161224145Sdim if (Enabled) { 162224145Sdim // Get the stream to write to. 163224145Sdim raw_ostream &OutStream = *CreateInfoOutputFile(); 164224145Sdim OutStream << "Statistics are disabled. " 165224145Sdim << "Build with asserts or with -DLLVM_ENABLE_STATS\n"; 166224145Sdim OutStream.flush(); 167224145Sdim delete &OutStream; // Close the file. 168224145Sdim } 169243830Sdim#endif 170243830Sdim} 171224145Sdim