mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-23 15:29:51 +00:00
208 lines
6.9 KiB
C++
208 lines
6.9 KiB
C++
|
//===- PathProfileVerifier.cpp --------------------------------*- C++ -*---===//
|
||
|
//
|
||
|
// The LLVM Compiler Infrastructure
|
||
|
//
|
||
|
// This file is distributed under the University of Illinois Open Source
|
||
|
// License. See LICENSE.TXT for details.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// This verifier derives an edge profile file from current path profile
|
||
|
// information
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
#define DEBUG_TYPE "path-profile-verifier"
|
||
|
|
||
|
#include "llvm/Module.h"
|
||
|
#include "llvm/Pass.h"
|
||
|
#include "llvm/Analysis/Passes.h"
|
||
|
#include "llvm/Analysis/ProfileInfoTypes.h"
|
||
|
#include "llvm/Analysis/PathProfileInfo.h"
|
||
|
#include "llvm/Support/Debug.h"
|
||
|
#include "llvm/Support/CommandLine.h"
|
||
|
#include "llvm/Support/raw_ostream.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
using namespace llvm;
|
||
|
|
||
|
namespace {
|
||
|
class PathProfileVerifier : public ModulePass {
|
||
|
private:
|
||
|
bool runOnModule(Module &M);
|
||
|
|
||
|
public:
|
||
|
static char ID; // Pass identification, replacement for typeid
|
||
|
PathProfileVerifier() : ModulePass(ID) {
|
||
|
initializePathProfileVerifierPass(*PassRegistry::getPassRegistry());
|
||
|
}
|
||
|
|
||
|
|
||
|
virtual const char *getPassName() const {
|
||
|
return "Path Profiler Verifier";
|
||
|
}
|
||
|
|
||
|
// The verifier requires the path profile and edge profile.
|
||
|
virtual void getAnalysisUsage(AnalysisUsage& AU) const;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
static cl::opt<std::string>
|
||
|
EdgeProfileFilename("path-profile-verifier-file",
|
||
|
cl::init("edgefrompath.llvmprof.out"),
|
||
|
cl::value_desc("filename"),
|
||
|
cl::desc("Edge profile file generated by -path-profile-verifier"),
|
||
|
cl::Hidden);
|
||
|
|
||
|
char PathProfileVerifier::ID = 0;
|
||
|
INITIALIZE_PASS(PathProfileVerifier, "path-profile-verifier",
|
||
|
"Compare the path profile derived edge profile against the "
|
||
|
"edge profile.", true, true)
|
||
|
|
||
|
ModulePass *llvm::createPathProfileVerifierPass() {
|
||
|
return new PathProfileVerifier();
|
||
|
}
|
||
|
|
||
|
// The verifier requires the path profile and edge profile.
|
||
|
void PathProfileVerifier::getAnalysisUsage(AnalysisUsage& AU) const {
|
||
|
AU.addRequired<PathProfileInfo>();
|
||
|
AU.addPreserved<PathProfileInfo>();
|
||
|
}
|
||
|
|
||
|
typedef std::map<unsigned, unsigned> DuplicateToIndexMap;
|
||
|
typedef std::map<BasicBlock*,DuplicateToIndexMap> BlockToDuplicateMap;
|
||
|
typedef std::map<BasicBlock*,BlockToDuplicateMap> NestedBlockToIndexMap;
|
||
|
|
||
|
// the verifier iterates through each path to gather the total
|
||
|
// number of edge frequencies
|
||
|
bool PathProfileVerifier::runOnModule (Module &M) {
|
||
|
PathProfileInfo& pathProfileInfo = getAnalysis<PathProfileInfo>();
|
||
|
|
||
|
// setup a data structure to map path edges which index an
|
||
|
// array of edge counters
|
||
|
NestedBlockToIndexMap arrayMap;
|
||
|
unsigned i = 0;
|
||
|
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
||
|
if (F->isDeclaration()) continue;
|
||
|
|
||
|
arrayMap[0][F->begin()][0] = i++;
|
||
|
|
||
|
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
|
||
|
TerminatorInst *TI = BB->getTerminator();
|
||
|
|
||
|
unsigned duplicate = 0;
|
||
|
BasicBlock* prev = 0;
|
||
|
for (unsigned s = 0, e = TI->getNumSuccessors(); s != e;
|
||
|
prev = TI->getSuccessor(s), ++s) {
|
||
|
if (prev == TI->getSuccessor(s))
|
||
|
duplicate++;
|
||
|
else duplicate = 0;
|
||
|
|
||
|
arrayMap[BB][TI->getSuccessor(s)][duplicate] = i++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::vector<unsigned> edgeArray(i);
|
||
|
|
||
|
// iterate through each path and increment the edge counters as needed
|
||
|
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
||
|
if (F->isDeclaration()) continue;
|
||
|
|
||
|
pathProfileInfo.setCurrentFunction(F);
|
||
|
|
||
|
DEBUG(dbgs() << "function '" << F->getName() << "' ran "
|
||
|
<< pathProfileInfo.pathsRun()
|
||
|
<< "/" << pathProfileInfo.getPotentialPathCount()
|
||
|
<< " potential paths\n");
|
||
|
|
||
|
for( ProfilePathIterator nextPath = pathProfileInfo.pathBegin(),
|
||
|
endPath = pathProfileInfo.pathEnd();
|
||
|
nextPath != endPath; nextPath++ ) {
|
||
|
ProfilePath* currentPath = nextPath->second;
|
||
|
|
||
|
ProfilePathEdgeVector* pev = currentPath->getPathEdges();
|
||
|
DEBUG(dbgs () << "path #" << currentPath->getNumber() << ": "
|
||
|
<< currentPath->getCount() << "\n");
|
||
|
// setup the entry edge (normally path profiling doens't care about this)
|
||
|
if (currentPath->getFirstBlockInPath() == &F->getEntryBlock())
|
||
|
edgeArray[arrayMap[0][currentPath->getFirstBlockInPath()][0]]
|
||
|
+= currentPath->getCount();
|
||
|
|
||
|
for( ProfilePathEdgeIterator nextEdge = pev->begin(),
|
||
|
endEdge = pev->end(); nextEdge != endEdge; nextEdge++ ) {
|
||
|
if (nextEdge != pev->begin())
|
||
|
DEBUG(dbgs() << " :: ");
|
||
|
|
||
|
BasicBlock* source = nextEdge->getSource();
|
||
|
BasicBlock* target = nextEdge->getTarget();
|
||
|
unsigned duplicateNumber = nextEdge->getDuplicateNumber();
|
||
|
DEBUG(dbgs () << source->getNameStr() << " --{" << duplicateNumber
|
||
|
<< "}--> " << target->getNameStr());
|
||
|
|
||
|
// Ensure all the referenced edges exist
|
||
|
// TODO: make this a separate function
|
||
|
if( !arrayMap.count(source) ) {
|
||
|
errs() << " error [" << F->getNameStr() << "()]: source '"
|
||
|
<< source->getNameStr()
|
||
|
<< "' does not exist in the array map.\n";
|
||
|
} else if( !arrayMap[source].count(target) ) {
|
||
|
errs() << " error [" << F->getNameStr() << "()]: target '"
|
||
|
<< target->getNameStr()
|
||
|
<< "' does not exist in the array map.\n";
|
||
|
} else if( !arrayMap[source][target].count(duplicateNumber) ) {
|
||
|
errs() << " error [" << F->getNameStr() << "()]: edge "
|
||
|
<< source->getNameStr() << " -> " << target->getNameStr()
|
||
|
<< " duplicate number " << duplicateNumber
|
||
|
<< " does not exist in the array map.\n";
|
||
|
} else {
|
||
|
edgeArray[arrayMap[source][target][duplicateNumber]]
|
||
|
+= currentPath->getCount();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DEBUG(errs() << "\n");
|
||
|
|
||
|
delete pev;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
std::string errorInfo;
|
||
|
std::string filename = EdgeProfileFilename;
|
||
|
|
||
|
// Open a handle to the file
|
||
|
FILE* edgeFile = fopen(filename.c_str(),"wb");
|
||
|
|
||
|
if (!edgeFile) {
|
||
|
errs() << "error: unable to open file '" << filename << "' for output.\n";
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
errs() << "Generating edge profile '" << filename << "' ...\n";
|
||
|
|
||
|
// write argument info
|
||
|
unsigned type = ArgumentInfo;
|
||
|
unsigned num = pathProfileInfo.argList.size();
|
||
|
int zeros = 0;
|
||
|
|
||
|
fwrite(&type,sizeof(unsigned),1,edgeFile);
|
||
|
fwrite(&num,sizeof(unsigned),1,edgeFile);
|
||
|
fwrite(pathProfileInfo.argList.c_str(),1,num,edgeFile);
|
||
|
if (num&3)
|
||
|
fwrite(&zeros, 1, 4-(num&3), edgeFile);
|
||
|
|
||
|
type = EdgeInfo;
|
||
|
num = edgeArray.size();
|
||
|
fwrite(&type,sizeof(unsigned),1,edgeFile);
|
||
|
fwrite(&num,sizeof(unsigned),1,edgeFile);
|
||
|
|
||
|
// write each edge to the file
|
||
|
for( std::vector<unsigned>::iterator s = edgeArray.begin(),
|
||
|
e = edgeArray.end(); s != e; s++)
|
||
|
fwrite(&*s, sizeof (unsigned), 1, edgeFile);
|
||
|
|
||
|
fclose (edgeFile);
|
||
|
|
||
|
return true;
|
||
|
}
|