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"
201f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h"
211f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Process.h"
22ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner#include "llvm/ADT/OwningPtr.h"
23a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner#include "llvm/ADT/StringMap.h"
24b6d465f8131f5fb0b8e565685fb3395ed9aecbdbChris Lattnerusing namespace llvm;
25f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
2649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on.
2749a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnernamespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
2971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// getLibSupportInfoOutputFilename - This ugly hack is brought to you courtesy
3071336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// of constructor/destructor ordering being unspecified by C++.  Basically the
31ac0b6ae358944ae8b2b5a11dc08f52c3ed89f2daChris Lattner// problem is that a Statistic object gets destroyed, which ends up calling
3271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// 'GetLibSupportInfoOutputFile()' (below), which calls this function.
3371336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// LibSupportInfoOutputFilename used to be a global variable, but sometimes it
34f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
35f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// this by creating the string the first time it is needed and never destroying
36f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer// it.
3790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::string> LibSupportInfoOutputFilename;
3871336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattnerstatic std::string &getLibSupportInfoOutputFilename() {
39f6e5a25f3a57a225c8545e453045f3ae220e3286Reid Spencer  return *LibSupportInfoOutputFilename;
4071336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner}
416c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
4246d9a6494496d215e850f337b5a723c484212f80Owen Andersonstatic ManagedStatic<sys::SmartMutex<true> > TimerLock;
4346d9a6494496d215e850f337b5a723c484212f80Owen Anderson
443f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattnernamespace {
453c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman  static cl::opt<bool>
463f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
473f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner                                      "tracking (this may be slow)"),
483f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner             cl::Hidden);
49f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
503c02aca2380bc95a3ce5799929354612c67cc105Dan Gohman  static cl::opt<std::string, true>
5196a54db5e763c19f556a1b54ad2956cc91b81cb8Chris Lattner  InfoOutputFilename("info-output-file", cl::value_desc("filename"),
52f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner                     cl::desc("File to append -stats and -timer output to"),
5371336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner                   cl::Hidden, cl::location(getLibSupportInfoOutputFilename()));
543f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner}
553f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner
5649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on.
5749a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnerraw_ostream *llvm::CreateInfoOutputFile() {
58cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  const std::string &OutputFilename = getLibSupportInfoOutputFilename();
59cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  if (OutputFilename.empty())
6049a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner    return new raw_fd_ostream(2, false); // stderr.
61cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  if (OutputFilename == "-")
6249a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner    return new raw_fd_ostream(1, false); // stdout.
63f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
6486026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // Append mode is used because the info output file is opened and closed
6586026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // each time -stats or -time-passes wants to print output to it. To
6686026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // compensate for this, the test-suite Makefiles have code to delete the
6786026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // info output file before running commands which write to it.
68f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  std::string Error;
69cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  raw_ostream *Result = new raw_fd_ostream(OutputFilename.c_str(),
70f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner                                           Error, raw_fd_ostream::F_Append);
71f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  if (Error.empty())
72f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner    return Result;
73f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
74f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  errs() << "Error opening info-output-file '"
75cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner    << OutputFilename << " for appending!\n";
76f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  delete Result;
7749a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner  return new raw_fd_ostream(2, false); // stderr.
78f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner}
79f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
80f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
81200aa6d89b75d2a4f630b85a4a785ae7d18d16bbOwen Andersonstatic TimerGroup *DefaultTimerGroup = 0;
826c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() {
839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimerGroup *tmp = DefaultTimerGroup;
843b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  sys::MemoryFence();
859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (tmp) return tmp;
869bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  llvm_acquire_global_lock();
889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  tmp = DefaultTimerGroup;
893b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  if (!tmp) {
909bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
919bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::MemoryFence();
929bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    DefaultTimerGroup = tmp;
933b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  }
949bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  llvm_release_global_lock();
95c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov
963b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  return tmp;
976c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
986c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
999bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
1009bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner// Timer Implementation
1019bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
1029bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
103cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N) {
104a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  assert(TG == 0 && "Timer already initialized");
105cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Name.assign(N.begin(), N.end());
106a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Started = false;
107a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TG = getDefaultTimerGroup();
108b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->addTimer(*this);
1096c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
111cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N, TimerGroup &tg) {
112a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  assert(TG == 0 && "Timer already initialized");
113cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Name.assign(N.begin(), N.end());
114a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Started = false;
115a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TG = &tg;
116b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->addTimer(*this);
1176c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1186c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1196c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() {
120ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  if (!TG) return;  // Never initialized, or already cleared.
121b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->removeTimer(*this);
1226c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1236c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
124e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohenstatic inline size_t getMemUsage() {
125ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  if (!TrackSpace) return 0;
126ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  return sys::Process::GetMallocUsage();
127aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer}
128aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer
129a782e75d487006cafffdc256b3c623307fee4dcfChris LattnerTimeRecord TimeRecord::getCurrentTime(bool Start) {
130df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  TimeRecord Result;
131ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  sys::TimeValue now(0,0), user(0,0), sys(0,0);
132ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
1337d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  if (Start) {
134ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    Result.MemUsed = getMemUsage();
1359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
1367d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  } else {
1379bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
138ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    Result.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;
1446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  return Result;
1456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
14790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::vector<Timer*> > ActiveTimers;
1488f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1496c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() {
1506c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Started = true;
151153d28a414d087cbe20d17329fed358f7fa1258bDan Gohman  ActiveTimers->push_back(this);
152a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Time -= TimeRecord::getCurrentTime(true);
1536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1546c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1556c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() {
156a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Time += TimeRecord::getCurrentTime(false);
1578f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
15890aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner  if (ActiveTimers->back() == this) {
15990aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->pop_back();
1608f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  } else {
1618f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    std::vector<Timer*>::iterator I =
16290aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner      std::find(ActiveTimers->begin(), ActiveTimers->end(), this);
16390aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    assert(I != ActiveTimers->end() && "stop but no startTimer?");
16490aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->erase(I);
1658f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
1666c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1676c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1689bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnerstatic void printVal(double Val, double Total, raw_ostream &OS) {
1690613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner  if (Total < 1e-7)   // Avoid dividing by zero.
1709bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << "        -----     ";
171962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer  else
172962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer    OS << format("  %7.4f (%5.1f%%)", Val, Val*100/Total);
1739bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
1749bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
175a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
176a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getUserTime())
177a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    printVal(getUserTime(), Total.getUserTime(), OS);
178a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getSystemTime())
179a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    printVal(getSystemTime(), Total.getSystemTime(), OS);
1809bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Total.getProcessTime())
1819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    printVal(getProcessTime(), Total.getProcessTime(), OS);
182a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  printVal(getWallTime(), Total.getWallTime(), OS);
1839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1849bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  OS << "  ";
1859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
186a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getMemUsed())
1874eb73c59bcd1055e9a3f324d836ce3898fbb7c81Benjamin Kramer    OS << format("%9" PRId64 "  ", (int64_t)getMemUsed());
1889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
1899bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1909bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
191d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
192d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//   NamedRegionTimer Implementation
193d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
194d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
195b35798347ea87b8b6d36155b211016a7769f01abDan Gohmannamespace {
196b35798347ea87b8b6d36155b211016a7769f01abDan Gohman
197a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnertypedef StringMap<Timer> Name2TimerMap;
198ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
199ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerclass Name2PairMap {
200ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map;
201ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerpublic:
202ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  ~Name2PairMap() {
203ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator
204ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner         I = Map.begin(), E = Map.end(); I != E; ++I)
205ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner      delete I->second.first;
206ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  }
207ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
208cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Timer &get(StringRef Name, StringRef GroupName) {
209ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    sys::SmartScopedLock<true> L(*TimerLock);
210ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
211ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName];
212ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
213ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    if (!GroupEntry.first)
214ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner      GroupEntry.first = new TimerGroup(GroupName);
215ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
216ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    Timer &T = GroupEntry.second[Name];
217ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    if (!T.isInitialized())
218ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner      T.init(Name, *GroupEntry.first);
219ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    return T;
220ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  }
221ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner};
2225e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
223b35798347ea87b8b6d36155b211016a7769f01abDan Gohman}
224b35798347ea87b8b6d36155b211016a7769f01abDan Gohman
225a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2TimerMap> NamedTimers;
226a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2PairMap> NamedGroupedTimers;
227d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
228cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnerstatic Timer &getNamedRegionTimer(StringRef Name) {
229a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
230a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
231a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Timer &T = (*NamedTimers)[Name];
232a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (!T.isInitialized())
233a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    T.init(Name);
234a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  return T;
235d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner}
236d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
23703c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name,
23803c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman                                   bool Enabled)
23903c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman  : TimeRegion(!Enabled ? 0 : &getNamedRegionTimer(Name)) {}
240d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
24103c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName,
24203c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman                                   bool Enabled)
24303c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman  : TimeRegion(!Enabled ? 0 : &NamedGroupedTimers->get(Name, GroupName)) {}
2448f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
2456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//   TimerGroup Implementation
2476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2486c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
24983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroupList - This is the global list of TimerGroups, maintained by the
25083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroup ctor/dtor and is protected by the TimerLock lock.
25183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattnerstatic TimerGroup *TimerGroupList = 0;
25283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
253cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris LattnerTimerGroup::TimerGroup(StringRef name)
254cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  : Name(name.begin(), name.end()), FirstTimer(0) {
25583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
25683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  // Add the group to TimerGroupList.
25783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
25883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  if (TimerGroupList)
25983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner    TimerGroupList->Prev = &Next;
26083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  Next = TimerGroupList;
26183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  Prev = &TimerGroupList;
26283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  TimerGroupList = this;
26383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner}
26483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
2659f9f6d19dd67926446fb89a7b2dc0bda6353645bChris LattnerTimerGroup::~TimerGroup() {
2669f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  // If the timer group is destroyed before the timers it owns, accumulate and
2679f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  // print the timing data.
2689f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  while (FirstTimer != 0)
2699f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner    removeTimer(*FirstTimer);
27083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
27183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  // Remove the group from the TimerGroupList.
27283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
27383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  *Prev = Next;
27483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  if (Next)
27583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner    Next->Prev = Prev;
2769f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner}
2779f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
2789f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
279b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::removeTimer(Timer &T) {
280a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
282b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // If the timer was started, move its data to TimersToPrint.
2839f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  if (T.Started)
284b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    TimersToPrint.push_back(std::make_pair(T.Time, T.Name));
2859f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
2869f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  T.TG = 0;
287b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
288b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Unlink the timer from our list.
289b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  *T.Prev = T.Next;
290b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (T.Next)
291b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    T.Next->Prev = T.Prev;
292b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
293b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Print the report when all timers in this group are destroyed if some of
294b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // them were started.
295b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (FirstTimer != 0 || TimersToPrint.empty())
296b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    return;
297b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
29849a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner  raw_ostream *OutStream = CreateInfoOutputFile();
299b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  PrintQueuedTimers(*OutStream);
30049a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner  delete OutStream;   // Close the file.
301b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner}
302b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
303b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::addTimer(Timer &T) {
304b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
305b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
306b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Add the timer to our list.
307b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (FirstTimer)
308b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    FirstTimer->Prev = &T.Next;
309b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  T.Next = FirstTimer;
310b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  T.Prev = &FirstTimer;
311b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  FirstTimer = &T;
312b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner}
3139bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
314b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
315b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Sort the timers in descending order by amount of time taken.
316fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer  std::sort(TimersToPrint.begin(), TimersToPrint.end());
317fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer
318a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TimeRecord Total;
319a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
320a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    Total += TimersToPrint[i].first;
321b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
322a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Print out timing header.
323b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "===" << std::string(73, '-') << "===\n";
324b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Figure out how many spaces to indent TimerGroup name.
325b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  unsigned Padding = (80-Name.length())/2;
326b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
327b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS.indent(Padding) << Name << '\n';
328b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "===" << std::string(73, '-') << "===\n";
329b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
330a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // If this is not an collection of ungrouped times, print the total time.
331a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Ungrouped timers don't really make sense to add up.  We still print the
332a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // TOTAL line to make the percentages make sense.
333962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer  if (this != DefaultTimerGroup)
334962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer    OS << format("  Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
335962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer                 Total.getProcessTime(), Total.getWallTime());
336b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << '\n';
337b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
338a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getUserTime())
339b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   ---User Time---";
340a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getSystemTime())
341b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   --System Time--";
342a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getProcessTime())
343b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   --User+System--";
344b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "   ---Wall Time---";
345a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getMemUsed())
346b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "  ---Mem---";
347b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "  --- Name ---\n";
348b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
349a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Loop through all of the timing data, printing it out.
350a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
351a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
352b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    Entry.first.print(Total, OS);
353b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << Entry.second << '\n';
354a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
355b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
356b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  Total.print(Total, OS);
357b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "Total\n\n";
358b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS.flush();
359b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
3609bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimersToPrint.clear();
36146d9a6494496d215e850f337b5a723c484212f80Owen Anderson}
36246d9a6494496d215e850f337b5a723c484212f80Owen Anderson
363ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner/// print - Print any started timers in this group and zero them.
364ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnervoid TimerGroup::print(raw_ostream &OS) {
365ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
366ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
367ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  // See if any of our timers were started, if so add them to TimersToPrint and
368ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  // reset them.
369ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  for (Timer *T = FirstTimer; T; T = T->Next) {
370ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    if (!T->Started) continue;
371ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    TimersToPrint.push_back(std::make_pair(T->Time, T->Name));
372ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
373ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    // Clear out the time.
374ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    T->Started = 0;
375ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    T->Time = TimeRecord();
376ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  }
377ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
378ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  // If any timers were started, print the group.
379ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  if (!TimersToPrint.empty())
380ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    PrintQueuedTimers(OS);
381ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner}
38283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
38383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// printAll - This static method prints all timers and clears them all out.
38483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattnervoid TimerGroup::printAll(raw_ostream &OS) {
38583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
38683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
38783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
38883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner    TG->print(OS);
38983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner}
390