diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index 85c4dec5fe7..0be92e9f551 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -80,84 +80,6 @@ static cl::opt<bool> EnableTiming("time-passes", cl::desc("Time each pass, printing elapsed time for each on exit")); -static TimeRecord getTimeRecord() { - static unsigned long PageSize = 0; - - if (PageSize == 0) { -#ifdef _SC_PAGE_SIZE - PageSize = sysconf(_SC_PAGE_SIZE); -#else -#ifdef _SC_PAGESIZE - PageSize = sysconf(_SC_PAGESIZE); -#else - PageSize = getpagesize(); -#endif -#endif - } - - struct rusage RU; - struct timeval T; - gettimeofday(&T, 0); - if (getrusage(RUSAGE_SELF, &RU)) { - perror("getrusage call failed: -time-passes info incorrect!"); - } - - TimeRecord Result; - Result.Elapsed = T.tv_sec + T.tv_usec/1000000.0; - Result.UserTime = RU.ru_utime.tv_sec + RU.ru_utime.tv_usec/1000000.0; - Result.SystemTime = RU.ru_stime.tv_sec + RU.ru_stime.tv_usec/1000000.0; - Result.MaxRSS = RU.ru_maxrss*PageSize; - - return Result; -} - -bool TimeRecord::operator<(const TimeRecord &TR) const { - // Primary sort key is User+System time - if (UserTime+SystemTime < TR.UserTime+TR.SystemTime) - return true; - if (UserTime+SystemTime > TR.UserTime+TR.SystemTime) - return false; - - // Secondary sort key is Wall Time - return Elapsed < TR.Elapsed; -} - -void TimeRecord::passStart(const TimeRecord &T) { - Elapsed -= T.Elapsed; - UserTime -= T.UserTime; - SystemTime -= T.SystemTime; - RSSTemp = T.MaxRSS; -} - -void TimeRecord::passEnd(const TimeRecord &T) { - Elapsed += T.Elapsed; - UserTime += T.UserTime; - SystemTime += T.SystemTime; - RSSTemp = T.MaxRSS - RSSTemp; - MaxRSS = std::max(MaxRSS, RSSTemp); -} - -static void printVal(double Val, double Total) { - if (Total < 1e-7) // Avoid dividing by zero... - fprintf(stderr, " ----- "); - else - fprintf(stderr, " %7.4f (%5.1f%%)", Val, Val*100/Total); -} - -void TimeRecord::print(const char *PassName, const TimeRecord &Total) const { - printVal(UserTime, Total.UserTime); - printVal(SystemTime, Total.SystemTime); - printVal(UserTime+SystemTime, Total.UserTime+Total.SystemTime); - printVal(Elapsed, Total.Elapsed); - - fprintf(stderr, " "); - - if (Total.MaxRSS) - std::cerr << MaxRSS << "\t"; - std::cerr << PassName << "\n"; -} - - // Create method. If Timing is enabled, this creates and returns a new timing // object, otherwise it returns null. // @@ -165,58 +87,6 @@ TimingInfo *TimingInfo::create() { return EnableTiming ? new TimingInfo() : 0; } -void TimingInfo::passStarted(Pass *P) { - TimingData[P].passStart(getTimeRecord()); -} -void TimingInfo::passEnded(Pass *P) { - TimingData[P].passEnd(getTimeRecord()); -} -void TimeRecord::sum(const TimeRecord &TR) { - Elapsed += TR.Elapsed; - UserTime += TR.UserTime; - SystemTime += TR.SystemTime; - MaxRSS += TR.MaxRSS; -} - -// TimingDtor - Print out information about timing information -TimingInfo::~TimingInfo() { - // Iterate over all of the data, converting it into the dual of the data map, - // so that the data is sorted by amount of time taken, instead of pointer. - // - std::vector<std::pair<TimeRecord, Pass*> > Data; - TimeRecord Total; - for (std::map<Pass*, TimeRecord>::iterator I = TimingData.begin(), - E = TimingData.end(); I != E; ++I) - // Throw out results for "grouping" pass managers... - if (!dynamic_cast<AnalysisResolver*>(I->first)) { - Data.push_back(std::make_pair(I->second, I->first)); - Total.sum(I->second); - } - - // Sort the data by time as the primary key, in reverse order... - std::sort(Data.begin(), Data.end(), - std::greater<std::pair<TimeRecord, Pass*> >()); - - // Print out timing header... - std::cerr << std::string(79, '=') << "\n" - << " ... Pass execution timing report ...\n" - << std::string(79, '=') << "\n Total Execution Time: " - << (Total.UserTime+Total.SystemTime) << " seconds (" - << Total.Elapsed << " wall clock)\n\n ---User Time--- " - << "--System Time-- --User+System-- ---Wall Time---"; - - if (Total.MaxRSS) - std::cerr << " ---Mem---"; - std::cerr << " --- Pass Name ---\n"; - - // Loop through all of the timing data, printing it out... - for (unsigned i = 0, e = Data.size(); i != e; ++i) - Data[i].first.print(Data[i].second->getPassName(), Total); - - Total.print("TOTAL", Total); -} - - void PMDebug::PrintArgumentInformation(const Pass *P) { // Print out passes in pass manager... if (const AnalysisResolver *PM = dynamic_cast<const AnalysisResolver*>(P)) { diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index cf8624105da..bde97ba3a34 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -18,6 +18,7 @@ #include "llvm/Pass.h" #include "Support/CommandLine.h" #include "Support/LeakDetector.h" +#include "Support/Timer.h" #include <algorithm> #include <iostream> class Annotable; @@ -75,25 +76,13 @@ struct PMDebug { // amount of time each pass takes to execute. This only happens when // -time-passes is enabled on the command line. // -struct TimeRecord { // TimeRecord - Data we collect and print for each pass - double Elapsed; // Wall clock time elapsed in seconds - double UserTime; // User time elapsed - double SystemTime; // System time elapsed - unsigned long MaxRSS; // Maximum resident set size (in bytes) - unsigned long RSSTemp; // Temp for calculating maxrss - - TimeRecord() : Elapsed(0), UserTime(0), SystemTime(0), MaxRSS(0) {} - void passStart(const TimeRecord &T); - void passEnd(const TimeRecord &T); - void sum(const TimeRecord &TR); - bool operator<(const TimeRecord &TR) const; - - void print(const char *PassName, const TimeRecord &TotalTime) const; -}; class TimingInfo { - std::map<Pass*, TimeRecord> TimingData; - TimingInfo() {} // Private ctor, must use create member + std::map<Pass*, Timer> TimingData; + TimerGroup TG; + + // Private ctor, must use 'create' member + TimingInfo() : TG("... Pass execution timing report ...") {} public: // Create method. If Timing is enabled, this creates and returns a new timing // object, otherwise it returns null. @@ -101,10 +90,23 @@ public: static TimingInfo *create(); // TimingDtor - Print out information about timing information - ~TimingInfo(); + ~TimingInfo() { + // Delete all of the timers... + TimingData.clear(); + // TimerGroup is deleted next, printing the report. + } - void passStarted(Pass *P); - void passEnded(Pass *P); + void passStarted(Pass *P) { + std::map<Pass*, Timer>::iterator I = TimingData.find(P); + if (I == TimingData.end()) + I = TimingData.insert(std::make_pair(P, Timer(P->getPassName()))).first; + I->second.startTimer(); + } + void passEnded(Pass *P) { + std::map<Pass*, Timer>::iterator I = TimingData.find(P); + assert (I != TimingData.end() && "passStarted/passEnded not nested right!"); + I->second.stopTimer(); + } }; //===----------------------------------------------------------------------===//