mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
46990c17f7
must be called in the pass's constructor. This function uses static dependency declarations to recursively initialize the pass's dependencies. Clients that only create passes through the createFooPass() APIs will require no changes. Clients that want to use the CommandLine options for passes will need to manually call the appropriate initialization functions in PassInitialization.h before parsing commandline arguments. I have tested this with all standard configurations of clang and llvm-gcc on Darwin. It is possible that there are problems with the static dependencies that will only be visible with non-standard options. If you encounter any crash in pass registration/creation, please send the testcase to me directly. llvm-svn: 116820
268 lines
9.3 KiB
C++
268 lines
9.3 KiB
C++
//===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements a concrete implementation of profiling information that
|
|
// loads the information from a profile dump file.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#define DEBUG_TYPE "profile-loader"
|
|
#include "llvm/BasicBlock.h"
|
|
#include "llvm/InstrTypes.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Analysis/Passes.h"
|
|
#include "llvm/Analysis/ProfileInfo.h"
|
|
#include "llvm/Analysis/ProfileInfoLoader.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/CFG.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/Format.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/ADT/SmallSet.h"
|
|
#include <set>
|
|
using namespace llvm;
|
|
|
|
STATISTIC(NumEdgesRead, "The # of edges read.");
|
|
|
|
static cl::opt<std::string>
|
|
ProfileInfoFilename("profile-info-file", cl::init("llvmprof.out"),
|
|
cl::value_desc("filename"),
|
|
cl::desc("Profile file loaded by -profile-loader"));
|
|
|
|
namespace {
|
|
class LoaderPass : public ModulePass, public ProfileInfo {
|
|
std::string Filename;
|
|
std::set<Edge> SpanningTree;
|
|
std::set<const BasicBlock*> BBisUnvisited;
|
|
unsigned ReadCount;
|
|
public:
|
|
static char ID; // Class identification, replacement for typeinfo
|
|
explicit LoaderPass(const std::string &filename = "")
|
|
: ModulePass(ID), Filename(filename) {
|
|
initializeLoaderPassPass(*PassRegistry::getPassRegistry());
|
|
if (filename.empty()) Filename = ProfileInfoFilename;
|
|
}
|
|
|
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.setPreservesAll();
|
|
}
|
|
|
|
virtual const char *getPassName() const {
|
|
return "Profiling information loader";
|
|
}
|
|
|
|
// recurseBasicBlock() - Calculates the edge weights for as much basic
|
|
// blocks as possbile.
|
|
virtual void recurseBasicBlock(const BasicBlock *BB);
|
|
virtual void readEdgeOrRemember(Edge, Edge&, unsigned &, double &);
|
|
virtual void readEdge(ProfileInfo::Edge, std::vector<unsigned>&);
|
|
|
|
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
|
/// an analysis interface through multiple inheritance. If needed, it
|
|
/// should override this to adjust the this pointer as needed for the
|
|
/// specified pass info.
|
|
virtual void *getAdjustedAnalysisPointer(AnalysisID PI) {
|
|
if (PI == &ProfileInfo::ID)
|
|
return (ProfileInfo*)this;
|
|
return this;
|
|
}
|
|
|
|
/// run - Load the profile information from the specified file.
|
|
virtual bool runOnModule(Module &M);
|
|
};
|
|
} // End of anonymous namespace
|
|
|
|
char LoaderPass::ID = 0;
|
|
INITIALIZE_AG_PASS(LoaderPass, ProfileInfo, "profile-loader",
|
|
"Load profile information from llvmprof.out", false, true, false)
|
|
|
|
char &llvm::ProfileLoaderPassID = LoaderPass::ID;
|
|
|
|
ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); }
|
|
|
|
/// createProfileLoaderPass - This function returns a Pass that loads the
|
|
/// profiling information for the module from the specified filename, making it
|
|
/// available to the optimizers.
|
|
Pass *llvm::createProfileLoaderPass(const std::string &Filename) {
|
|
return new LoaderPass(Filename);
|
|
}
|
|
|
|
void LoaderPass::readEdgeOrRemember(Edge edge, Edge &tocalc,
|
|
unsigned &uncalc, double &count) {
|
|
double w;
|
|
if ((w = getEdgeWeight(edge)) == MissingValue) {
|
|
tocalc = edge;
|
|
uncalc++;
|
|
} else {
|
|
count+=w;
|
|
}
|
|
}
|
|
|
|
// recurseBasicBlock - Visits all neighbours of a block and then tries to
|
|
// calculate the missing edge values.
|
|
void LoaderPass::recurseBasicBlock(const BasicBlock *BB) {
|
|
|
|
// break recursion if already visited
|
|
if (BBisUnvisited.find(BB) == BBisUnvisited.end()) return;
|
|
BBisUnvisited.erase(BB);
|
|
if (!BB) return;
|
|
|
|
for (succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
|
bbi != bbe; ++bbi) {
|
|
recurseBasicBlock(*bbi);
|
|
}
|
|
for (const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
|
bbi != bbe; ++bbi) {
|
|
recurseBasicBlock(*bbi);
|
|
}
|
|
|
|
Edge tocalc;
|
|
if (CalculateMissingEdge(BB, tocalc)) {
|
|
SpanningTree.erase(tocalc);
|
|
}
|
|
}
|
|
|
|
void LoaderPass::readEdge(ProfileInfo::Edge e,
|
|
std::vector<unsigned> &ECs) {
|
|
if (ReadCount < ECs.size()) {
|
|
double weight = ECs[ReadCount++];
|
|
if (weight != ProfileInfoLoader::Uncounted) {
|
|
// Here the data realm changes from the unsigned of the file to the
|
|
// double of the ProfileInfo. This conversion is save because we know
|
|
// that everything thats representable in unsinged is also representable
|
|
// in double.
|
|
EdgeInformation[getFunction(e)][e] += (double)weight;
|
|
|
|
DEBUG(dbgs() << "--Read Edge Counter for " << e
|
|
<< " (# "<< (ReadCount-1) << "): "
|
|
<< (unsigned)getEdgeWeight(e) << "\n");
|
|
} else {
|
|
// This happens only if reading optimal profiling information, not when
|
|
// reading regular profiling information.
|
|
SpanningTree.insert(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool LoaderPass::runOnModule(Module &M) {
|
|
ProfileInfoLoader PIL("profile-loader", Filename, M);
|
|
|
|
EdgeInformation.clear();
|
|
std::vector<unsigned> Counters = PIL.getRawEdgeCounts();
|
|
if (Counters.size() > 0) {
|
|
ReadCount = 0;
|
|
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
|
if (F->isDeclaration()) continue;
|
|
DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
|
|
readEdge(getEdge(0,&F->getEntryBlock()), Counters);
|
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
|
TerminatorInst *TI = BB->getTerminator();
|
|
for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
|
|
readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
|
|
}
|
|
}
|
|
}
|
|
if (ReadCount != Counters.size()) {
|
|
errs() << "WARNING: profile information is inconsistent with "
|
|
<< "the current program!\n";
|
|
}
|
|
NumEdgesRead = ReadCount;
|
|
}
|
|
|
|
Counters = PIL.getRawOptimalEdgeCounts();
|
|
if (Counters.size() > 0) {
|
|
ReadCount = 0;
|
|
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
|
if (F->isDeclaration()) continue;
|
|
DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n");
|
|
readEdge(getEdge(0,&F->getEntryBlock()), Counters);
|
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
|
TerminatorInst *TI = BB->getTerminator();
|
|
if (TI->getNumSuccessors() == 0) {
|
|
readEdge(getEdge(BB,0), Counters);
|
|
}
|
|
for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) {
|
|
readEdge(getEdge(BB,TI->getSuccessor(s)), Counters);
|
|
}
|
|
}
|
|
while (SpanningTree.size() > 0) {
|
|
|
|
unsigned size = SpanningTree.size();
|
|
|
|
BBisUnvisited.clear();
|
|
for (std::set<Edge>::iterator ei = SpanningTree.begin(),
|
|
ee = SpanningTree.end(); ei != ee; ++ei) {
|
|
BBisUnvisited.insert(ei->first);
|
|
BBisUnvisited.insert(ei->second);
|
|
}
|
|
while (BBisUnvisited.size() > 0) {
|
|
recurseBasicBlock(*BBisUnvisited.begin());
|
|
}
|
|
|
|
if (SpanningTree.size() == size) {
|
|
DEBUG(dbgs()<<"{");
|
|
for (std::set<Edge>::iterator ei = SpanningTree.begin(),
|
|
ee = SpanningTree.end(); ei != ee; ++ei) {
|
|
DEBUG(dbgs()<< *ei <<",");
|
|
}
|
|
assert(0 && "No edge calculated!");
|
|
}
|
|
|
|
}
|
|
}
|
|
if (ReadCount != Counters.size()) {
|
|
errs() << "WARNING: profile information is inconsistent with "
|
|
<< "the current program!\n";
|
|
}
|
|
NumEdgesRead = ReadCount;
|
|
}
|
|
|
|
BlockInformation.clear();
|
|
Counters = PIL.getRawBlockCounts();
|
|
if (Counters.size() > 0) {
|
|
ReadCount = 0;
|
|
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
|
if (F->isDeclaration()) continue;
|
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
|
if (ReadCount < Counters.size())
|
|
// Here the data realm changes from the unsigned of the file to the
|
|
// double of the ProfileInfo. This conversion is save because we know
|
|
// that everything thats representable in unsinged is also
|
|
// representable in double.
|
|
BlockInformation[F][BB] = (double)Counters[ReadCount++];
|
|
}
|
|
if (ReadCount != Counters.size()) {
|
|
errs() << "WARNING: profile information is inconsistent with "
|
|
<< "the current program!\n";
|
|
}
|
|
}
|
|
|
|
FunctionInformation.clear();
|
|
Counters = PIL.getRawFunctionCounts();
|
|
if (Counters.size() > 0) {
|
|
ReadCount = 0;
|
|
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
|
if (F->isDeclaration()) continue;
|
|
if (ReadCount < Counters.size())
|
|
// Here the data realm changes from the unsigned of the file to the
|
|
// double of the ProfileInfo. This conversion is save because we know
|
|
// that everything thats representable in unsinged is also
|
|
// representable in double.
|
|
FunctionInformation[F] = (double)Counters[ReadCount++];
|
|
}
|
|
if (ReadCount != Counters.size()) {
|
|
errs() << "WARNING: profile information is inconsistent with "
|
|
<< "the current program!\n";
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|