mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	Luis Felipe Strano Moraes! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129558 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			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 doesn'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;
 | |
| }
 |