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"
15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/StringMap.h"
16551ccae044b0ff658fe629dd67edd5ffe75d10e8Reid Spencer#include "llvm/Support/CommandLine.h"
17dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/Support/FileSystem.h"
18d9ea85ab01fb0f2929ed50223d3758dceea8bcbdChris Lattner#include "llvm/Support/Format.h"
19d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/ManagedStatic.h"
201f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Mutex.h"
211f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Process.h"
22d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/raw_ostream.h"
23b6d465f8131f5fb0b8e565685fb3395ed9aecbdbChris Lattnerusing namespace llvm;
24f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
2549a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on.
2649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnernamespace llvm { extern raw_ostream *CreateInfoOutputFile(); }
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
5549a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner// CreateInfoOutputFile - Return a file stream to print our output on.
5649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattnerraw_ostream *llvm::CreateInfoOutputFile() {
57cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  const std::string &OutputFilename = getLibSupportInfoOutputFilename();
58cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  if (OutputFilename.empty())
5949a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner    return new raw_fd_ostream(2, false); // stderr.
60cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  if (OutputFilename == "-")
6149a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner    return new raw_fd_ostream(1, false); // stdout.
62f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
6386026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // Append mode is used because the info output file is opened and closed
6486026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // each time -stats or -time-passes wants to print output to it. To
6586026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // compensate for this, the test-suite Makefiles have code to delete the
6686026cd24eb8bdffdd6cf94669f98baeb87d8ef3Dan Gohman  // info output file before running commands which write to it.
6737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  std::error_code EC;
6837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  raw_ostream *Result = new raw_fd_ostream(OutputFilename, EC,
6937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                                           sys::fs::F_Append | sys::fs::F_Text);
7037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (!EC)
71f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner    return Result;
72f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
73f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  errs() << "Error opening info-output-file '"
74cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner    << OutputFilename << " for appending!\n";
75f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner  delete Result;
7649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner  return new raw_fd_ostream(2, false); // stderr.
77f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner}
78f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
79f8df3e011c9b32f16bd6f3d4bb8d3d2e26280986Chris Lattner
80dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic TimerGroup *DefaultTimerGroup = nullptr;
816c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() {
829bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimerGroup *tmp = DefaultTimerGroup;
833b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  sys::MemoryFence();
849bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (tmp) return tmp;
859bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
86c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  sys::SmartScopedLock<true> Lock(*TimerLock);
879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  tmp = DefaultTimerGroup;
883b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  if (!tmp) {
899bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    tmp = new TimerGroup("Miscellaneous Ungrouped Timers");
909bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::MemoryFence();
919bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    DefaultTimerGroup = tmp;
923b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  }
93c11e84d3e7a432449d453b51b567f2fc5db4e8c0Mikhail Glushenkov
943b8d135879bd045d63174064c6879eaa6581ec00Owen Anderson  return tmp;
956c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
966c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
979bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
989bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner// Timer Implementation
999bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner//===----------------------------------------------------------------------===//
1009bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
101cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N) {
102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  assert(!TG && "Timer already initialized");
103cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Name.assign(N.begin(), N.end());
104a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Started = false;
105a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TG = getDefaultTimerGroup();
106b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->addTimer(*this);
1076c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
109cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnervoid Timer::init(StringRef N, TimerGroup &tg) {
110dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  assert(!TG && "Timer already initialized");
111cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Name.assign(N.begin(), N.end());
112a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Started = false;
113a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TG = &tg;
114b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->addTimer(*this);
1156c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1166c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1176c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() {
118ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  if (!TG) return;  // Never initialized, or already cleared.
119b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  TG->removeTimer(*this);
1206c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1216c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
122e269a1ac1cd795135e91e42527a9814f4807c75aJeff Cohenstatic inline size_t getMemUsage() {
123ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  if (!TrackSpace) return 0;
124ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  return sys::Process::GetMallocUsage();
125aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer}
126aeb47b8db9246fc0d5d6e437225fe84524da9202Reid Spencer
127a782e75d487006cafffdc256b3c623307fee4dcfChris LattnerTimeRecord TimeRecord::getCurrentTime(bool Start) {
128df52c9aaf2ec6fbd0562e849cdba36e620537989Reid Spencer  TimeRecord Result;
129ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  sys::TimeValue now(0,0), user(0,0), sys(0,0);
130ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
1317d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  if (Start) {
132ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    Result.MemUsed = getMemUsage();
1339bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
1347d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  } else {
1359bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    sys::Process::GetTimeUsage(now, user, sys);
136ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    Result.MemUsed = getMemUsage();
1377d05563324e538a377ba12ca62b2b5b0fbbba547Reid Spencer  }
1388f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
139a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Result.WallTime   =  now.seconds() +  now.microseconds() / 1000000.0;
1409bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  Result.UserTime   = user.seconds() + user.microseconds() / 1000000.0;
141a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Result.SystemTime =  sys.seconds() +  sys.microseconds() / 1000000.0;
1426c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  return Result;
1436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
14590aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattnerstatic ManagedStatic<std::vector<Timer*> > ActiveTimers;
1468f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() {
1486c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Started = true;
149153d28a414d087cbe20d17329fed358f7fa1258bDan Gohman  ActiveTimers->push_back(this);
150a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Time -= TimeRecord::getCurrentTime(true);
1516c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1526c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() {
154a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Time += TimeRecord::getCurrentTime(false);
1558f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
15690aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner  if (ActiveTimers->back() == this) {
15790aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->pop_back();
1588f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  } else {
1598f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    std::vector<Timer*>::iterator I =
16090aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner      std::find(ActiveTimers->begin(), ActiveTimers->end(), this);
16190aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    assert(I != ActiveTimers->end() && "stop but no startTimer?");
16290aa839c88776e3dd0b3a798a98ea30d85b6b53cChris Lattner    ActiveTimers->erase(I);
1638f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
1646c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1656c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1669bb110f78efb6096e70336da83b2015f83fc6233Chris Lattnerstatic void printVal(double Val, double Total, raw_ostream &OS) {
1670613edc5cfe6a6c06db93436a024a265fde2a5abChris Lattner  if (Total < 1e-7)   // Avoid dividing by zero.
1689bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    OS << "        -----     ";
169962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer  else
170962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer    OS << format("  %7.4f (%5.1f%%)", Val, Val*100/Total);
1719bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
1729bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
173a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnervoid TimeRecord::print(const TimeRecord &Total, raw_ostream &OS) const {
174a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getUserTime())
175a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    printVal(getUserTime(), Total.getUserTime(), OS);
176a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getSystemTime())
177a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    printVal(getSystemTime(), Total.getSystemTime(), OS);
1789bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  if (Total.getProcessTime())
1799bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner    printVal(getProcessTime(), Total.getProcessTime(), OS);
180a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  printVal(getWallTime(), Total.getWallTime(), OS);
1819bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1829bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  OS << "  ";
1839bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
184a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getMemUsed())
18541a964931a0e0943ceef28b0c691843bf8ca87b7Benjamin Kramer    OS << format("%9" PRId64 "  ", (int64_t)getMemUsed());
1869bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner}
1879bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
1889bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
189d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
190d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//   NamedRegionTimer Implementation
191d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
192d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
193b35798347ea87b8b6d36155b211016a7769f01abDan Gohmannamespace {
194b35798347ea87b8b6d36155b211016a7769f01abDan Gohman
195a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnertypedef StringMap<Timer> Name2TimerMap;
196ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
197ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerclass Name2PairMap {
198ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  StringMap<std::pair<TimerGroup*, Name2TimerMap> > Map;
199ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnerpublic:
200ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  ~Name2PairMap() {
201ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    for (StringMap<std::pair<TimerGroup*, Name2TimerMap> >::iterator
202ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner         I = Map.begin(), E = Map.end(); I != E; ++I)
203ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner      delete I->second.first;
204ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  }
205ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
206cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattner  Timer &get(StringRef Name, StringRef GroupName) {
207ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    sys::SmartScopedLock<true> L(*TimerLock);
208ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
209ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    std::pair<TimerGroup*, Name2TimerMap> &GroupEntry = Map[GroupName];
210ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
211ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    if (!GroupEntry.first)
212ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner      GroupEntry.first = new TimerGroup(GroupName);
213ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
214ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    Timer &T = GroupEntry.second[Name];
215ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    if (!T.isInitialized())
216ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner      T.init(Name, *GroupEntry.first);
217ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    return T;
218ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  }
219ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner};
2205e84368b26415b3bb7f3f8d9cff3e05938dd82d0Dan Gohman
221b35798347ea87b8b6d36155b211016a7769f01abDan Gohman}
222b35798347ea87b8b6d36155b211016a7769f01abDan Gohman
223a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2TimerMap> NamedTimers;
224a782e75d487006cafffdc256b3c623307fee4dcfChris Lattnerstatic ManagedStatic<Name2PairMap> NamedGroupedTimers;
225d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
226cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris Lattnerstatic Timer &getNamedRegionTimer(StringRef Name) {
227a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
228a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner
229a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  Timer &T = (*NamedTimers)[Name];
230a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (!T.isInitialized())
231a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    T.init(Name);
232a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  return T;
233d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner}
234d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
23503c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name,
23603c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman                                   bool Enabled)
237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  : TimeRegion(!Enabled ? nullptr : &getNamedRegionTimer(Name)) {}
238d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
23903c3dc7b6828d48a9f3be50896b3390a696caa64Dan GohmanNamedRegionTimer::NamedRegionTimer(StringRef Name, StringRef GroupName,
24003c3dc7b6828d48a9f3be50896b3390a696caa64Dan Gohman                                   bool Enabled)
241dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  : TimeRegion(!Enabled ? nullptr : &NamedGroupedTimers->get(Name, GroupName)){}
2428f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
2436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//   TimerGroup Implementation
2456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
24783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroupList - This is the global list of TimerGroups, maintained by the
24883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// TimerGroup ctor/dtor and is protected by the TimerLock lock.
249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesstatic TimerGroup *TimerGroupList = nullptr;
25083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
251cebf5bc2ee0c5fdfa2b604e002b60add3cc895f0Chris LattnerTimerGroup::TimerGroup(StringRef name)
252dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  : Name(name.begin(), name.end()), FirstTimer(nullptr) {
25383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
25483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  // Add the group to TimerGroupList.
25583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
25683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  if (TimerGroupList)
25783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner    TimerGroupList->Prev = &Next;
25883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  Next = TimerGroupList;
25983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  Prev = &TimerGroupList;
26083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  TimerGroupList = this;
26183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner}
26283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
2639f9f6d19dd67926446fb89a7b2dc0bda6353645bChris LattnerTimerGroup::~TimerGroup() {
2649f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  // If the timer group is destroyed before the timers it owns, accumulate and
2659f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  // print the timing data.
266dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  while (FirstTimer)
2679f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner    removeTimer(*FirstTimer);
26883fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
26983fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  // Remove the group from the TimerGroupList.
27083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
27183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  *Prev = Next;
27283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  if (Next)
27383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner    Next->Prev = Prev;
2749f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner}
2759f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
2769f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
277b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::removeTimer(Timer &T) {
278a9d1f2c559ef4b2549e29288fe6944e68913ba0fOwen Anderson  sys::SmartScopedLock<true> L(*TimerLock);
2799bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
280b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // If the timer was started, move its data to TimersToPrint.
2819f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner  if (T.Started)
282b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    TimersToPrint.push_back(std::make_pair(T.Time, T.Name));
2839f9f6d19dd67926446fb89a7b2dc0bda6353645bChris Lattner
284dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  T.TG = nullptr;
285b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
286b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Unlink the timer from our list.
287b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  *T.Prev = T.Next;
288b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (T.Next)
289b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    T.Next->Prev = T.Prev;
290b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
291b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Print the report when all timers in this group are destroyed if some of
292b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // them were started.
293dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (FirstTimer || TimersToPrint.empty())
294b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    return;
295b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
29649a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner  raw_ostream *OutStream = CreateInfoOutputFile();
297b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  PrintQueuedTimers(*OutStream);
29849a2bb23d1391c8be45985518d4c5e99ff11b864Chris Lattner  delete OutStream;   // Close the file.
299b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner}
300b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
301b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::addTimer(Timer &T) {
302b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
303b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
304b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Add the timer to our list.
305b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (FirstTimer)
306b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    FirstTimer->Prev = &T.Next;
307b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  T.Next = FirstTimer;
308b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  T.Prev = &FirstTimer;
309b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  FirstTimer = &T;
310b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner}
3119bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner
312b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattnervoid TimerGroup::PrintQueuedTimers(raw_ostream &OS) {
313b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Sort the timers in descending order by amount of time taken.
314fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer  std::sort(TimersToPrint.begin(), TimersToPrint.end());
315fff0f11989a9ef23ab3e308783cc90c7620000ebBenjamin Kramer
316a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  TimeRecord Total;
317a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
318a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    Total += TimersToPrint[i].first;
319b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
320a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Print out timing header.
321b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "===" << std::string(73, '-') << "===\n";
322b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  // Figure out how many spaces to indent TimerGroup name.
323b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  unsigned Padding = (80-Name.length())/2;
324b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
325b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS.indent(Padding) << Name << '\n';
326b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "===" << std::string(73, '-') << "===\n";
327b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
328a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // If this is not an collection of ungrouped times, print the total time.
329a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Ungrouped timers don't really make sense to add up.  We still print the
330a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // TOTAL line to make the percentages make sense.
331962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer  if (this != DefaultTimerGroup)
332962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer    OS << format("  Total Execution Time: %5.4f seconds (%5.4f wall clock)\n",
333962bad70f4277841cf6278306caa93ebce304b48Benjamin Kramer                 Total.getProcessTime(), Total.getWallTime());
334b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << '\n';
335b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
336a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getUserTime())
337b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   ---User Time---";
338a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getSystemTime())
339b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   --System Time--";
340a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getProcessTime())
341b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "   --User+System--";
342b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "   ---Wall Time---";
343a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  if (Total.getMemUsed())
344b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << "  ---Mem---";
345b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "  --- Name ---\n";
346b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
347a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  // Loop through all of the timing data, printing it out.
348a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i) {
349a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner    const std::pair<TimeRecord, std::string> &Entry = TimersToPrint[e-i-1];
350b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    Entry.first.print(Total, OS);
351b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner    OS << Entry.second << '\n';
352a782e75d487006cafffdc256b3c623307fee4dcfChris Lattner  }
353b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
354b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  Total.print(Total, OS);
355b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS << "Total\n\n";
356b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner  OS.flush();
357b9312690a2a79de490ab9c439b9b5d7c9319bff8Chris Lattner
3589bb110f78efb6096e70336da83b2015f83fc6233Chris Lattner  TimersToPrint.clear();
35946d9a6494496d215e850f337b5a723c484212f80Owen Anderson}
36046d9a6494496d215e850f337b5a723c484212f80Owen Anderson
361ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner/// print - Print any started timers in this group and zero them.
362ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattnervoid TimerGroup::print(raw_ostream &OS) {
363ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
364ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
365ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  // See if any of our timers were started, if so add them to TimersToPrint and
366ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  // reset them.
367ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  for (Timer *T = FirstTimer; T; T = T->Next) {
368ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    if (!T->Started) continue;
369ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    TimersToPrint.push_back(std::make_pair(T->Time, T->Name));
370ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
371ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    // Clear out the time.
372ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    T->Started = 0;
373ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    T->Time = TimeRecord();
374ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  }
375ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner
376ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  // If any timers were started, print the group.
377ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner  if (!TimersToPrint.empty())
378ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner    PrintQueuedTimers(OS);
379ecdbff8c74e9c85af08fe9ec9cee4625d36c3c36Chris Lattner}
38083fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
38183fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner/// printAll - This static method prints all timers and clears them all out.
38283fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattnervoid TimerGroup::printAll(raw_ostream &OS) {
38383fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  sys::SmartScopedLock<true> L(*TimerLock);
38483fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner
38583fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner  for (TimerGroup *TG = TimerGroupList; TG; TG = TG->Next)
38683fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner    TG->print(OS);
38783fa78efb19d288d172a5db87bafcb9a34a4f035Chris Lattner}
388