Timer.cpp revision d0fde30ce850b78371fd1386338350591f9ff494
16c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===-- Timer.cpp - Interval Timing Support -------------------------------===//
2b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//                     The LLVM Compiler Infrastructure
4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
5b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// This file was developed by the LLVM research group and is distributed under
6b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// the University of Illinois Open Source License. See LICENSE.TXT for details.
7b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//
8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===//
96c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//
106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// Interval Timing implementation.
116c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//
126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
136c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
146c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner#include "Support/Timer.h"
153f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner#include "Support/CommandLine.h"
167a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#include "Config/sys/resource.h"
177a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#include "Config/sys/time.h"
187a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#include "Config/unistd.h"
197a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#include "Config/malloc.h"
206c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner#include <iostream>
216c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner#include <algorithm>
229550dc2df2aad33e92febc0e3a15aca372639a10Chris Lattner#include <functional>
23f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner#include <fstream>
24d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner#include <map>
25f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
26d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekenamespace llvm {
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
3071336a9c14d2da7fd9ab094eed8c6f3695b864eeChris 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
3371336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// would get destroyed before the Statistic, causing havoc to ensue.  We "fix"
3471336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// this by creating the string the first time it is needed and never destroying
3571336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner// it.
3671336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattnerstatic std::string &getLibSupportInfoOutputFilename() {
3771336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner  static std::string *LibSupportInfoOutputFilename = new std::string();
3871336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner  return *LibSupportInfoOutputFilename;
3971336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner}
406c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
413f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattnernamespace {
427a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#ifdef HAVE_MALLINFO
433f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner  cl::opt<bool>
443f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner  TrackSpace("track-memory", cl::desc("Enable -time-passes memory "
453f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner                                      "tracking (this may be slow)"),
463f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner             cl::Hidden);
477a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#endif
48f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
49f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  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
556c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *DefaultTimerGroup = 0;
566c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstatic TimerGroup *getDefaultTimerGroup() {
576c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (DefaultTimerGroup) return DefaultTimerGroup;
586c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  return DefaultTimerGroup = new TimerGroup("Miscellaneous Ungrouped Timers");
596c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
606c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
616c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(const std::string &N)
628f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
636c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    Started(false), TG(getDefaultTimerGroup()) {
646c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG->addTimer();
656c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
666c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
676c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(const std::string &N, TimerGroup &tg)
688f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  : Elapsed(0), UserTime(0), SystemTime(0), MemUsed(0), PeakMem(0), Name(N),
696c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    Started(false), TG(&tg) {
706c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG->addTimer();
716c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
726c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
736c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(const Timer &T) {
746c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG = T.TG;
756c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (TG) TG->addTimer();
766c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  operator=(T);
776c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
786c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
796c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
806c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner// Copy ctor, initialize with no TG member.
816c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::Timer(bool, const Timer &T) {
826c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG = T.TG;     // Avoid assertion in operator=
836c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  operator=(T);  // Copy contents
846c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TG = 0;
856c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
866c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
876c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
886c38a79d770f3f0eaa11694ad84ca729b75272c4Chris LattnerTimer::~Timer() {
896c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (TG) {
906c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    if (Started) {
916c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      Started = false;
926c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      TG->addTimerToPrint(*this);
936c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    }
946c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    TG->removeTimer();
956c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
966c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
976c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
988f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattnerstatic long getMemUsage() {
997a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#ifdef HAVE_MALLINFO
1003f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner  if (TrackSpace) {
1013f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner    struct mallinfo MI = mallinfo();
102e040f9706697b786a1288971b6d5ab96107bb799Chris Lattner    return MI.uordblks/*+MI.hblkhd*/;
1033f39849003689a4d33aecdc744d4d27fd93a8f68Chris Lattner  }
1047a73b80b9052136c8cd2234eb3433a07df7cf38eJohn Criswell#endif
1058c63883f1ff72191becfda8506e3919a50af20d8Brian Gaeke  return 0;
1068f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner}
1078f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnerstruct TimeRecord {
1096c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  double Elapsed, UserTime, SystemTime;
11018eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  long MemUsed;
1116c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner};
1126c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1138f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattnerstatic TimeRecord getTimeRecord(bool Start) {
1146c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  struct rusage RU;
1156c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  struct timeval T;
116bbe5ac1458f3719fd51785f086e9166ccbb0c464Chris Lattner  long MemUsed = 0;
1178f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  if (Start) {
1188f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    MemUsed = getMemUsage();
1198f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    if (getrusage(RUSAGE_SELF, &RU))
1208f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner      perror("getrusage call failed: -time-passes info incorrect!");
1218f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
1226c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  gettimeofday(&T, 0);
1238f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1248f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  if (!Start) {
1258f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    MemUsed = getMemUsage();
1268f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    if (getrusage(RUSAGE_SELF, &RU))
1278f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner      perror("getrusage call failed: -time-passes info incorrect!");
1286c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
1296c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1306c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  TimeRecord Result;
1316c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Result.Elapsed    =           T.tv_sec +           T.tv_usec/1000000.0;
1326c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Result.UserTime   = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0;
1336c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0;
1348f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  Result.MemUsed = MemUsed;
1358f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1366c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  return Result;
1376c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1386c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1398f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattnerstatic std::vector<Timer*> ActiveTimers;
1408f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1416c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::startTimer() {
1426c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Started = true;
1438f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  TimeRecord TR = getTimeRecord(true);
1446c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Elapsed    -= TR.Elapsed;
1456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  UserTime   -= TR.UserTime;
1466c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  SystemTime -= TR.SystemTime;
14718eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  MemUsed    -= TR.MemUsed;
1488f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  PeakMemBase = TR.MemUsed;
1498f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  ActiveTimers.push_back(this);
1506c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1516c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1526c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::stopTimer() {
1538f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  TimeRecord TR = getTimeRecord(false);
1546c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Elapsed    += TR.Elapsed;
1556c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  UserTime   += TR.UserTime;
1566c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  SystemTime += TR.SystemTime;
15718eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  MemUsed    += TR.MemUsed;
1588f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1598f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  if (ActiveTimers.back() == this) {
1608f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    ActiveTimers.pop_back();
1618f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  } else {
1628f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    std::vector<Timer*>::iterator I =
1638f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner      std::find(ActiveTimers.begin(), ActiveTimers.end(), this);
1648f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    assert(I != ActiveTimers.end() && "stop but no startTimer?");
1658f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    ActiveTimers.erase(I);
1668f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
1676c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1686c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1696c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid Timer::sum(const Timer &T) {
1706c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Elapsed    += T.Elapsed;
1716c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  UserTime   += T.UserTime;
1726c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  SystemTime += T.SystemTime;
17318eba91a05ccff184820f8afddfddada15e35e65Chris Lattner  MemUsed    += T.MemUsed;
1748f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  PeakMem    += T.PeakMem;
1756c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
1766c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
1778f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner/// addPeakMemoryMeasurement - This method should be called whenever memory
1788f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner/// usage needs to be checked.  It adds a peak memory measurement to the
1798f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner/// currently active timers, which will be printed when the timer group prints
1808f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner///
1818f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattnervoid Timer::addPeakMemoryMeasurement() {
1828f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  long MemUsed = getMemUsage();
1838f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
1848f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  for (std::vector<Timer*>::iterator I = ActiveTimers.begin(),
1858f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner         E = ActiveTimers.end(); I != E; ++I)
1868f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner    (*I)->PeakMem = std::max((*I)->PeakMem, MemUsed-(*I)->PeakMemBase);
1878f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner}
1888f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
189d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
190d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//   NamedRegionTimer Implementation
191d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner//===----------------------------------------------------------------------===//
192d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
193d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattnerstatic Timer &getNamedRegionTimer(const std::string &Name) {
194d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  static std::map<std::string, Timer> NamedTimers;
195d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
196d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  std::map<std::string, Timer>::iterator I = NamedTimers.lower_bound(Name);
197d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  if (I != NamedTimers.end() && I->first == Name)
198d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner    return I->second;
199d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
200d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  return NamedTimers.insert(I, std::make_pair(Name, Timer(Name)))->second;
201d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner}
202d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
203d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris LattnerNamedRegionTimer::NamedRegionTimer(const std::string &Name)
204d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner  : TimeRegion(getNamedRegionTimer(Name)) {}
205d5a310e4b3251410d4afd58ccea5ec7f0cb13d5fChris Lattner
2068f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner
2076c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//   TimerGroup Implementation
2096c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner//===----------------------------------------------------------------------===//
2106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
211f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner// printAlignedFP - Simulate the printf "%A.Bf" format, where A is the
212f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner// TotalWidth size, and B is the AfterDec size.
213f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner//
214f205fec78ae79707464d568bad297bc69fd1db78Chris Lattnerstatic void printAlignedFP(double Val, unsigned AfterDec, unsigned TotalWidth,
215f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner                           std::ostream &OS) {
216f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  assert(TotalWidth >= AfterDec+1 && "Bad FP Format!");
217f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS.width(TotalWidth-AfterDec-1);
218f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  char OldFill = OS.fill();
219f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS.fill(' ');
220f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS << (int)Val;  // Integer part;
221f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS << ".";
222f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS.width(AfterDec);
223f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS.fill('0');
224f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  unsigned ResultFieldSize = 1;
225f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  while (AfterDec--) ResultFieldSize *= 10;
226f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS << (int)(Val*ResultFieldSize) % ResultFieldSize;
227f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS.fill(OldFill);
228f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner}
229f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
230f205fec78ae79707464d568bad297bc69fd1db78Chris Lattnerstatic void printVal(double Val, double Total, std::ostream &OS) {
2316c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (Total < 1e-7)   // Avoid dividing by zero...
232f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    OS << "        -----     ";
233f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  else {
234f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    OS << "  ";
235f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    printAlignedFP(Val, 4, 7, OS);
236f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    OS << " (";
237f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    printAlignedFP(Val*100/Total, 1, 5, OS);
238f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    OS << "%)";
239f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  }
2406c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
2416c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
242f205fec78ae79707464d568bad297bc69fd1db78Chris Lattnervoid Timer::print(const Timer &Total, std::ostream &OS) {
2436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (Total.UserTime)
244f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    printVal(UserTime, Total.UserTime, OS);
2456c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (Total.SystemTime)
246f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    printVal(SystemTime, Total.SystemTime, OS);
2476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (Total.getProcessTime())
248f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    printVal(getProcessTime(), Total.getProcessTime(), OS);
249f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  printVal(Elapsed, Total.Elapsed, OS);
2506c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
251f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS << "  ";
2526c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
253f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  if (Total.MemUsed) {
254f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    OS.width(9);
255f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    OS << MemUsed << "  ";
256f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  }
2578f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  if (Total.PeakMem) {
258f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    if (PeakMem) {
259f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      OS.width(9);
260f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      OS << PeakMem << "  ";
261f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    } else
262f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      OS << "           ";
2638f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner  }
264f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  OS << Name << "\n";
2656c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
2666c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  Started = false;  // Once printed, don't print again
2676c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
2686c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
269f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner// GetLibSupportInfoOutputFile - Return a file stream to print our output on...
270d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekestd::ostream *
271d0fde30ce850b78371fd1386338350591f9ff494Brian GaekeGetLibSupportInfoOutputFile() {
27271336a9c14d2da7fd9ab094eed8c6f3695b864eeChris Lattner  std::string &LibSupportInfoOutputFilename = getLibSupportInfoOutputFilename();
273f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  if (LibSupportInfoOutputFilename.empty())
274f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    return &std::cerr;
275f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  if (LibSupportInfoOutputFilename == "-")
276f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    return &std::cout;
277f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
278f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  std::ostream *Result = new std::ofstream(LibSupportInfoOutputFilename.c_str(),
279903c2d11e2dfadaaa7c04c2e46bac62d82e7ed15Chris Lattner                                           std::ios::app);
280f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  if (!Result->good()) {
281f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    std::cerr << "Error opening info-output-file '"
282f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner              << LibSupportInfoOutputFilename << " for appending!\n";
283f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    delete Result;
284f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    return &std::cerr;
285f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  }
286f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner  return Result;
287f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner}
288f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
2896c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
2906c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattnervoid TimerGroup::removeTimer() {
2916c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (--NumTimers == 0 && !TimersToPrint.empty()) { // Print timing report...
2926c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    // Sort the timers in descending order by amount of time taken...
2936c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    std::sort(TimersToPrint.begin(), TimersToPrint.end(),
2946c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner              std::greater<Timer>());
2956c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
2966c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    // Figure out how many spaces to indent TimerGroup name...
2976c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    unsigned Padding = (80-Name.length())/2;
2986c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    if (Padding > 80) Padding = 0;         // Don't allow "negative" numbers
2996c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
300f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    std::ostream *OutStream = GetLibSupportInfoOutputFile();
301f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
3026c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    ++NumTimers;
3036c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    {  // Scope to contain Total timer... don't allow total timer to drop us to
3046c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner       // zero timers...
3056c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      Timer Total("TOTAL");
3066c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3076c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
3086c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner        Total.sum(TimersToPrint[i]);
3096c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3106c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      // Print out timing header...
311f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      *OutStream << "===" << std::string(73, '-') << "===\n"
312f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner                 << std::string(Padding, ' ') << Name << "\n"
313f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner                 << "===" << std::string(73, '-')
314f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner                 << "===\n  Total Execution Time: ";
3158166b7cdb891e0d3c5789260248211a8b6e99787Chris Lattner
316f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      printAlignedFP(Total.getProcessTime(), 4, 5, *OutStream);
317f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      *OutStream << " seconds (";
318f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      printAlignedFP(Total.getWallTime(), 4, 5, *OutStream);
319f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      *OutStream << " wall clock)\n\n";
3206c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3216c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      if (Total.UserTime)
322f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner        *OutStream << "   ---User Time---";
3236c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      if (Total.SystemTime)
324f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner        *OutStream << "   --System Time--";
3256c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      if (Total.getProcessTime())
326f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner        *OutStream << "   --User+System--";
327f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      *OutStream << "   ---Wall Time---";
32818eba91a05ccff184820f8afddfddada15e35e65Chris Lattner      if (Total.getMemUsed())
329f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner        *OutStream << "  ---Mem---";
3308f0d824dd7d3ad72ce2212556f306a69310dff3eChris Lattner      if (Total.getPeakMem())
331f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner        *OutStream << "  -PeakMem-";
332f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      *OutStream << "  --- Name ---\n";
3336c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3346c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      // Loop through all of the timing data, printing it out...
3356c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner      for (unsigned i = 0, e = TimersToPrint.size(); i != e; ++i)
336f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner        TimersToPrint[i].print(Total, *OutStream);
3376c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
338f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      Total.print(Total, *OutStream);
339f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      *OutStream << std::endl;  // Flush output
3406c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    }
3416c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    --NumTimers;
3426c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3436c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    TimersToPrint.clear();
344f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner
345f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner    if (OutStream != &std::cerr && OutStream != &std::cout)
346f205fec78ae79707464d568bad297bc69fd1db78Chris Lattner      delete OutStream;   // Close the file...
3476c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
3486c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner
3496c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  // Delete default timer group!
3506c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  if (NumTimers == 0 && this == DefaultTimerGroup) {
3516c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    delete DefaultTimerGroup;
3526c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner    DefaultTimerGroup = 0;
3536c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner  }
3546c38a79d770f3f0eaa11694ad84ca729b75272c4Chris Lattner}
355d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
356d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke} // End llvm namespace
357