1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/lib/Analysis/ProfileInfoLoaderPass.cpp
Chandler Carruth 4c1f3c24db Move all of the header files which are involved in modelling the LLVM IR
into their new header subdirectory: include/llvm/IR. This matches the
directory structure of lib, and begins to correct a long standing point
of file layout clutter in LLVM.

There are still more header files to move here, but I wanted to handle
them in separate commits to make tracking what files make sense at each
layer easier.

The only really questionable files here are the target intrinsic
tablegen files. But that's a battle I'd rather not fight today.

I've updated both CMake and Makefile build systems (I think, and my
tests think, but I may have missed something).

I've also re-sorted the includes throughout the project. I'll be
committing updates to Clang, DragonEgg, and Polly momentarily.

llvm-svn: 171366
2013-01-02 11:36:10 +00:00

269 lines
9.5 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/Analysis/Passes.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ProfileInfo.h"
#include "llvm/Analysis/ProfileInfoLoader.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.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);
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->getName() << "\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()) {
M.getContext().emitWarning("profile information is inconsistent "
"with the current program");
}
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->getName() << "\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()) {
M.getContext().emitWarning("profile information is inconsistent "
"with the current program");
}
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()) {
M.getContext().emitWarning("profile information is inconsistent "
"with the current program");
}
}
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()) {
M.getContext().emitWarning("profile information is inconsistent "
"with the current program");
}
}
return false;
}