From 691fa3cfb12f459b953dd400057841b10ccf4b72 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 29 Apr 2002 04:04:29 +0000 Subject: [PATCH] Add a new command line option for PassManager using utilities. Now for llc, gccas, analyze, opt, etc you can specify the -time-passes command line option that outputs a timing summary report that indicates how long each pass takes to execute. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2394 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/Pass.cpp | 60 +++++++++++++++++++++++++ lib/VMCore/PassManagerT.h | 95 ++++++++++++++++++++++++++++++++++----- 2 files changed, 144 insertions(+), 11 deletions(-) diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index c3c9d456b5e..0344dd63b33 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -15,6 +15,8 @@ #include "Support/CommandLine.h" #include #include +#include +#include // Source of unique analysis ID #'s. unsigned AnalysisID::NextID = 0; @@ -49,6 +51,64 @@ void PassManager::add(Pass *P) { PM->add(P); } bool PassManager::run(Module *M) { return PM->run(M); } +//===----------------------------------------------------------------------===// +// TimingInfo Class - This class is used to calculate information about the +// amount of time each pass takes to execute. This only happens with +// -time-passes is enabled on the command line. +// +static cl::Flag EnableTiming("time-passes", "Time each pass, printing elapsed" + " time for each on exit"); + +static double getTime() { + struct timeval T; + gettimeofday(&T, 0); + return T.tv_sec + T.tv_usec/1000000.0; +} + +// Create method. If Timing is enabled, this creates and returns a new timing +// object, otherwise it returns null. +// +TimingInfo *TimingInfo::create() { + return EnableTiming ? new TimingInfo() : 0; +} + +void TimingInfo::passStarted(Pass *P) { TimingData[P] -= getTime(); } +void TimingInfo::passEnded(Pass *P) { TimingData[P] += getTime(); } + +// 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 > Data; + double TotalTime = 0; + for (std::map::iterator I = TimingData.begin(), + E = TimingData.end(); I != E; ++I) + // Throw out results for "grouping" pass managers... + if (!dynamic_cast(I->first)) { + Data.push_back(std::make_pair(I->second, I->first)); + TotalTime += I->second; + } + + // Sort the data by time as the primary key, in reverse order... + std::sort(Data.begin(), Data.end(), greater >()); + + // Print out timing header... + cerr << std::string(79, '=') << "\n" + << " ... Pass execution timing report ...\n" + << std::string(79, '=') << "\n Total Execution Time: " << TotalTime + << " seconds\n\n % Time: Seconds:\tPass Name (mangled):\n"; + + // Loop through all of the timing data, printing it out... + for (unsigned i = 0, e = Data.size(); i != e; ++i) { + fprintf(stderr, " %6.2f%% %fs\t%s\n", Data[i].first*100 / TotalTime, + Data[i].first, typeid(*Data[i].second).name()); + } + cerr << " 100.00% " << TotalTime << "s\tTOTAL\n" + << std::string(79, '=') << "\n"; +} + + //===----------------------------------------------------------------------===// // Pass debugging information. Often it is useful to find out what pass is // running when a crash occurs in a utility. When this library is compiled with diff --git a/lib/VMCore/PassManagerT.h b/lib/VMCore/PassManagerT.h index eb80740d44a..8d1716b95a0 100644 --- a/lib/VMCore/PassManagerT.h +++ b/lib/VMCore/PassManagerT.h @@ -35,6 +35,28 @@ struct PMDebug { }; +//===----------------------------------------------------------------------===// +// TimingInfo Class - This class is used to calculate information about the +// amount of time each pass takes to execute. This only happens when +// -time-passes is enabled on the command line. +// +class TimingInfo { + std::map TimingData; + TimingInfo() {} // Private ctor, must use create member +public: + // Create method. If Timing is enabled, this creates and returns a new timing + // object, otherwise it returns null. + // + static TimingInfo *create(); + + // TimingDtor - Print out information about timing information + ~TimingInfo(); + + void passStarted(Pass *P); + void passEnded(Pass *P); +}; + + //===----------------------------------------------------------------------===// // Declare the PassManagerTraits which will be specialized... @@ -49,15 +71,15 @@ template class PassManagerTraits; // Do not define. // template class PassManagerT : public PassManagerTraits,public AnalysisResolver{ - typedef typename PassManagerTraits::PassClass PassClass; - typedef typename PassManagerTraits::SubPassClass SubPassClass; - typedef typename PassManagerTraits::BatcherClass BatcherClass; - typedef typename PassManagerTraits::ParentClass ParentClass; - typedef PassManagerTraits Traits; + typedef PassManagerTraits Traits; + typedef typename Traits::PassClass PassClass; + typedef typename Traits::SubPassClass SubPassClass; + typedef typename Traits::BatcherClass BatcherClass; + typedef typename Traits::ParentClass ParentClass; - friend typename PassManagerTraits::PassClass; - friend typename PassManagerTraits::SubPassClass; - friend class PassManagerTraits; + friend typename Traits::PassClass; + friend typename Traits::SubPassClass; + friend class Traits; std::vector Passes; // List of pass's to run @@ -128,7 +150,9 @@ public: #endif // Run the sub pass! - bool Changed = Traits::runPass(P, M); + startPass(P); + bool Changed = runPass(P, M); + endPass(P); MadeChanges |= Changed; if (Changed) @@ -217,6 +241,20 @@ public: return I->second; } + // {start/end}Pass - Called when a pass is started, it just propogates + // information up to the top level PassManagerT object to tell it that a pass + // has started or ended. This is used to gather timing information about + // passes. + // + void startPass(Pass *P) { + if (Parent) Parent->startPass(P); + else PassStarted(P); + } + void endPass(Pass *P) { + if (Parent) Parent->endPass(P); + else PassEnded(P); + } + // markPassUsed - Inform higher level pass managers (and ourselves) // that these analyses are being used by this pass. This is used to // make sure that analyses are not free'd before we have to use @@ -389,6 +427,10 @@ template<> struct PassManagerTraits : public BasicBlockPass { return P->runOnBasicBlock(M); } + // Dummy implementation of PassStarted/PassEnded + static void PassStarted(Pass *P) {} + static void PassEnded(Pass *P) {} + // getPMName() - Return the name of the unit the PassManager operates on for // debugging. const char *getPMName() const { return "BasicBlock"; } @@ -428,6 +470,10 @@ template<> struct PassManagerTraits : public FunctionPass { return P->runOnFunction(F); } + // Dummy implementation of PassStarted/PassEnded + static void PassStarted(Pass *P) {} + static void PassEnded(Pass *P) {} + // getPMName() - Return the name of the unit the PassManager operates on for // debugging. const char *getPMName() const { return "Function"; } @@ -465,10 +511,37 @@ template<> struct PassManagerTraits : public Pass { // debugging. const char *getPMName() const { return "Module"; } - // run - Implement the Pass interface... + // TimingInformation - This data member maintains timing information for each + // of the passes that is executed. + // + TimingInfo *TimeInfo; + + // PassStarted/Ended - This callback is notified any time a pass is started + // or stops. This is used to collect timing information about the different + // passes being executed. + // + void PassStarted(Pass *P) { + if (TimeInfo) TimeInfo->passStarted(P); + } + void PassEnded(Pass *P) { + if (TimeInfo) TimeInfo->passEnded(P); + } + + // run - Implement the PassManager interface... bool run(Module *M) { - return ((PassManagerT*)this)->runOnUnit(M); + TimeInfo = TimingInfo::create(); + bool Result = ((PassManagerT*)this)->runOnUnit(M); + if (TimeInfo) { + delete TimeInfo; + TimeInfo = 0; + } + return Result; } + + // PassManagerTraits constructor - Create a timing info object if the user + // specified timing info should be collected on the command line. + // + PassManagerTraits() : TimeInfo(0) {} }; -- 2.34.1