diff options
Diffstat (limited to 'lib/Transforms/Instrumentation/GCOVProfiling.cpp')
-rw-r--r-- | lib/Transforms/Instrumentation/GCOVProfiling.cpp | 286 |
1 files changed, 139 insertions, 147 deletions
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp index ffde7f8d9bae..b4070b602768 100644 --- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -14,7 +14,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Instrumentation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" @@ -35,6 +34,8 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/GCOVProfiler.h" +#include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include <algorithm> #include <memory> @@ -68,86 +69,93 @@ GCOVOptions GCOVOptions::getDefault() { } namespace { - class GCOVFunction; +class GCOVFunction; + +class GCOVProfiler { +public: + GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {} + GCOVProfiler(const GCOVOptions &Opts) : Options(Opts) { + assert((Options.EmitNotes || Options.EmitData) && + "GCOVProfiler asked to do nothing?"); + ReversedVersion[0] = Options.Version[3]; + ReversedVersion[1] = Options.Version[2]; + ReversedVersion[2] = Options.Version[1]; + ReversedVersion[3] = Options.Version[0]; + ReversedVersion[4] = '\0'; + } + bool runOnModule(Module &M); + +private: + // Create the .gcno files for the Module based on DebugInfo. + void emitProfileNotes(); + + // Modify the program to track transitions along edges and call into the + // profiling runtime to emit .gcda files when run. + bool emitProfileArcs(); + + // Get pointers to the functions in the runtime library. + Constant *getStartFileFunc(); + Constant *getIncrementIndirectCounterFunc(); + Constant *getEmitFunctionFunc(); + Constant *getEmitArcsFunc(); + Constant *getSummaryInfoFunc(); + Constant *getEndFileFunc(); + + // Create or retrieve an i32 state value that is used to represent the + // pred block number for certain non-trivial edges. + GlobalVariable *getEdgeStateValue(); + + // Produce a table of pointers to counters, by predecessor and successor + // block number. + GlobalVariable *buildEdgeLookupTable(Function *F, GlobalVariable *Counter, + const UniqueVector<BasicBlock *> &Preds, + const UniqueVector<BasicBlock *> &Succs); + + // Add the function to write out all our counters to the global destructor + // list. + Function * + insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); + Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); + void insertIndirectCounterIncrement(); + + std::string mangleName(const DICompileUnit *CU, const char *NewStem); - class GCOVProfiler : public ModulePass { - public: - static char ID; - GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {} - GCOVProfiler(const GCOVOptions &Opts) : ModulePass(ID), Options(Opts) { - assert((Options.EmitNotes || Options.EmitData) && - "GCOVProfiler asked to do nothing?"); - ReversedVersion[0] = Options.Version[3]; - ReversedVersion[1] = Options.Version[2]; - ReversedVersion[2] = Options.Version[1]; - ReversedVersion[3] = Options.Version[0]; - ReversedVersion[4] = '\0'; - initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); - } - const char *getPassName() const override { - return "GCOV Profiler"; - } + GCOVOptions Options; - private: - bool runOnModule(Module &M) override; - - // Create the .gcno files for the Module based on DebugInfo. - void emitProfileNotes(); - - // Modify the program to track transitions along edges and call into the - // profiling runtime to emit .gcda files when run. - bool emitProfileArcs(); - - // Get pointers to the functions in the runtime library. - Constant *getStartFileFunc(); - Constant *getIncrementIndirectCounterFunc(); - Constant *getEmitFunctionFunc(); - Constant *getEmitArcsFunc(); - Constant *getSummaryInfoFunc(); - Constant *getDeleteWriteoutFunctionListFunc(); - Constant *getDeleteFlushFunctionListFunc(); - Constant *getEndFileFunc(); - - // Create or retrieve an i32 state value that is used to represent the - // pred block number for certain non-trivial edges. - GlobalVariable *getEdgeStateValue(); - - // Produce a table of pointers to counters, by predecessor and successor - // block number. - GlobalVariable *buildEdgeLookupTable(Function *F, - GlobalVariable *Counter, - const UniqueVector<BasicBlock *>&Preds, - const UniqueVector<BasicBlock*>&Succs); - - // Add the function to write out all our counters to the global destructor - // list. - Function *insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*, - MDNode*> >); - Function *insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >); - void insertIndirectCounterIncrement(); - - std::string mangleName(const DICompileUnit *CU, const char *NewStem); - - GCOVOptions Options; - - // Reversed, NUL-terminated copy of Options.Version. - char ReversedVersion[5]; - // Checksum, produced by hash of EdgeDestinations - SmallVector<uint32_t, 4> FileChecksums; - - Module *M; - LLVMContext *Ctx; - SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs; - DenseMap<DISubprogram *, Function *> FnMap; - }; + // Reversed, NUL-terminated copy of Options.Version. + char ReversedVersion[5]; + // Checksum, produced by hash of EdgeDestinations + SmallVector<uint32_t, 4> FileChecksums; + + Module *M; + LLVMContext *Ctx; + SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs; +}; + +class GCOVProfilerLegacyPass : public ModulePass { +public: + static char ID; + GCOVProfilerLegacyPass() + : GCOVProfilerLegacyPass(GCOVOptions::getDefault()) {} + GCOVProfilerLegacyPass(const GCOVOptions &Opts) + : ModulePass(ID), Profiler(Opts) { + initializeGCOVProfilerLegacyPassPass(*PassRegistry::getPassRegistry()); + } + const char *getPassName() const override { return "GCOV Profiler"; } + + bool runOnModule(Module &M) override { return Profiler.runOnModule(M); } + +private: + GCOVProfiler Profiler; +}; } -char GCOVProfiler::ID = 0; -INITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling", +char GCOVProfilerLegacyPass::ID = 0; +INITIALIZE_PASS(GCOVProfilerLegacyPass, "insert-gcov-profiling", "Insert instrumentation for GCOV profiling", false, false) ModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) { - return new GCOVProfiler(Options); + return new GCOVProfilerLegacyPass(Options); } static StringRef getFunctionName(const DISubprogram *SP) { @@ -257,10 +265,9 @@ namespace { void writeOut() { uint32_t Len = 3; SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile; - for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(), - E = LinesByFile.end(); I != E; ++I) { - Len += I->second->length(); - SortedLinesByFile.push_back(&*I); + for (auto &I : LinesByFile) { + Len += I.second->length(); + SortedLinesByFile.push_back(&I); } writeBytes(LinesTag, 4); @@ -272,10 +279,8 @@ namespace { StringMapEntry<GCOVLines *> *RHS) { return LHS->getKey() < RHS->getKey(); }); - for (SmallVectorImpl<StringMapEntry<GCOVLines *> *>::iterator - I = SortedLinesByFile.begin(), E = SortedLinesByFile.end(); - I != E; ++I) - (*I)->getValue()->writeOut(); + for (auto &I : SortedLinesByFile) + I->getValue()->writeOut(); write(0); write(0); } @@ -450,28 +455,32 @@ bool GCOVProfiler::runOnModule(Module &M) { this->M = &M; Ctx = &M.getContext(); - FnMap.clear(); - for (Function &F : M) { - if (DISubprogram *SP = F.getSubprogram()) - FnMap[SP] = &F; - } - if (Options.EmitNotes) emitProfileNotes(); if (Options.EmitData) return emitProfileArcs(); return false; } -static bool functionHasLines(Function *F) { +PreservedAnalyses GCOVProfilerPass::run(Module &M, + AnalysisManager<Module> &AM) { + + GCOVProfiler Profiler(GCOVOpts); + + if (!Profiler.runOnModule(M)) + return PreservedAnalyses::all(); + + return PreservedAnalyses::none(); +} + +static bool functionHasLines(Function &F) { // Check whether this function actually has any source lines. Not only // do these waste space, they also can crash gcov. - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { - for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); - I != IE; ++I) { + for (auto &BB : F) { + for (auto &I : BB) { // Debug intrinsic locations correspond to the location of the // declaration, not necessarily any statements or expressions. - if (isa<DbgInfoIntrinsic>(I)) continue; + if (isa<DbgInfoIntrinsic>(&I)) continue; - const DebugLoc &Loc = I->getDebugLoc(); + const DebugLoc &Loc = I.getDebugLoc(); if (!Loc) continue; @@ -504,27 +513,27 @@ void GCOVProfiler::emitProfileNotes() { std::string EdgeDestinations; unsigned FunctionIdent = 0; - for (auto *SP : CU->getSubprograms()) { - Function *F = FnMap[SP]; - if (!F) continue; + for (auto &F : M->functions()) { + DISubprogram *SP = F.getSubprogram(); + if (!SP) continue; if (!functionHasLines(F)) continue; // gcov expects every function to start with an entry block that has a // single successor, so split the entry block to make sure of that. - BasicBlock &EntryBlock = F->getEntryBlock(); + BasicBlock &EntryBlock = F.getEntryBlock(); BasicBlock::iterator It = EntryBlock.begin(); while (isa<AllocaInst>(*It) || isa<DbgInfoIntrinsic>(*It)) ++It; EntryBlock.splitBasicBlock(It); - Funcs.push_back(make_unique<GCOVFunction>(SP, F, &out, FunctionIdent++, + Funcs.push_back(make_unique<GCOVFunction>(SP, &F, &out, FunctionIdent++, Options.UseCfgChecksum, Options.ExitBlockBeforeBody)); GCOVFunction &Func = *Funcs.back(); - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { - GCOVBlock &Block = Func.getBlock(&*BB); - TerminatorInst *TI = BB->getTerminator(); + for (auto &BB : F) { + GCOVBlock &Block = Func.getBlock(&BB); + TerminatorInst *TI = BB.getTerminator(); if (int successors = TI->getNumSuccessors()) { for (int i = 0; i != successors; ++i) { Block.addEdge(Func.getBlock(TI->getSuccessor(i))); @@ -534,13 +543,12 @@ void GCOVProfiler::emitProfileNotes() { } uint32_t Line = 0; - for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); - I != IE; ++I) { + for (auto &I : BB) { // Debug intrinsic locations correspond to the location of the // declaration, not necessarily any statements or expressions. - if (isa<DbgInfoIntrinsic>(I)) continue; + if (isa<DbgInfoIntrinsic>(&I)) continue; - const DebugLoc &Loc = I->getDebugLoc(); + const DebugLoc &Loc = I.getDebugLoc(); if (!Loc) continue; @@ -581,16 +589,15 @@ bool GCOVProfiler::emitProfileArcs() { bool Result = false; bool InsertIndCounterIncrCode = false; for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { - auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; - for (auto *SP : CU->getSubprograms()) { - Function *F = FnMap[SP]; - if (!F) continue; + for (auto &F : M->functions()) { + DISubprogram *SP = F.getSubprogram(); + if (!SP) continue; if (!functionHasLines(F)) continue; if (!Result) Result = true; unsigned Edges = 0; - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { - TerminatorInst *TI = BB->getTerminator(); + for (auto &BB : F) { + TerminatorInst *TI = BB.getTerminator(); if (isa<ReturnInst>(TI)) ++Edges; else @@ -610,12 +617,12 @@ bool GCOVProfiler::emitProfileArcs() { UniqueVector<BasicBlock *> ComplexEdgeSuccs; unsigned Edge = 0; - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { - TerminatorInst *TI = BB->getTerminator(); + for (auto &BB : F) { + TerminatorInst *TI = BB.getTerminator(); int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); if (Successors) { if (Successors == 1) { - IRBuilder<> Builder(&*BB->getFirstInsertionPt()); + IRBuilder<> Builder(&*BB.getFirstInsertionPt()); Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Edge); Value *Count = Builder.CreateLoad(Counter); @@ -626,16 +633,13 @@ bool GCOVProfiler::emitProfileArcs() { Value *Sel = Builder.CreateSelect(BI->getCondition(), Builder.getInt64(Edge), Builder.getInt64(Edge + 1)); - SmallVector<Value *, 2> Idx; - Idx.push_back(Builder.getInt64(0)); - Idx.push_back(Sel); - Value *Counter = Builder.CreateInBoundsGEP(Counters->getValueType(), - Counters, Idx); + Value *Counter = Builder.CreateInBoundsGEP( + Counters->getValueType(), Counters, {Builder.getInt64(0), Sel}); Value *Count = Builder.CreateLoad(Counter); Count = Builder.CreateAdd(Count, Builder.getInt64(1)); Builder.CreateStore(Count, Counter); } else { - ComplexEdgePreds.insert(&*BB); + ComplexEdgePreds.insert(&BB); for (int i = 0; i != Successors; ++i) ComplexEdgeSuccs.insert(TI->getSuccessor(i)); } @@ -646,7 +650,7 @@ bool GCOVProfiler::emitProfileArcs() { if (!ComplexEdgePreds.empty()) { GlobalVariable *EdgeTable = - buildEdgeLookupTable(F, Counters, + buildEdgeLookupTable(&F, Counters, ComplexEdgePreds, ComplexEdgeSuccs); GlobalVariable *EdgeState = getEdgeStateValue(); @@ -679,7 +683,7 @@ bool GCOVProfiler::emitProfileArcs() { FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); Function *F = Function::Create(FTy, GlobalValue::InternalLinkage, "__llvm_gcov_init", M); - F->setUnnamedAddr(true); + F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); F->setLinkage(GlobalValue::InternalLinkage); F->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) @@ -732,8 +736,8 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable( EdgeTable[i] = NullValue; unsigned Edge = 0; - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { - TerminatorInst *TI = BB->getTerminator(); + for (BasicBlock &BB : *F) { + TerminatorInst *TI = BB.getTerminator(); int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) { for (int i = 0; i != Successors; ++i) { @@ -742,7 +746,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable( Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Edge + i); EdgeTable[((Succs.idFor(Succ) - 1) * Preds.size()) + - (Preds.idFor(&*BB) - 1)] = cast<Constant>(Counter); + (Preds.idFor(&BB) - 1)] = cast<Constant>(Counter); } } Edge += Successors; @@ -754,7 +758,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable( ConstantArray::get(EdgeTableTy, makeArrayRef(&EdgeTable[0],TableSize)), "__llvm_gcda_edge_table"); - EdgeTableGV->setUnnamedAddr(true); + EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); return EdgeTableGV; } @@ -805,16 +809,6 @@ Constant *GCOVProfiler::getSummaryInfoFunc() { return M->getOrInsertFunction("llvm_gcda_summary_info", FTy); } -Constant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() { - FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); - return M->getOrInsertFunction("llvm_delete_writeout_function_list", FTy); -} - -Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() { - FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); - return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy); -} - Constant *GCOVProfiler::getEndFileFunc() { FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); return M->getOrInsertFunction("llvm_gcda_end_file", FTy); @@ -828,7 +822,7 @@ GlobalVariable *GCOVProfiler::getEdgeStateValue() { ConstantInt::get(Type::getInt32Ty(*Ctx), 0xffffffff), "__llvm_gcov_global_state_pred"); - GV->setUnnamedAddr(true); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); } return GV; } @@ -840,7 +834,7 @@ Function *GCOVProfiler::insertCounterWriteout( if (!WriteoutF) WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage, "__llvm_gcov_writeout", M); - WriteoutF->setUnnamedAddr(true); + WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); WriteoutF->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) WriteoutF->addFnAttr(Attribute::NoRedZone); @@ -884,7 +878,7 @@ Function *GCOVProfiler::insertCounterWriteout( GlobalVariable *GV = CountersBySP[j].first; unsigned Arcs = - cast<ArrayType>(GV->getType()->getElementType())->getNumElements(); + cast<ArrayType>(GV->getValueType())->getNumElements(); Builder.CreateCall(EmitArcs, {Builder.getInt32(Arcs), Builder.CreateConstGEP2_64(GV, 0, 0)}); } @@ -900,7 +894,7 @@ Function *GCOVProfiler::insertCounterWriteout( void GCOVProfiler::insertIndirectCounterIncrement() { Function *Fn = cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc()); - Fn->setUnnamedAddr(true); + Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); Fn->setLinkage(GlobalValue::InternalLinkage); Fn->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) @@ -957,7 +951,7 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) { "__llvm_gcov_flush", M); else FlushF->setLinkage(GlobalValue::InternalLinkage); - FlushF->setUnnamedAddr(true); + FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); FlushF->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) FlushF->addFnAttr(Attribute::NoRedZone); @@ -972,11 +966,9 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) { Builder.CreateCall(WriteoutF, {}); // Zero out the counters. - for (ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator - I = CountersBySP.begin(), E = CountersBySP.end(); - I != E; ++I) { - GlobalVariable *GV = I->first; - Constant *Null = Constant::getNullValue(GV->getType()->getElementType()); + for (const auto &I : CountersBySP) { + GlobalVariable *GV = I.first; + Constant *Null = Constant::getNullValue(GV->getValueType()); Builder.CreateStore(Null, GV); } |