Statistic.cpp revision 208954
119370Spst//===-- Statistic.cpp - Easy way to expose stats information --------------===// 219370Spst// 319370Spst// The LLVM Compiler Infrastructure 4130803Smarcel// 5130803Smarcel// This file is distributed under the University of Illinois Open Source 6130803Smarcel// License. See LICENSE.TXT for details. 798944Sobrien// 819370Spst//===----------------------------------------------------------------------===// 998944Sobrien// 1098944Sobrien// This file implements the 'Statistic' class, which is designed to be an easy 1198944Sobrien// way to expose various success metrics from passes. These statistics are 1298944Sobrien// printed at the end of a run, when the -stats command line option is enabled 1319370Spst// on the command line. 1498944Sobrien// 1598944Sobrien// This is useful for reporting information like the number of instructions 1698944Sobrien// simplified, optimized or removed by various transformations, like this: 1798944Sobrien// 1819370Spst// static Statistic NumInstEliminated("GCSE", "Number of instructions killed"); 1998944Sobrien// 2098944Sobrien// Later, in the code: ++NumInstEliminated; 2198944Sobrien// 2298944Sobrien//===----------------------------------------------------------------------===// 2319370Spst 2419370Spst#include "llvm/ADT/Statistic.h" 2519370Spst#include "llvm/Support/CommandLine.h" 2619370Spst#include "llvm/Support/Debug.h" 27130803Smarcel#include "llvm/Support/ManagedStatic.h" 28130803Smarcel#include "llvm/Support/raw_ostream.h" 29130803Smarcel#include "llvm/System/Mutex.h" 30130803Smarcel#include "llvm/ADT/StringExtras.h" 31130803Smarcel#include <algorithm> 32130803Smarcel#include <cstring> 33130803Smarcelusing namespace llvm; 3419370Spst 3519370Spst// CreateInfoOutputFile - Return a file stream to print our output on. 3619370Spstnamespace llvm { extern raw_ostream *CreateInfoOutputFile(); } 3719370Spst 3819370Spst/// -stats - Command line option to cause transformations to emit stats about 3919370Spst/// what they did. 40130803Smarcel/// 41130803Smarcelstatic cl::opt<bool> 42130803SmarcelEnabled("stats", cl::desc("Enable statistics output from program")); 4398944Sobrien 4419370Spst 4519370Spstnamespace { 4698944Sobrien/// StatisticInfo - This class is used in a ManagedStatic so that it is created 4719370Spst/// on demand (when the first statistic is bumped) and destroyed only when 4819370Spst/// llvm_shutdown is called. We print statistics from the destructor. 4919370Spstclass StatisticInfo { 5019370Spst std::vector<const Statistic*> Stats; 5198944Sobrien friend void llvm::PrintStatistics(); 5219370Spst friend void llvm::PrintStatistics(raw_ostream &OS); 5398944Sobrienpublic: 5419370Spst ~StatisticInfo(); 5598944Sobrien 5619370Spst void addStatistic(const Statistic *S) { 5798944Sobrien Stats.push_back(S); 5819370Spst } 5998944Sobrien}; 6019370Spst} 6198944Sobrien 6298944Sobrienstatic ManagedStatic<StatisticInfo> StatInfo; 6398944Sobrienstatic ManagedStatic<sys::SmartMutex<true> > StatLock; 6419370Spst 6598944Sobrien/// RegisterStatistic - The first time a statistic is bumped, this method is 6698944Sobrien/// called. 6798944Sobrienvoid Statistic::RegisterStatistic() { 6819370Spst // If stats are enabled, inform StatInfo that this statistic should be 6998944Sobrien // printed. 7098944Sobrien sys::SmartScopedLock<true> Writer(*StatLock); 7119370Spst if (!Initialized) { 7298944Sobrien if (Enabled) 7398944Sobrien StatInfo->addStatistic(this); 7498944Sobrien 7598944Sobrien sys::MemoryFence(); 7619370Spst // Remember we have been registered. 7798944Sobrien Initialized = true; 7898944Sobrien } 7919370Spst} 8098944Sobrien 8198944Sobriennamespace { 8219370Spst 8398944Sobrienstruct NameCompare { 8498944Sobrien bool operator()(const Statistic *LHS, const Statistic *RHS) const { 8598944Sobrien int Cmp = std::strcmp(LHS->getName(), RHS->getName()); 8698944Sobrien if (Cmp != 0) return Cmp < 0; 8798944Sobrien 8898944Sobrien // Secondary key is the description. 8998944Sobrien return std::strcmp(LHS->getDesc(), RHS->getDesc()) < 0; 9098944Sobrien } 9198944Sobrien}; 9298944Sobrien 9398944Sobrien} 9498944Sobrien 9598944Sobrien// Print information when destroyed, iff command line option is specified. 9698944SobrienStatisticInfo::~StatisticInfo() { 9798944Sobrien llvm::PrintStatistics(); 9898944Sobrien} 9998944Sobrien 10098944Sobrienvoid llvm::EnableStatistics() { 10198944Sobrien Enabled.setValue(true); 10298944Sobrien} 10398944Sobrien 10498944Sobrienvoid llvm::PrintStatistics(raw_ostream &OS) { 10519370Spst StatisticInfo &Stats = *StatInfo; 10619370Spst 10719370Spst // Figure out how long the biggest Value and Name fields are. 10819370Spst unsigned MaxNameLen = 0, MaxValLen = 0; 10998944Sobrien for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) { 11098944Sobrien MaxValLen = std::max(MaxValLen, 11119370Spst (unsigned)utostr(Stats.Stats[i]->getValue()).size()); 11298944Sobrien MaxNameLen = std::max(MaxNameLen, 11319370Spst (unsigned)std::strlen(Stats.Stats[i]->getName())); 11498944Sobrien } 11598944Sobrien 11698944Sobrien // Sort the fields by name. 11798944Sobrien std::stable_sort(Stats.Stats.begin(), Stats.Stats.end(), NameCompare()); 11898944Sobrien 11946283Sdfr // Print out the statistics header... 12098944Sobrien OS << "===" << std::string(73, '-') << "===\n" 12198944Sobrien << " ... Statistics Collected ...\n" 12298944Sobrien << "===" << std::string(73, '-') << "===\n\n"; 12398944Sobrien 12498944Sobrien // Print all of the statistics. 12598944Sobrien for (size_t i = 0, e = Stats.Stats.size(); i != e; ++i) { 12698944Sobrien std::string CountStr = utostr(Stats.Stats[i]->getValue()); 12746283Sdfr OS << std::string(MaxValLen-CountStr.size(), ' ') 12846283Sdfr << CountStr << " " << Stats.Stats[i]->getName() 12946283Sdfr << std::string(MaxNameLen-std::strlen(Stats.Stats[i]->getName()), ' ') 13046283Sdfr << " - " << Stats.Stats[i]->getDesc() << "\n"; 13146283Sdfr } 13298944Sobrien 13346283Sdfr OS << '\n'; // Flush the output stream. 13446283Sdfr OS.flush(); 13546283Sdfr 13646283Sdfr} 13746283Sdfr 13846283Sdfrvoid llvm::PrintStatistics() { 13946283Sdfr StatisticInfo &Stats = *StatInfo; 14046283Sdfr 14146283Sdfr // Statistics not enabled? 14246283Sdfr if (Stats.Stats.empty()) return; 14398944Sobrien 14446283Sdfr // Get the stream to write to. 14546283Sdfr raw_ostream &OutStream = *CreateInfoOutputFile(); 14619370Spst PrintStatistics(OutStream); 14719370Spst delete &OutStream; // Close the file. 14819370Spst} 14919370Spst