mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-17 05:29:24 +00:00
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:
parent
63f824ce18
commit
691fa3cfb1
@ -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
|
||||
|
@ -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) {}
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user