/// findFunctionScopedAllocas - store all allocas that are known to be valid /// to the end of their function in a set. The current algorithm does this by /// finding all the allocas in the entry block that are before the first /// llvm.stacksave call (if any). /// /// FIXME: There can also be allocas elsewhere that get deallocated at the end /// of the function but they are pessimistically ignored for now. /// void ExactCheckOpt::findFunctionScopedAllocas(Module &M) { for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->empty()) continue; BasicBlock &BB = F->getEntryBlock(); for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I) { if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) { FunctionScopedAllocas.insert(AI); } else if(CallInst *CI = dyn_cast<CallInst>(I)) { Function *CalledFunction = CI->getCalledFunction(); if (CalledFunction && CalledFunction->getName() == "llvm.stacksave") break; } } } }
bool TraceBasicBlocks::runOnModule(Module &M) { Context =&M.getContext(); Function *Main = M.getFunction("main"); if (Main == 0) { errs() << "WARNING: cannot insert basic-block trace instrumentation" << " into a module with no main function!\n"; return false; // No main, no instrumentation! } const char* FnName="llvm_trace_basic_block"; Constant *InstrFn = M.getOrInsertFunction (FnName, Type::getVoidTy(*Context), Type::getInt64Ty(*Context), NULL); unsigned BBNumber = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if(F->empty()) { continue; } //We insert instrumentation calls in reverse order, because insertion puts them before previous instructions for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { dbgs() << "InsertInstrumentationCall (\"" << BB->getName () << "\", \"" << F->getName() << "\", " << BBNumber << ")\n"; //On Exit we emit the FunRet block TerminatorInst* TI=BB->getTerminator(); if(TI->getNumSuccessors()==0) { InsertRetInstrumentationCall(TI,InstrFn); } InsertInstrumentationCall (BB, InstrFn, BBNumber); if(TraceMemory) { InsertMemoryTracingCall (BB,InstrFn); } ++BBNumber; } //on Entry we emit the FunCall block. BasicBlock* EntryBlock=&F->getEntryBlock(); InsertInstrumentationCall (EntryBlock, InstrFn, BBTraceStream::FunCallID); } // Add the initialization call to main. InsertProfilingInitCall(Main, "llvm_start_basic_block_tracing"); return true; }
/// matchEdges - Link every profile counter with an edge. unsigned ProfileMetadataLoaderPass::matchEdges(Module &M, ProfileData &PB, ArrayRef<unsigned> Counters) { if (Counters.size() == 0) return 0; unsigned ReadCount = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; DEBUG(dbgs() << "Loading edges in '" << F->getName() << "'\n"); readEdge(ReadCount++, PB, PB.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(ReadCount++, PB, PB.getEdge(BB,TI->getSuccessor(s)), Counters); } } } return ReadCount; }
bool MLStatic::runOnModule(Module &M) { for(Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; errs()<<"---Running for Function:"<<F->getName()<<"\n"; DT = &getAnalysis<DominatorTree>(*F); BasicBlock *BB = &(F->getEntryBlock()); tracePath(BB); } DEBUG(dbgs()<<"PATH collection Complete\n"); for(Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { for(int i=0;i<pathCollecn2[F].size();++i){ for(int j=0;j<pathCollecn2[F][i].size();++j){ DEBUG(dbgs()<<pathCollecn2[F][i][j]->getName()<<" "); } DEBUG(dbgs()<<"\n"); } } expandPathAll(M); return false; }
bool PrintFunctionNames::runOnModule(Module &M) { errs() << "Pass PrintFunctionNames\n"; // iterating through functions for(Module::iterator f = M.begin(), fe = M.end(); f != fe; f++) { if (!f->isDeclaration()) { // finding and printing file information BasicBlock &block = f->getEntryBlock(); Instruction &inst = block.front(); if (MDNode *node = inst.getMetadata("dbg")) { DILocation loc(node); errs() << "File name: " << loc.getFilename() << "\t"; } } // finding and printing function informatonion errs() << "Function name: " << f->getName() << "\n"; } return false; }
bool OptimalEdgeProfiler::runOnModule(Module &M) { Function *Main = M.getFunction("main"); if (Main == 0) { errs() << "WARNING: cannot insert edge profiling into a module" << " with no main function!\n"; return false; // No main, no instrumentation! } // NumEdges counts all the edges that may be instrumented. Later on its // decided which edges to actually instrument, to achieve optimal profiling. // For the entry block a virtual edge (0,entry) is reserved, for each block // with no successors an edge (BB,0) is reserved. These edges are necessary // to calculate a truly optimal maximum spanning tree and thus an optimal // instrumentation. unsigned NumEdges = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; // Reserve space for (0,entry) edge. ++NumEdges; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { // Keep track of which blocks need to be instrumented. We don't want to // instrument blocks that are added as the result of breaking critical // edges! if (BB->getTerminator()->getNumSuccessors() == 0) { // Reserve space for (BB,0) edge. ++NumEdges; } else { NumEdges += BB->getTerminator()->getNumSuccessors(); } } } // In the profiling output a counter for each edge is reserved, but only few // are used. This is done to be able to read back in the profile without // calulating the maximum spanning tree again, instead each edge counter that // is not used is initialised with -1 to signal that this edge counter has to // be calculated from other edge counters on reading the profile info back // in. const Type *Int32 = Type::getInt32Ty(M.getContext()); const ArrayType *ATy = ArrayType::get(Int32, NumEdges); GlobalVariable *Counters = new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage, Constant::getNullValue(ATy), "OptEdgeProfCounters"); NumEdgesInserted = 0; std::vector<Constant*> Initializer(NumEdges); Constant* Zero = ConstantInt::get(Int32, 0); Constant* Uncounted = ConstantInt::get(Int32, ProfileInfoLoader::Uncounted); // Instrument all of the edges not in MST... unsigned i = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; DEBUG(dbgs()<<"Working on "<<F->getNameStr()<<"\n"); // Calculate a Maximum Spanning Tree with the edge weights determined by // ProfileEstimator. ProfileEstimator also assign weights to the virtual // edges (0,entry) and (BB,0) (for blocks with no successors) and this // edges also participate in the maximum spanning tree calculation. // The third parameter of MaximumSpanningTree() has the effect that not the // actual MST is returned but the edges _not_ in the MST. ProfileInfo::EdgeWeights ECs = getAnalysis<ProfileInfo>(*F).getEdgeWeights(F); std::vector<ProfileInfo::EdgeWeight> EdgeVector(ECs.begin(), ECs.end()); MaximumSpanningTree<BasicBlock> MST (EdgeVector); std::stable_sort(MST.begin(),MST.end()); // Check if (0,entry) not in the MST. If not, instrument edge // (IncrementCounterInBlock()) and set the counter initially to zero, if // the edge is in the MST the counter is initialised to -1. BasicBlock *entry = &(F->getEntryBlock()); ProfileInfo::Edge edge = ProfileInfo::getEdge(0,entry); if (!std::binary_search(MST.begin(), MST.end(), edge)) { printEdgeCounter(edge,entry,i); IncrementCounterInBlock(entry, i, Counters); ++NumEdgesInserted; Initializer[i++] = (Zero); } else{ Initializer[i++] = (Uncounted); } // InsertedBlocks contains all blocks that were inserted for splitting an // edge, this blocks do not have to be instrumented. DenseSet<BasicBlock*> InsertedBlocks; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { // Check if block was not inserted and thus does not have to be // instrumented. if (InsertedBlocks.count(BB)) continue; // Okay, we have to add a counter of each outgoing edge not in MST. If // the outgoing edge is not critical don't split it, just insert the // counter in the source or destination of the edge. Also, if the block // has no successors, the virtual edge (BB,0) is processed. TerminatorInst *TI = BB->getTerminator(); if (TI->getNumSuccessors() == 0) { ProfileInfo::Edge edge = ProfileInfo::getEdge(BB,0); if (!std::binary_search(MST.begin(), MST.end(), edge)) { printEdgeCounter(edge,BB,i); IncrementCounterInBlock(BB, i, Counters); ++NumEdgesInserted; Initializer[i++] = (Zero); } else{ Initializer[i++] = (Uncounted); } } for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { BasicBlock *Succ = TI->getSuccessor(s); ProfileInfo::Edge edge = ProfileInfo::getEdge(BB,Succ); if (!std::binary_search(MST.begin(), MST.end(), edge)) { // If the edge is critical, split it. bool wasInserted = SplitCriticalEdge(TI, s, this); Succ = TI->getSuccessor(s); if (wasInserted) InsertedBlocks.insert(Succ); // Okay, we are guaranteed that the edge is no longer critical. If // we only have a single successor, insert the counter in this block, // otherwise insert it in the successor block. if (TI->getNumSuccessors() == 1) { // Insert counter at the start of the block printEdgeCounter(edge,BB,i); IncrementCounterInBlock(BB, i, Counters); ++NumEdgesInserted; } else { // Insert counter at the start of the block printEdgeCounter(edge,Succ,i); IncrementCounterInBlock(Succ, i, Counters); ++NumEdgesInserted; } Initializer[i++] = (Zero); } else { Initializer[i++] = (Uncounted); } } } } // Check if the number of edges counted at first was the number of edges we // considered for instrumentation. assert(i==NumEdges && "the number of edges in counting array is wrong"); // Assing the now completely defined initialiser to the array. Constant *init = ConstantArray::get(ATy, Initializer); Counters->setInitializer(init); // Add the initialization call to main. InsertProfilingInitCall(Main, "llvm_start_opt_edge_profiling", Counters); return true; }
bool EdgeProfiler::runOnModule(Module &M) { Function *Main = M.getFunction("main"); if (Main == 0) { errs() << "WARNING: cannot insert edge profiling into a module" << " with no main function!\n"; return false; // No main, no instrumentation! } std::set<BasicBlock*> BlocksToInstrument; unsigned NumEdges = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; // Reserve space for (0,entry) edge. ++NumEdges; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { // Keep track of which blocks need to be instrumented. We don't want to // instrument blocks that are added as the result of breaking critical // edges! BlocksToInstrument.insert(BB); NumEdges += BB->getTerminator()->getNumSuccessors(); } } Type *ATy = ArrayType::get(Type::getInt32Ty(M.getContext()), NumEdges); GlobalVariable *Counters = new GlobalVariable(M, ATy, false, GlobalValue::InternalLinkage, Constant::getNullValue(ATy), "EdgeProfCounters"); NumEdgesInserted = NumEdges; // Instrument all of the edges... unsigned i = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; // Create counter for (0,entry) edge. IncrementCounterInBlock(&F->getEntryBlock(), i++, Counters); for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) if (BlocksToInstrument.count(BB)) { // Don't instrument inserted blocks // Okay, we have to add a counter of each outgoing edge. If the // outgoing edge is not critical don't split it, just insert the counter // in the source or destination of the edge. TerminatorInst *TI = BB->getTerminator(); for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { // If the edge is critical, split it. SplitCriticalEdge(TI, s, this); // Okay, we are guaranteed that the edge is no longer critical. If we // only have a single successor, insert the counter in this block, // otherwise insert it in the successor block. if (TI->getNumSuccessors() == 1) { // Insert counter at the start of the block IncrementCounterInBlock(BB, i++, Counters, false); } else { // Insert counter at the start of the block IncrementCounterInBlock(TI->getSuccessor(s), i++, Counters); } } } } // Add the initialization call to main. InsertProfilingInitCall(Main, "llvm_start_edge_profiling", Counters); return true; }
bool LoaderPass::runOnModule(Module &M) { ProfileInfoLoader PIL("profile-loader", Filename); EdgeInformation.clear(); std::vector<uint64_t> Counters64 = PIL.getRawEdgeCounts(); if (Counters64.size() > 0) { ReadCount = 0; std::vector<uint64_t>& Counters = Counters64; 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()) { errs() << "WARNING: profile information is inconsistent with " << "the current program!\n"; } NumEdgesRead = ReadCount; } #if 0 std::vector<unsigned> 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()) { errs() << "WARNING: profile information is inconsistent with " << "the current program!\n"; } NumEdgesRead = ReadCount; } #endif BlockInformation.clear(); Counters64 = PIL.getRawBlockCounts(); if (Counters64.size() > 0) { std::vector<uint64_t>& Counters = Counters64; 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(); std::vector<unsigned> 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"; } } ValueInformation.clear(); Counters = PIL.getRawValueCounts(); if(Counters.size() > 0) { ReadCount = 0; for(Module::iterator F = M.begin(),E = M.end(); F!= E; ++F) { if (F->isDeclaration()) continue; for(inst_iterator I = inst_begin(F),IE = inst_end(F); I!=IE; ++I){ CallInst* Call = dyn_cast<CallInst>(&*I); if(!Call) continue; if(Call->getCalledValue()->getName() != "llvm_profiling_trap_value") continue; unsigned index = getTrapedIndex(Call); ValueCounts Ins; Ins.Nums = Counters[index]; const std::vector<int>& content = PIL.getRawValueContent(index); Ins.flags = (ProfilingFlags)content.front(); Ins.Contents.resize(content.size()-1); copy(content.begin()+1,content.end(),Ins.Contents.begin()); //should NOT insert two values into one cell. ValueInformation[Call] = Ins; } } } SLGInformation.clear(); Counters = PIL.getRawSLGCounts(); if(Counters.size() > 0) { unsigned MaxStore = std::accumulate(Counters.begin(), Counters.end(), 0, sig_max); std::vector<const Instruction*> Cache(MaxStore+1); ReadCount = 0; unsigned load_idx = 0, store_idx = 1; for(Module::iterator F = M.begin(), E = M.end(); F!=E; ++F){ for(inst_iterator I = inst_begin(F), IE = inst_end(F); I!=IE; ++I){ if(!isa<StoreInst>(&*I) && !isa<LoadInst>(&*I)) continue; if(lle::access_global_variable(&*I)){ unsigned index = 0; Instruction* SLI = &*I; if(isa<StoreInst>(&*I)){ index = store_idx++; }else if(LoadInst* LI = dyn_cast<LoadInst>(&*I)){ SLGInformation[LI] = std::make_pair(load_idx, (Instruction*)NULL); index = Counters[load_idx++]; if(index == 0 || index == ~0U/*unsigned -1*/){ continue; } } if(index >= Cache.size()) continue; if(Cache[index]){ const Instruction* SLJ = Cache[index]; if(isa<StoreInst>(SLJ) && isa<LoadInst>(SLI)) SLGInformation[SLI].second = SLJ; else if(isa<StoreInst>(SLI) && isa<LoadInst>(SLJ)) SLGInformation[SLJ].second = SLI; else assert(0 && "It shouldn't happen"); }else Cache[index] = &*I; } } } } MPInformation.clear(); Counters = PIL.getRawMPICounts(); if(Counters.size() > 0) { ReadCount = 0; for(auto F = M.begin(), E = M.end(); F!=E; ++F){ for(auto I = inst_begin(F), IE = inst_end(F); I!=IE; ++I){ CallInst* CI = dyn_cast<CallInst>(&*I); if(CI == NULL) continue; if(lle::get_mpi_count_idx(CI)){ MPInformation[CI] = std::make_pair(ReadCount, Counters[ReadCount]); ++ReadCount; } } } } MPIFullInformation.clear(); Counters = PIL.getRawMPIFullCounts(); if(Counters.size() > 0) { ReadCount = 0; for(auto F = M.begin(), E = M.end(); F!=E; ++F){ for(auto I = inst_begin(F), IE = inst_end(F); I!=IE; ++I){ CallInst* CI = dyn_cast<CallInst>(&*I); if(CI == NULL) continue; if(lle::get_mpi_count_idx(CI)){ MPIFullInformation[CI] = std::make_pair(ReadCount, Counters[ReadCount]); ++ReadCount; } } } } return false; }
// 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->getName() << " --{" << duplicateNumber << "}--> " << target->getName()); // Ensure all the referenced edges exist // TODO: make this a separate function if( !arrayMap.count(source) ) { errs() << " error [" << F->getName() << "()]: source '" << source->getName() << "' does not exist in the array map.\n"; } else if( !arrayMap[source].count(target) ) { errs() << " error [" << F->getName() << "()]: target '" << target->getName() << "' does not exist in the array map.\n"; } else if( !arrayMap[source][target].count(duplicateNumber) ) { errs() << " error [" << F->getName() << "()]: edge " << source->getName() << " -> " << target->getName() << " 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; }
bool GenericToNVVM::runOnModule(Module &M) { // Create a clone of each global variable that has the default address space. // The clone is created with the global address space specifier, and the pair // of original global variable and its clone is placed in the GVMap for later // use. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;) { GlobalVariable *GV = &*I++; if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC && !llvm::isTexture(*GV) && !llvm::isSurface(*GV) && !llvm::isSampler(*GV) && !GV->getName().startswith("llvm.")) { GlobalVariable *NewGV = new GlobalVariable( M, GV->getValueType(), GV->isConstant(), GV->getLinkage(), GV->hasInitializer() ? GV->getInitializer() : nullptr, "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL); NewGV->copyAttributesFrom(GV); GVMap[GV] = NewGV; } } // Return immediately, if every global variable has a specific address space // specifier. if (GVMap.empty()) { return false; } // Walk through the instructions in function defitinions, and replace any use // of original global variables in GVMap with a use of the corresponding // copies in GVMap. If necessary, promote constants to instructions. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { if (I->isDeclaration()) { continue; } IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg()); for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE; ++BBI) { for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) { for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i) { Value *Operand = II->getOperand(i); if (isa<Constant>(Operand)) { II->setOperand( i, remapConstant(&M, &*I, cast<Constant>(Operand), Builder)); } } } } ConstantToValueMap.clear(); } // Copy GVMap over to a standard value map. ValueToValueMapTy VM; for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I) VM[I->first] = I->second; // Walk through the metadata section and update the debug information // associated with the global variables in the default address space. for (NamedMDNode &I : M.named_metadata()) { remapNamedMDNode(VM, &I); } // Walk through the global variable initializers, and replace any use of // original global variables in GVMap with a use of the corresponding copies // in GVMap. The copies need to be bitcast to the original global variable // types, as we cannot use cvta in global variable initializers. for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) { GlobalVariable *GV = I->first; GlobalVariable *NewGV = I->second; // Remove GV from the map so that it can be RAUWed. Note that // DenseMap::erase() won't invalidate any iterators but this one. auto Next = std::next(I); GVMap.erase(I); I = Next; Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType()); // At this point, the remaining uses of GV should be found only in global // variable initializers, as other uses have been already been removed // while walking through the instructions in function definitions. GV->replaceAllUsesWith(BitCastNewGV); std::string Name = GV->getName(); GV->eraseFromParent(); NewGV->setName(Name); } assert(GVMap.empty() && "Expected it to be empty by now"); return true; }
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; }
// // Method: runOnModule() // // Description: // Entry point for this LLVM pass. // Clone functions that take LoadInsts as arguments // // Inputs: // M - A reference to the LLVM module to transform // // Outputs: // M - The transformed LLVM module. // // Return value: // true - The module was modified. // false - The module was not modified. // bool LoadArgs::runOnModule(Module& M) { std::map<std::pair<Function*, const Type * > , Function* > fnCache; bool changed; do { changed = false; for (Module::iterator Func = M.begin(); Func != M.end(); ++Func) { for (Function::iterator B = Func->begin(), FE = Func->end(); B != FE; ++B) { for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { CallInst *CI = dyn_cast<CallInst>(I++); if(!CI) continue; if(CI->hasByValArgument()) continue; // if the CallInst calls a function, that is externally defined, // or might be changed, ignore this call site. Function *F = CI->getCalledFunction(); if (!F || (F->isDeclaration() || F->mayBeOverridden())) continue; if(F->hasStructRetAttr()) continue; if(F->isVarArg()) continue; // find the argument we must replace Function::arg_iterator ai = F->arg_begin(), ae = F->arg_end(); unsigned argNum = 0; for(; argNum < CI->getNumArgOperands();argNum++, ++ai) { // do not care about dead arguments if(ai->use_empty()) continue; if(F->getAttributes().getParamAttributes(argNum).hasAttrSomewhere(Attribute::SExt) || F->getAttributes().getParamAttributes(argNum).hasAttrSomewhere(Attribute::ZExt)) continue; if (isa<LoadInst>(CI->getArgOperand(argNum))) break; } // if no argument was a GEP operator to be changed if(ai == ae) continue; LoadInst *LI = dyn_cast<LoadInst>(CI->getArgOperand(argNum)); Instruction * InsertPt = &(Func->getEntryBlock().front()); AllocaInst *NewVal = new AllocaInst(LI->getType(), "",InsertPt); StoreInst *Copy = new StoreInst(LI, NewVal); Copy->insertAfter(LI); /*if(LI->getParent() != CI->getParent()) continue; // Also check that there is no store after the load. // TODO: Check if the load/store do not alias. BasicBlock::iterator bii = LI->getParent()->begin(); Instruction *BII = bii; while(BII != LI) { ++bii; BII = bii; } while(BII != CI) { if(isa<StoreInst>(BII)) break; ++bii; BII = bii; } if(isa<StoreInst>(bii)){ continue; }*/ // Construct the new Type // Appends the struct Type at the beginning std::vector<Type*>TP; for(unsigned c = 0; c < CI->getNumArgOperands();c++) { if(c == argNum) TP.push_back(LI->getPointerOperand()->getType()); TP.push_back(CI->getArgOperand(c)->getType()); } //return type is same as that of original instruction FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); numSimplified++; //if(numSimplified > 1000) //return true; Function *NewF; std::map<std::pair<Function*, const Type* > , Function* >::iterator Test; Test = fnCache.find(std::make_pair(F, NewFTy)); if(Test != fnCache.end()) { NewF = Test->second; } else { NewF = Function::Create(NewFTy, GlobalValue::InternalLinkage, F->getName().str() + ".TEST", &M); fnCache[std::make_pair(F, NewFTy)] = NewF; Function::arg_iterator NI = NewF->arg_begin(); ValueToValueMapTy ValueMap; unsigned count = 0; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++count, ++NI) { if(count == argNum) { NI->setName("LDarg"); continue; } ValueMap[II] = NI; NI->setName(II->getName()); NI->addAttr(F->getAttributes().getParamAttributes(II->getArgNo() + 1)); ++II; } // Perform the cloning. SmallVector<ReturnInst*,100> Returns; CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector<Value*> fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { fargs.push_back(ai); } NewF->setAttributes(NewF->getAttributes().addAttributes( F->getContext(), 0, F->getAttributes().getRetAttributes())); NewF->setAttributes(NewF->getAttributes().addAttributes( F->getContext(), ~0, F->getAttributes().getFnAttributes())); //Get the point to insert the GEP instr. Instruction *InsertPoint; for (BasicBlock::iterator insrt = NewF->front().begin(); isa<AllocaInst>(InsertPoint = insrt); ++insrt) {;} LoadInst *LI_new = new LoadInst(fargs.at(argNum), "", InsertPoint); fargs.at(argNum+1)->replaceAllUsesWith(LI_new); } //this does not seem to be a good idea AttributeSet NewCallPAL=AttributeSet(); // Get the initial attributes of the call AttributeSet CallPAL = CI->getAttributes(); AttributeSet RAttrs = CallPAL.getRetAttributes(); AttributeSet FnAttrs = CallPAL.getFnAttributes(); if (!RAttrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),0, RAttrs); SmallVector<Value*, 8> Args; for(unsigned j =0;j<CI->getNumArgOperands();j++) { if(j == argNum) { Args.push_back(NewVal); } Args.push_back(CI->getArgOperand(j)); // position in the NewCallPAL AttributeSet Attrs = CallPAL.getParamAttributes(j+1); if (!Attrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),Args.size(), Attrs); } // Create the new attributes vec. if (!FnAttrs.isEmpty()) NewCallPAL=NewCallPAL.addAttributes(F->getContext(),~0, FnAttrs); CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); CI->eraseFromParent(); changed = true; } } } } while(changed); return true; }
bool LoaderPass::runOnModule(Module &M) { ProfileInfoLoader PIL("profile-loader", Filename, M); EdgeInformation.clear(); std::vector<unsigned> ECs = PIL.getRawEdgeCounts(); if (ECs.size() > 0) { unsigned ei = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; if (ei < ECs.size()) EdgeInformation[F][ProfileInfo::getEdge(0, &F->getEntryBlock())] += ECs[ei++]; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { // Okay, we have to add a counter of each outgoing edge. If the // outgoing edge is not critical don't split it, just insert the counter // in the source or destination of the edge. TerminatorInst *TI = BB->getTerminator(); for (unsigned s = 0, e = TI->getNumSuccessors(); s != e; ++s) { if (ei < ECs.size()) EdgeInformation[F][ProfileInfo::getEdge(BB, TI->getSuccessor(s))] += ECs[ei++]; } } } if (ei != ECs.size()) { cerr << "WARNING: profile information is inconsistent with " << "the current program!\n"; } } BlockInformation.clear(); std::vector<unsigned> BCs = PIL.getRawBlockCounts(); if (BCs.size() > 0) { unsigned bi = 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 (bi < BCs.size()) BlockInformation[F][BB] = BCs[bi++]; } if (bi != BCs.size()) { cerr << "WARNING: profile information is inconsistent with " << "the current program!\n"; } } FunctionInformation.clear(); std::vector<unsigned> FCs = PIL.getRawFunctionCounts(); if (FCs.size() > 0) { unsigned fi = 0; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->isDeclaration()) continue; if (fi < FCs.size()) FunctionInformation[F] = FCs[fi++]; } if (fi != FCs.size()) { cerr << "WARNING: profile information is inconsistent with " << "the current program!\n"; } } return false; }