1193323Sed//===-- Statistic.cpp - Easy way to expose stats information --------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the 'Statistic' class, which is designed to be an easy 11193323Sed// way to expose various success metrics from passes. These statistics are 12193323Sed// printed at the end of a run, when the -stats command line option is enabled 13193323Sed// on the command line. 14193323Sed// 15193323Sed// This is useful for reporting information like the number of instructions 16193323Sed// simplified, optimized or removed by various transformations, like this: 17193323Sed// 18193323Sed// static Statistic NumInstEliminated("GCSE", "Number of instructions killed"); 19193323Sed// 20193323Sed// Later, in the code: ++NumInstEliminated; 21193323Sed// 22193323Sed//===----------------------------------------------------------------------===// 23193323Sed 24193323Sed#include "llvm/ADT/Statistic.h" 25249423Sdim#include "llvm/ADT/StringExtras.h" 26193323Sed#include "llvm/Support/CommandLine.h" 27202375Srdivacky#include "llvm/Support/Debug.h" 28234353Sdim#include "llvm/Support/Format.h" 29193323Sed#include "llvm/Support/ManagedStatic.h" 30249423Sdim#include "llvm/Support/Mutex.h" 31198090Srdivacky#include "llvm/Support/raw_ostream.h" 32193323Sed#include <algorithm> 33193323Sed#include <cstring> 34193323Sedusing namespace llvm; 35193323Sed 36206083Srdivacky// CreateInfoOutputFile - Return a file stream to print our output on. 37206083Srdivackynamespace llvm { extern raw_ostream *CreateInfoOutputFile(); } 38193323Sed 39193323Sed/// -stats - Command line option to cause transformations to emit stats about 40193323Sed/// what they did. 41193323Sed/// 42193323Sedstatic cl::opt<bool> 43249423SdimEnabled( 44249423Sdim "stats", 45249423Sdim cl::desc("Enable statistics output from program (available with Asserts)")); 46193323Sed 47193323Sed 48193323Sednamespace { 49193323Sed/// StatisticInfo - This class is used in a ManagedStatic so that it is created 50212904Sdim/// on demand (when the first statistic is bumped) and destroyed only when 51193323Sed/// llvm_shutdown is called. We print statistics from the destructor. 52193323Sedclass StatisticInfo { 53193323Sed std::vector<const Statistic*> Stats; 54206083Srdivacky friend void llvm::PrintStatistics(); 55206083Srdivacky friend void llvm::PrintStatistics(raw_ostream &OS); 56193323Sedpublic: 57193323Sed ~StatisticInfo(); 58212904Sdim 59193323Sed void addStatistic(const Statistic *S) { 60193323Sed Stats.push_back(S); 61193323Sed } 62193323Sed}; 63193323Sed} 64193323Sed 65193323Sedstatic ManagedStatic<StatisticInfo> StatInfo; 66198090Srdivackystatic ManagedStatic<sys::SmartMutex<true> > StatLock; 67193323Sed 68193323Sed/// RegisterStatistic - The first time a statistic is bumped, this method is 69193323Sed/// called. 70193323Sedvoid Statistic::RegisterStatistic() { 71193323Sed // If stats are enabled, inform StatInfo that this statistic should be 72193323Sed // printed. 73198090Srdivacky sys::SmartScopedLock<true> Writer(*StatLock); 74195098Sed if (!Initialized) { 75195098Sed if (Enabled) 76195098Sed StatInfo->addStatistic(this); 77212904Sdim 78234353Sdim TsanHappensBefore(this); 79195098Sed sys::MemoryFence(); 80195098Sed // Remember we have been registered. 81234353Sdim TsanIgnoreWritesBegin(); 82195098Sed Initialized = true; 83234353Sdim TsanIgnoreWritesEnd(); 84195098Sed } 85193323Sed} 86193323Sed 87193323Sednamespace { 88193323Sed 89193323Sedstruct NameCompare { 90193323Sed bool operator()(const Statistic *LHS, const Statistic *RHS) const { 91193323Sed int Cmp = std::strcmp(LHS->getName(), RHS->getName()); 92193323Sed if (Cmp != 0) return Cmp < 0; 93212904Sdim 94193323Sed // Secondary key is the description. 95193323Sed return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0; 96193323Sed } 97193323Sed}; 98193323Sed 99193323Sed} 100193323Sed 101193323Sed// Print information when destroyed, iff command line option is specified. 102193323SedStatisticInfo::~StatisticInfo() { 103206083Srdivacky llvm::PrintStatistics(); 104206083Srdivacky} 105193323Sed 106206083Srdivackyvoid llvm::EnableStatistics() { 107206083Srdivacky Enabled.setValue(true); 108206083Srdivacky} 109193323Sed 110221345Sdimbool llvm::AreStatisticsEnabled() { 111221345Sdim return Enabled; 112221345Sdim} 113221345Sdim 114206083Srdivackyvoid llvm::PrintStatistics(raw_ostream &OS) { 115206083Srdivacky StatisticInfo &Stats = *StatInfo; 116206083Srdivacky 117193323Sed // Figure out how long the biggest Value and Name fields are. 118193323Sed unsigned MaxNameLen = 0, MaxValLen = 0; 119206083Srdivacky for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) { 120193323Sed MaxValLen = std::max(MaxValLen, 121206083Srdivacky (unsigned)utostr(Stats.Stats[i]->getValue()).size()); 122193323Sed MaxNameLen = std::max(MaxNameLen, 123206083Srdivacky (unsigned)std::strlen(Stats.Stats[i]->getName())); 124193323Sed } 125212904Sdim 126193323Sed // Sort the fields by name. 127206083Srdivacky std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare()); 128193323Sed 129193323Sed // Print out the statistics header... 130206083Srdivacky OS << "===" << std::string(73, '-') << "===\n" 131206083Srdivacky << " ... Statistics Collected ...\n" 132206083Srdivacky << "===" << std::string(73, '-') << "===\n\n"; 133212904Sdim 134193323Sed // Print all of the statistics. 135234353Sdim for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) 136234353Sdim OS << format("%*u %-*s - %s\n", 137234353Sdim MaxValLen, Stats.Stats[i]->getValue(), 138234353Sdim MaxNameLen, Stats.Stats[i]->getName(), 139234353Sdim Stats.Stats[i]->getDesc()); 140212904Sdim 141206083Srdivacky OS << '\n'; // Flush the output stream. 142206083Srdivacky OS.flush(); 143206083Srdivacky 144193323Sed} 145206083Srdivacky 146206083Srdivackyvoid llvm::PrintStatistics() { 147249423Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) 148206083Srdivacky StatisticInfo &Stats = *StatInfo; 149206083Srdivacky 150206083Srdivacky // Statistics not enabled? 151206083Srdivacky if (Stats.Stats.empty()) return; 152206083Srdivacky 153206083Srdivacky // Get the stream to write to. 154206083Srdivacky raw_ostream &OutStream = *CreateInfoOutputFile(); 155206083Srdivacky PrintStatistics(OutStream); 156206083Srdivacky delete &OutStream; // Close the file. 157249423Sdim#else 158249423Sdim // Check if the -stats option is set instead of checking 159249423Sdim // !Stats.Stats.empty(). In release builds, Statistics operators 160249423Sdim // do nothing, so stats are never Registered. 161249423Sdim if (Enabled) { 162249423Sdim // Get the stream to write to. 163249423Sdim raw_ostream &OutStream = *CreateInfoOutputFile(); 164249423Sdim OutStream << "Statistics are disabled. " 165249423Sdim << "Build with asserts or with -DLLVM_ENABLE_STATS\n"; 166249423Sdim OutStream.flush(); 167249423Sdim delete &OutStream; // Close the file. 168249423Sdim } 169249423Sdim#endif 170206083Srdivacky} 171