Timer.cpp revision 9f9f6d19dd67926446fb89a7b2dc0bda6353645b
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"
22a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner#include "llvm/ADT/StringMap.h"
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
55f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner// GetLibSupportInfoOutputFile - Return a file stream to print our output on.
56f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattnerraw_ostream *llvm::GetLibSupportInfoOutputFile() {
57f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
58f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  if (LibSupportInfoOutputFilename.empty())
59f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner    return &errs();
60f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  if (LibSupportInfoOutputFilename == "-")
61f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner    return &outs();
62f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
63f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  std::string Error;
64f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  raw_ostream *Result = new raw_fd_ostream(LibSupportInfoOutputFilename.c_str(),
65f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner                                           Error, raw_fd_ostream::F_Append);
66f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  if (Error.empty())
67f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner    return Result;
68f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
69f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  errs() << "Error opening info-output-file '"
70f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner    << LibSupportInfoOutputFilename << " for appending!\n";
71f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  delete Result;
72f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  return &errs();
73f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner}
74f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
75f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
76200aa6d89b75d2a4f630b85a4a785ae7d18d16bbOwen Andersonstatic TimerGroup *DefaultTimerGroup = 0;
776c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() {
789bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimerGroup *tmp = DefaultTimerGroup;
793b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  sys::MemoryFence();
809bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (tmp) return tmp;
819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
829bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  llvm_acquire_global_lock();
839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  tmp = DefaultTimerGroup;
843b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  if (!tmp) {
859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
869bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::MemoryFence();
879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    DefaultTimerGroup = tmp;
883b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  }
899bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  llvm_release_global_lock();
90c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov
913b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  return tmp;
926c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
936c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
949bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
959bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner// Timer Implementation
969bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
979bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
98a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid Timer::init(const std::string &N) {
99a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  assert(TG == 0 && "Timer already initialized");
100a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Name = N;
101a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Started = false;
102a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TG = getDefaultTimerGroup();
103b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->addTimer(*this);
1046c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1056c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
106a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid Timer::init(const std::string &N, TimerGroup &tg) {
107a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  assert(TG == 0 && "Timer already initialized");
108a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Name = N;
109a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Started = false;
110a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TG = &tg;
111b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->addTimer(*this);
1126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1136c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1146c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() {
115a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (!TG) return;  // Never initialized.
116b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->removeTimer(*this);
1176c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1186c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
119e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohenstatic inline size_t getMemUsage() {
120aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer  if (TrackSpace)
121e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohen    return sys::Process::GetMallocUsage();
122aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer  return 0;
123aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer}
124aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer
125a782e75d487006cafffdc256b3c623307fee4dcfChris LattnerTimeRecord TimeRecord::getCurrentTime(bool Start) {
126df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  TimeRecord Result;
127b4db5f3e4b24bfc515bc615b2b6256083c7ef508Chris Lattner
128df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  sys::TimeValue now(0,0);
129df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  sys::TimeValue user(0,0);
130df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  sys::TimeValue sys(0,0);
131b4db5f3e4b24bfc515bc615b2b6256083c7ef508Chris Lattner
1326f2c64d70aad5328a843a6f6a6547ada69ead33bOwen Anderson  ssize_t MemUsed = 0;
1337d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  if (Start) {
134aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer    MemUsed = getMemUsage();
1359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
1367d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  } else {
1379bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
138fed1b27d323001682e7cb1bd66bb5d603cabb9f8Chris Lattner    MemUsed = getMemUsage();
1397d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  }
1408f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
141a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Result.WallTime   =  now.seconds() +  now.microseconds() / 1000000.0;
1429bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.UserTime   = user.seconds() + user.microseconds() / 1000000.0;
143a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Result.SystemTime =  sys.seconds() +  sys.microseconds() / 1000000.0;
1449bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.MemUsed = MemUsed;
1456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  return Result;
1466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
14890aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::vector<Timer*> > ActiveTimers;
1498f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1506c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() {
1516c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Started = true;
152153d28a414d087cbe20d17329fed358f7fa1258bDan Gohman  ActiveTimers->push_back(this);
153a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Time -= TimeRecord::getCurrentTime(true);
1546c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1556c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1566c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() {
157a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Time += TimeRecord::getCurrentTime(false);
1588f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
15990aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner  if (ActiveTimers->back() == this) {
16090aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->pop_back();
1618f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  } else {
1628f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    std::vector<Timer*>::iterator I =
16390aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner      std::find(ActiveTimers->begin(), ActiveTimers->end(), this);
16490aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    assert(I != ActiveTimers->end() && "stop but no startTimer?");
16590aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->erase(I);
1668f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
1676c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1686c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1699bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnerstatic void printVal(double Val, double Total, raw_ostream &OS) {
1700613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner  if (Total < 1e-7)   // Avoid dividing by zero.
1719bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << "        -----     ";
1729bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  else {
1739bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << "  " << format("%7.4f", Val) << " (";
1749bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << format("%5.1f", Val*100/Total) << "%)";
1759bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  }
1769bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
1779bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
178a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
179a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getUserTime())
180a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    printVal(getUserTime(), Total.getUserTime(), OS);
181a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getSystemTime())
182a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    printVal(getSystemTime(), Total.getSystemTime(), OS);
1839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Total.getProcessTime())
1849bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    printVal(getProcessTime(), Total.getProcessTime(), OS);
185a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  printVal(getWallTime(), Total.getWallTime(), OS);
1869bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  OS << "  ";
1889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
189a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getMemUsed())
190a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    OS << format("%9lld", (long long)getMemUsed()) << "  ";
1919bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
1929bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1939bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
194d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
195d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//   NamedRegionTimer Implementation
196d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
197d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
198a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnertypedef StringMap<Timer> Name2TimerMap;
199a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnertypedef StringMap<std::pair<TimerGroup, Name2TimerMap> > Name2PairMap;
2005e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
201a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2TimerMap> NamedTimers;
202a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2PairMap> NamedGroupedTimers;
203d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
20490aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic Timer &getNamedRegionTimer(const std::string &Name) {
205a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
206a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
207a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Timer &T = (*NamedTimers)[Name];
208a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (!T.isInitialized())
209a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    T.init(Name);
210a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  return T;
211d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner}
212d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
2135e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohmanstatic Timer &getNamedRegionTimer(const std::string &Name,
2145e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                  const std::string &GroupName) {
215a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2165e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
217a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  std::pair<TimerGroup, Name2TimerMap> &GroupEntry =
218a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    (*NamedGroupedTimers)[GroupName];
2195e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
220a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (GroupEntry.second.empty())
221a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    GroupEntry.first.setName(GroupName);
2225e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
223a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Timer &T = GroupEntry.second[Name];
224a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (!T.isInitialized())
225a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    T.init(Name);
226a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  return T;
2275e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman}
2285e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
229d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris LattnerNamedRegionTimer::NamedRegionTimer(const std::string &Name)
230d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  : TimeRegion(getNamedRegionTimer(Name)) {}
231d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
2325e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan GohmanNamedRegionTimer::NamedRegionTimer(const std::string &Name,
2335e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman                                   const std::string &GroupName)
2345e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman  : TimeRegion(getNamedRegionTimer(Name, GroupName)) {}
2358f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
2366c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2376c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//   TimerGroup Implementation
2386c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2396c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
2409f9f6d19dd67926446fb89a7b2dc0bda6353645bChris LattnerTimerGroup::~TimerGroup() {
2419f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  // If the timer group is destroyed before the timers it owns, accumulate and
2429f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  // print the timing data.
2439f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  while (FirstTimer != 0)
2449f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner    removeTimer(*FirstTimer);
2459f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner}
2469f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
2479f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
248b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::removeTimer(Timer &T) {
249a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2509bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
251b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // If the timer was started, move its data to TimersToPrint.
2529f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  if (T.Started)
253b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    TimersToPrint.push_back(std::make_pair(T.Time, T.Name));
2549f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
2559f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  T.TG = 0;
256b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
257b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Unlink the timer from our list.
258b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  *T.Prev = T.Next;
259b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (T.Next)
260b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    T.Next->Prev = T.Prev;
261b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
262b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Print the report when all timers in this group are destroyed if some of
263b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // them were started.
264b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (FirstTimer != 0 || TimersToPrint.empty())
265b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    return;
266b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
267b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  raw_ostream *OutStream = GetLibSupportInfoOutputFile();
2689f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
269b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  PrintQueuedTimers(*OutStream);
2709f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
271b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (OutStream != &errs() && OutStream != &outs())
272b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    delete OutStream;   // Close the file.
273b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner}
274b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
275b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::addTimer(Timer &T) {
276b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
277b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
278b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Add the timer to our list.
279b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (FirstTimer)
280b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    FirstTimer->Prev = &T.Next;
281b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  T.Next = FirstTimer;
282b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  T.Prev = &FirstTimer;
283b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  FirstTimer = &T;
284b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner}
2859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
286b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
287b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Sort the timers in descending order by amount of time taken.
288b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  std::sort(TimersToPrint.begin(), TimersToPrint.end());
289b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
290a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TimeRecord Total;
291a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
292a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    Total += TimersToPrint[i].first;
293b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
294a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Print out timing header.
295b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "===" << std::string(73, '-') << "===\n";
296b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Figure out how many spaces to indent TimerGroup name.
297b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  unsigned Padding = (80-Name.length())/2;
298b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
299b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS.indent(Padding) << Name << '\n';
300b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "===" << std::string(73, '-') << "===\n";
301b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
302a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // If this is not an collection of ungrouped times, print the total time.
303a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Ungrouped timers don't really make sense to add up.  We still print the
304a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // TOTAL line to make the percentages make sense.
305a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (this != DefaultTimerGroup) {
306b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "  Total Execution Time: ";
307b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << format("%5.4f", Total.getProcessTime()) << " seconds (";
308b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << format("%5.4f", Total.getWallTime()) << " wall clock)\n";
3099fa0eff30a0d4fcbc84ac3ada4c47620b5449043Chris Lattner  }
310b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << '\n';
311b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
312a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getUserTime())
313b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   ---User Time---";
314a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getSystemTime())
315b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   --System Time--";
316a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getProcessTime())
317b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   --User+System--";
318b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "   ---Wall Time---";
319a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getMemUsed())
320b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "  ---Mem---";
321b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "  --- Name ---\n";
322b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
323a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Loop through all of the timing data, printing it out.
324a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
325a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
326b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    Entry.first.print(Total, OS);
327b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << Entry.second << '\n';
328a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
329b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
330b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  Total.print(Total, OS);
331b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "Total\n\n";
332b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS.flush();
333b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
3349bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimersToPrint.clear();
33546d9a6494496d215e850f337b5a723c484212f80Owen Anderson}
33646d9a6494496d215e850f337b5a723c484212f80Owen Anderson
337