Timer.cpp revision fc86c3cfd6e81113722f17bebc54bc0b63389b58
16c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===-- Timer.cpp - Interval Timing Support -------------------------------===//
2f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//                     The LLVM Compiler Infrastructure
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===//
96c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//
106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// Interval Timing implementation.
116c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//
126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
136c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
14551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/Timer.h"
15551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h"
16fc86c3cfd6e81113722f17bebc54bc0b63389b58Chris Lattner#include "llvm/Support/Debug.h"
1790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner#include "llvm/Support/ManagedStatic.h"
18d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner#include "llvm/Support/raw_ostream.h"
19d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner#include "llvm/Support/Format.h"
20fc86c3cfd6e81113722f17bebc54bc0b63389b58Chris Lattner#include "llvm/System/Mutex.h"
21df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer#include "llvm/System/Process.h"
22d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner#include <map>
23b6d465f8131f5fb0b8e565685fb3395ed9aecbdbChris Lattnerusing namespace llvm;
24f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
25b4db5f3e4b24bfc515bc615b2b6256083c7ef508Chris Lattner// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
26d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattnernamespace llvm { extern raw_ostream *GetLibSupportInfoOutputFile(); }
27d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
2871336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
2971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// of constructor/destructor ordering being unspecified by C++.  Basically the
30ac0b6ae358944ae8b2b5a11dc08f52c3ed89f2daChris Lattner// problem is that a Statistic object gets destroyed, which ends up calling
3171336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
3271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
33f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
34f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// this by creating the string the first time it is needed and never destroying
35f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// it.
3690aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::string> LibSupportInfoOutputFilename;
3771336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattnerstatic std::string &getLibSupportInfoOutputFilename() {
38f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer  return *LibSupportInfoOutputFilename;
3971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner}
406c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
4146d9a6494496d215e850f337b5a723c484212f80Owen Andersonstatic ManagedStatic<sys::SmartMutex<true> > TimerLock;
4246d9a6494496d215e850f337b5a723c484212f80Owen Anderson
433f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattnernamespace {
443c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman  static cl::opt<bool>
453f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
463f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner                                      "tracking (this may be slow)"),
473f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner             cl::Hidden);
48f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
493c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman  static cl::opt<std::string, true>
5096a54db5e763c19f556a1b54ad2956cc91b81cb8Chris Lattner  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
51f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner                     cl::desc("File to append -stats and -timer output to"),
5271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
533f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner}
543f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner
55200aa6d89b75d2a4f630b85a4a785ae7d18d16bbOwen Andersonstatic TimerGroup *DefaultTimerGroup = 0;
566c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() {
579bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimerGroup *tmp = DefaultTimerGroup;
583b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  sys::MemoryFence();
599bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (tmp) return tmp;
609bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
619bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  llvm_acquire_global_lock();
629bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  tmp = DefaultTimerGroup;
633b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  if (!tmp) {
649bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
659bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::MemoryFence();
669bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    DefaultTimerGroup = tmp;
673b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  }
689bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  llvm_release_global_lock();
69c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov
703b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  return tmp;
716c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
726c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
739bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
749bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner// Timer Implementation
759bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
769bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
776c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(const std::string &N)
78fc86c3cfd6e81113722f17bebc54bc0b63389b58Chris Lattner  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), Name(N),
796c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    Started(false), TG(getDefaultTimerGroup()) {
806c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG->addTimer();
816c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
826c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
836c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(const std::string &N, TimerGroup &tg)
84fc86c3cfd6e81113722f17bebc54bc0b63389b58Chris Lattner  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), Name(N),
856c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    Started(false), TG(&tg) {
866c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG->addTimer();
876c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
886c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
896c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(const Timer &T) {
906c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG = T.TG;
916c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (TG) TG->addTimer();
926c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  operator=(T);
936c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
946c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
956c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// Copy ctor, initialize with no TG member.
966c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(bool, const Timer &T) {
976c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG = T.TG;     // Avoid assertion in operator=
986c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  operator=(T);  // Copy contents
996c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG = 0;
1006c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1016c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1026c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() {
1039bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (!TG) return;
1049bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1059bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Started) {
1069bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    Started = false;
1079bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    TG->addTimerToPrint(*this);
1086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
1099bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TG->removeTimer();
1106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1116c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
112e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohenstatic inline size_t getMemUsage() {
113aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer  if (TrackSpace)
114e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohen    return sys::Process::GetMallocUsage();
115aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer  return 0;
116aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer}
117aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer
1186c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstruct TimeRecord {
1196f2c64d70aad5328a843a6f6a6547ada69ead33bOwen Anderson  double Elapsed, UserTime, SystemTime;
1206f2c64d70aad5328a843a6f6a6547ada69ead33bOwen Anderson  ssize_t MemUsed;
1216c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner};
1226c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1238f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattnerstatic TimeRecord getTimeRecord(bool Start) {
124df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  TimeRecord Result;
125b4db5f3e4b24bfc515bc615b2b6256083c7ef508Chris Lattner
126df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  sys::TimeValue now(0,0);
127df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  sys::TimeValue user(0,0);
128df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  sys::TimeValue sys(0,0);
129b4db5f3e4b24bfc515bc615b2b6256083c7ef508Chris Lattner
1306f2c64d70aad5328a843a6f6a6547ada69ead33bOwen Anderson  ssize_t MemUsed = 0;
1317d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  if (Start) {
132aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer    MemUsed = getMemUsage();
1339bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
1347d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  } else {
1359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
136fed1b27d323001682e7cb1bd66bb5d603cabb9f8Chris Lattner    MemUsed = getMemUsage();
1377d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  }
1388f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1399bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.Elapsed    =  now.seconds()  + now.microseconds() / 1000000.0;
1409bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.UserTime   = user.seconds() + user.microseconds() / 1000000.0;
1419bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.SystemTime =  sys.seconds()  + sys.microseconds() / 1000000.0;
1429bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.MemUsed = MemUsed;
1436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  return Result;
1446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
14690aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::vector<Timer*> > ActiveTimers;
1478f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1486c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() {
1496c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Started = true;
150153d28a414d087cbe20d17329fed358f7fa1258bDan Gohman  ActiveTimers->push_back(this);
1518f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  TimeRecord TR = getTimeRecord(true);
1526c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Elapsed    -= TR.Elapsed;
1536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  UserTime   -= TR.UserTime;
1546c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  SystemTime -= TR.SystemTime;
15518eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  MemUsed    -= TR.MemUsed;
1566c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1576c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1586c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() {
1598f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  TimeRecord TR = getTimeRecord(false);
1606c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Elapsed    += TR.Elapsed;
1616c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  UserTime   += TR.UserTime;
1626c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  SystemTime += TR.SystemTime;
16318eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  MemUsed    += TR.MemUsed;
1648f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
16590aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner  if (ActiveTimers->back() == this) {
16690aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->pop_back();
1678f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  } else {
1688f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    std::vector<Timer*>::iterator I =
16990aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner      std::find(ActiveTimers->begin(), ActiveTimers->end(), this);
17090aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    assert(I != ActiveTimers->end() && "stop but no startTimer?");
17190aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->erase(I);
1728f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
1736c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1746c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1756c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::sum(const Timer &T) {
1766c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Elapsed    += T.Elapsed;
1776c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  UserTime   += T.UserTime;
1786c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  SystemTime += T.SystemTime;
17918eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  MemUsed    += T.MemUsed;
1806c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1816c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1820ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattnerconst Timer &Timer::operator=(const Timer &T) {
1830ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  Elapsed = T.Elapsed;
1840ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  UserTime = T.UserTime;
1850ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  SystemTime = T.SystemTime;
1860ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  MemUsed = T.MemUsed;
1870ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  Name = T.Name;
1880ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  Started = T.Started;
1890ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  assert(TG == T.TG && "Can only assign timers in the same TimerGroup!");
1900ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  return *this;
1910ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner}
1920ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner
1930ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner
1949bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnerstatic void printVal(double Val, double Total, raw_ostream &OS) {
1950613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner  if (Total < 1e-7)   // Avoid dividing by zero.
1969bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << "        -----     ";
1979bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  else {
1989bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << "  " << format("%7.4f", Val) << " (";
1999bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << format("%5.1f", Val*100/Total) << "%)";
2009bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  }
2019bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
2029bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
2039bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnervoid Timer::print(const Timer &Total, raw_ostream &OS) {
2049bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Total.UserTime)
2059bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    printVal(UserTime, Total.UserTime, OS);
2069bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Total.SystemTime)
2079bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    printVal(SystemTime, Total.SystemTime, OS);
2089bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Total.getProcessTime())
2099bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    printVal(getProcessTime(), Total.getProcessTime(), OS);
2109bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  printVal(Elapsed, Total.Elapsed, OS);
2119bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
2129bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  OS << "  ";
2139bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
2140ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  if (Total.MemUsed)
2159bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << format("%9lld", (long long)MemUsed) << "  ";
2160ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner
2179bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  OS << Name << "\n";
2189bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
2199bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Started = false;  // Once printed, don't print again
2209bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
2219bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
2229bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
223d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
224d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//   NamedRegionTimer Implementation
225d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
226d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
2275e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohmantypedef std::map<std::string, Timer> Name2Timer;
2285e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohmantypedef std::map<std::string, std::pair<TimerGroup, Name2Timer> > Name2Pair;
2295e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
2305e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohmanstatic ManagedStatic<Name2Timer> NamedTimers;
2315e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohmanstatic ManagedStatic<Name2Pair> NamedGroupedTimers;
232d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
23390aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic Timer &getNamedRegionTimer(const std::string &Name) {
234a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2355e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  Name2Timer::iterator I = NamedTimers->find(Name);
236c418bf3dd593b5b2fe2f978930f6d0d6b17e344eDan Gohman  if (I != NamedTimers->end())
237d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner    return I->second;
238d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
23990aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner  return NamedTimers->insert(I, std::make_pair(Name, Timer(Name)))->second;
240d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner}
241d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
2425e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohmanstatic Timer &getNamedRegionTimer(const std::string &Name,
2435e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                  const std::string &GroupName) {
244a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2455e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
2465e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  Name2Pair::iterator I = NamedGroupedTimers->find(GroupName);
2475e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  if (I == NamedGroupedTimers->end()) {
2485e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman    TimerGroup TG(GroupName);
2495e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman    std::pair<TimerGroup, Name2Timer> Pair(TG, Name2Timer());
2505e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman    I = NamedGroupedTimers->insert(I, std::make_pair(GroupName, Pair));
2515e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  }
2525e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
2535e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  Name2Timer::iterator J = I->second.second.find(Name);
2545e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  if (J == I->second.second.end())
2555e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman    J = I->second.second.insert(J,
2565e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                std::make_pair(Name,
2575e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                               Timer(Name,
2585e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                                     I->second.first)));
2595e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
2605e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  return J->second;
2615e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman}
2625e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
263d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris LattnerNamedRegionTimer::NamedRegionTimer(const std::string &Name)
264d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  : TimeRegion(getNamedRegionTimer(Name)) {}
265d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
2665e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan GohmanNamedRegionTimer::NamedRegionTimer(const std::string &Name,
2675e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                   const std::string &GroupName)
2685e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  : TimeRegion(getNamedRegionTimer(Name, GroupName)) {}
2698f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
2706c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2716c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//   TimerGroup Implementation
2726c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2736c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
2740613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
2750ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattnerraw_ostream *llvm::GetLibSupportInfoOutputFile() {
27671336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
277f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  if (LibSupportInfoOutputFilename.empty())
278d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner    return &errs();
279f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  if (LibSupportInfoOutputFilename == "-")
280d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner    return &outs();
281f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
282d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner  std::string Error;
283d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner  raw_ostream *Result = new raw_fd_ostream(LibSupportInfoOutputFilename.c_str(),
284d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner                                           Error, raw_fd_ostream::F_Append);
285d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner  if (Error.empty())
286d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner    return Result;
287c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov
288d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner  errs() << "Error opening info-output-file '"
289bcd2498f4f1682dbdc41452add5b9bc72cbd6b3fBill Wendling         << LibSupportInfoOutputFilename << " for appending!\n";
290d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner  delete Result;
291d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner  return &errs();
292f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner}
293f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
2946c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
2956c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid TimerGroup::removeTimer() {
296a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2979bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (--NumTimers != 0 || TimersToPrint.empty())
2989bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    return; // Don't print timing report.
2999bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3009bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  // Sort the timers in descending order by amount of time taken.
3019bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  std::sort(TimersToPrint.begin(), TimersToPrint.end(),
3029bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner            std::greater<Timer>());
3036c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3049bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  // Figure out how many spaces to indent TimerGroup name.
3059bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  unsigned Padding = (80-Name.length())/2;
3069bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
307f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
3089bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  raw_ostream *OutStream = GetLibSupportInfoOutputFile();
3099bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3109bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  ++NumTimers;
3110613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner  {  // Scope to contain Total timer: don't allow total timer to drop us to
3120613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner     // zero timers.
3139bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    Timer Total("TOTAL");
3149bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3159bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
3169bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      Total.sum(TimersToPrint[i]);
3179bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3180613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner    // Print out timing header.
3199bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    *OutStream << "===" << std::string(73, '-') << "===\n"
3209bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner               << std::string(Padding, ' ') << Name << "\n"
3219bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner               << "===" << std::string(73, '-')
3229bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner               << "===\n";
3239bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3249bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    // If this is not an collection of ungrouped times, print the total time.
3259bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    // Ungrouped timers don't really make sense to add up.  We still print the
3269bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    // TOTAL line to make the percentages make sense.
3279bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    if (this != DefaultTimerGroup) {
3289bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << "  Total Execution Time: ";
3299bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3309bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << format("%5.4f", Total.getProcessTime()) << " seconds (";
3319bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << format("%5.4f", Total.getWallTime()) << " wall clock)\n";
3329bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    }
3339bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    *OutStream << "\n";
3349bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    if (Total.UserTime)
3369bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << "   ---User Time---";
3379bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    if (Total.SystemTime)
3389bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << "   --System Time--";
3399bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    if (Total.getProcessTime())
3409bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << "   --User+System--";
3419bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    *OutStream << "   ---Wall Time---";
3429bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    if (Total.getMemUsed())
3439bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      *OutStream << "  ---Mem---";
3449bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    *OutStream << "  --- Name ---\n";
3459bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3460613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner    // Loop through all of the timing data, printing it out.
3479bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
3489bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner      TimersToPrint[i].print(Total, *OutStream);
3499bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3509bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    Total.print(Total, *OutStream);
3519bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    *OutStream << '\n';
3529bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OutStream->flush();
3536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
3549bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  --NumTimers;
3559bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3569bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimersToPrint.clear();
3579bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
3580ea86bc411748f10b913f42ef3a71b46ace7ceb2Chris Lattner  if (OutStream != &errs() && OutStream != &outs())
3590613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner    delete OutStream;   // Close the file.
3606c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
361d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
36246d9a6494496d215e850f337b5a723c484212f80Owen Andersonvoid TimerGroup::addTimer() {
363a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
36446d9a6494496d215e850f337b5a723c484212f80Owen Anderson  ++NumTimers;
36546d9a6494496d215e850f337b5a723c484212f80Owen Anderson}
36646d9a6494496d215e850f337b5a723c484212f80Owen Anderson
36746d9a6494496d215e850f337b5a723c484212f80Owen Andersonvoid TimerGroup::addTimerToPrint(const Timer &T) {
368a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
36946d9a6494496d215e850f337b5a723c484212f80Owen Anderson  TimersToPrint.push_back(Timer(true, T));
37046d9a6494496d215e850f337b5a723c484212f80Owen Anderson}
37146d9a6494496d215e850f337b5a723c484212f80Owen Anderson
372