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
This commit is contained in:
Chris Lattner 2002-04-29 04:04:29 +00:00
parent 63f824ce18
commit 691fa3cfb1
2 changed files with 145 additions and 12 deletions

View File

@ -15,6 +15,8 @@
#include "Support/CommandLine.h"
#include <typeinfo>
#include <iostream>
#include <sys/time.h>
#include <stdio.h>
// 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<pair<double, Pass*> > Data;
double TotalTime = 0;
for (std::map<Pass*, double>::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));
TotalTime += I->second;
}
// Sort the data by time as the primary key, in reverse order...
std::sort(Data.begin(), Data.end(), greater<pair<double, Pass*> >());
// 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

View File

@ -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<Pass*, double> 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 UnitType> class PassManagerTraits; // Do not define.
//
template<typename UnitType>
class PassManagerT : public PassManagerTraits<UnitType>,public AnalysisResolver{
typedef typename PassManagerTraits<UnitType>::PassClass PassClass;
typedef typename PassManagerTraits<UnitType>::SubPassClass SubPassClass;
typedef typename PassManagerTraits<UnitType>::BatcherClass BatcherClass;
typedef typename PassManagerTraits<UnitType>::ParentClass ParentClass;
typedef PassManagerTraits<UnitType> Traits;
typedef PassManagerTraits<UnitType> Traits;
typedef typename Traits::PassClass PassClass;
typedef typename Traits::SubPassClass SubPassClass;
typedef typename Traits::BatcherClass BatcherClass;
typedef typename Traits::ParentClass ParentClass;
friend typename PassManagerTraits<UnitType>::PassClass;
friend typename PassManagerTraits<UnitType>::SubPassClass;
friend class PassManagerTraits<UnitType>;
friend typename Traits::PassClass;
friend typename Traits::SubPassClass;
friend class Traits;
std::vector<PassClass*> 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<BasicBlock> : 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<Function> : 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<Module> : public Pass {
// debugging.
const char *getPMName() const { return "Module"; }
// run - Implement the Pass interface...
bool run(Module *M) {
return ((PassManagerT<Module>*)this)->runOnUnit(M);
// 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) {
TimeInfo = TimingInfo::create();
bool Result = ((PassManagerT<Module>*)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) {}
};