X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FInstrumentation%2FGCOVProfiling.cpp;h=685428ee952e1519fdcc95eeb9724d0e9798e81c;hb=e1d7711d2f9cc628a3e8fa0c6f4925af8f09651e;hp=557ef66dfdfb781abc964d4d9ed72cd357b6bbcf;hpb=ee5e607355f76f0de64ea9ff5a380a5317627e05;p=oota-llvm.git diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 557ef66dfdf..685428ee952 100644 --- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -14,8 +14,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "insert-gcov-profiling" - #include "llvm/Transforms/Instrumentation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" @@ -24,25 +22,28 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/UniqueVector.h" -#include "llvm/DebugInfo.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/DebugLoc.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/InstIterator.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include +#include #include #include using namespace llvm; +#define DEBUG_TYPE "insert-gcov-profiling" + static cl::opt DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden, cl::ValueRequired); @@ -77,10 +78,7 @@ namespace { "GCOVProfiler asked to do nothing?"); init(); } - ~GCOVProfiler() { - DeleteContainerPointers(Funcs); - } - virtual const char *getPassName() const { + const char *getPassName() const override { return "GCOV Profiler"; } @@ -93,7 +91,7 @@ namespace { ReversedVersion[4] = '\0'; initializeGCOVProfilerPass(*PassRegistry::getPassRegistry()); } - bool runOnModule(Module &M); + bool runOnModule(Module &M) override; // Create the .gcno files for the Module based on DebugInfo. void emitProfileNotes(); @@ -135,13 +133,13 @@ namespace { GCOVOptions Options; // Reversed, NUL-terminated copy of Options.Version. - char ReversedVersion[5]; + char ReversedVersion[5]; // Checksum, produced by hash of EdgeDestinations SmallVector FileChecksums; Module *M; LLVMContext *Ctx; - SmallVector Funcs; + SmallVector, 16> Funcs; }; } @@ -213,6 +211,7 @@ namespace { class GCOVLines : public GCOVRecord { public: void addLine(uint32_t Line) { + assert(Line != 0 && "Line zero is not a valid real line number."); Lines.push_back(Line); } @@ -228,7 +227,7 @@ namespace { write(Lines[i]); } - GCOVLines(StringRef F, raw_ostream *os) + GCOVLines(StringRef F, raw_ostream *os) : Filename(F) { this->os = os; } @@ -276,7 +275,7 @@ namespace { }); for (SmallVectorImpl *>::iterator I = SortedLinesByFile.begin(), E = SortedLinesByFile.end(); - I != E; ++I) + I != E; ++I) (*I)->getValue()->writeOut(); write(0); write(0); @@ -311,11 +310,15 @@ namespace { Function *F = SP.getFunction(); DEBUG(dbgs() << "Function: " << getFunctionName(SP) << "\n"); - uint32_t i = 0; - for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { + + Function::iterator BB = F->begin(), E = F->end(); + Blocks[BB++] = new GCOVBlock(0, os); + ReturnBlock = new GCOVBlock(1, os); + + uint32_t i = 2; + for (; BB != E; ++BB) { Blocks[BB] = new GCOVBlock(i++, os); } - ReturnBlock = new GCOVBlock(i++, os); std::string FunctionNameAndLine; raw_string_ostream FNLOS(FunctionNameAndLine); @@ -449,6 +452,28 @@ bool GCOVProfiler::runOnModule(Module &M) { return false; } +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) { + // Debug intrinsic locations correspond to the location of the + // declaration, not necessarily any statements or expressions. + if (isa(I)) continue; + + const DebugLoc &Loc = I->getDebugLoc(); + if (Loc.isUnknown()) continue; + + // Artificial lines such as calls to the global constructors. + if (Loc.getLine() == 0) continue; + + return true; + } + } + return false; +} + void GCOVProfiler::emitProfileNotes() { NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; @@ -459,12 +484,12 @@ void GCOVProfiler::emitProfileNotes() { // LTO, we'll generate the same .gcno files. DICompileUnit CU(CU_Nodes->getOperand(i)); - std::string ErrorInfo; - raw_fd_ostream out(mangleName(CU, "gcno").c_str(), ErrorInfo, - sys::fs::F_None); + std::error_code EC; + raw_fd_ostream out(mangleName(CU, "gcno"), EC, sys::fs::F_None); std::string EdgeDestinations; DIArray SPs = CU.getSubprograms(); + unsigned FunctionIdent = 0; for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { DISubprogram SP(SPs.getElement(i)); assert((!SP || SP.isSubprogram()) && @@ -474,6 +499,7 @@ void GCOVProfiler::emitProfileNotes() { Function *F = SP.getFunction(); if (!F) 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. @@ -483,26 +509,34 @@ void GCOVProfiler::emitProfileNotes() { ++It; EntryBlock.splitBasicBlock(It); - GCOVFunction *Func = - new GCOVFunction(SP, &out, i, Options.UseCfgChecksum); - Funcs.push_back(Func); + Funcs.push_back(make_unique(SP, &out, FunctionIdent++, + Options.UseCfgChecksum)); + GCOVFunction &Func = *Funcs.back(); for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { - GCOVBlock &Block = Func->getBlock(BB); + 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))); + Block.addEdge(Func.getBlock(TI->getSuccessor(i))); } } else if (isa(TI)) { - Block.addEdge(Func->getReturnBlock()); + Block.addEdge(Func.getReturnBlock()); } uint32_t Line = 0; for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) { + // Debug intrinsic locations correspond to the location of the + // declaration, not necessarily any statements or expressions. + if (isa(I)) continue; + const DebugLoc &Loc = I->getDebugLoc(); if (Loc.isUnknown()) continue; + + // Artificial lines such as calls to the global constructors. + if (Loc.getLine() == 0) continue; + if (Line == Loc.getLine()) continue; Line = Loc.getLine(); if (SP != getDISubprogram(Loc.getScope(*Ctx))) continue; @@ -511,7 +545,7 @@ void GCOVProfiler::emitProfileNotes() { Lines.addLine(Loc.getLine()); } } - EdgeDestinations += Func->getEdgeDestinations(); + EdgeDestinations += Func.getEdgeDestinations(); } FileChecksums.push_back(hash_value(EdgeDestinations)); @@ -519,9 +553,7 @@ void GCOVProfiler::emitProfileNotes() { out.write(ReversedVersion, 4); out.write(reinterpret_cast(&FileChecksums.back()), 4); - for (SmallVectorImpl::iterator I = Funcs.begin(), - E = Funcs.end(); I != E; ++I) { - GCOVFunction *Func = *I; + for (auto &Func : Funcs) { Func->setCfgChecksum(FileChecksums.back()); Func->writeOut(); } @@ -535,7 +567,7 @@ bool GCOVProfiler::emitProfileArcs() { NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return false; - bool Result = false; + bool Result = false; bool InsertIndCounterIncrCode = false; for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { DICompileUnit CU(CU_Nodes->getOperand(i)); @@ -549,6 +581,7 @@ bool GCOVProfiler::emitProfileArcs() { continue; Function *F = SP.getFunction(); if (!F) continue; + if (!functionHasLines(F)) continue; if (!Result) Result = true; unsigned Edges = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { @@ -558,7 +591,7 @@ bool GCOVProfiler::emitProfileArcs() { else Edges += TI->getNumSuccessors(); } - + ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(*Ctx), Edges); GlobalVariable *Counters = @@ -567,10 +600,10 @@ bool GCOVProfiler::emitProfileArcs() { Constant::getNullValue(CounterTy), "__llvm_gcov_ctr"); CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP)); - + UniqueVector ComplexEdgePreds; UniqueVector ComplexEdgeSuccs; - + unsigned Edge = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); @@ -604,13 +637,13 @@ bool GCOVProfiler::emitProfileArcs() { Edge += Successors; } } - + if (!ComplexEdgePreds.empty()) { GlobalVariable *EdgeTable = buildEdgeLookupTable(F, Counters, ComplexEdgePreds, ComplexEdgeSuccs); GlobalVariable *EdgeState = getEdgeStateValue(); - + for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { IRBuilder<> Builder(ComplexEdgePreds[i + 1]->getFirstInsertionPt()); Builder.CreateStore(Builder.getInt32(i), EdgeState); @@ -687,7 +720,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable( Type *Int64PtrTy = Type::getInt64PtrTy(*Ctx); ArrayType *EdgeTableTy = ArrayType::get(Int64PtrTy, TableSize); - OwningArrayPtr EdgeTable(new Constant*[TableSize]); + std::unique_ptr EdgeTable(new Constant *[TableSize]); Constant *NullValue = Constant::getNullValue(Int64PtrTy); for (size_t i = 0; i != TableSize; ++i) EdgeTable[i] = NullValue; @@ -709,11 +742,11 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable( Edge += Successors; } - ArrayRef V(&EdgeTable[0], TableSize); GlobalVariable *EdgeTableGV = new GlobalVariable( *M, EdgeTableTy, true, GlobalValue::InternalLinkage, - ConstantArray::get(EdgeTableTy, V), + ConstantArray::get(EdgeTableTy, + makeArrayRef(&EdgeTable[0],TableSize)), "__llvm_gcda_edge_table"); EdgeTableGV->setUnnamedAddr(true); return EdgeTableGV; @@ -883,7 +916,7 @@ void GCOVProfiler::insertIndirectCounterIncrement() { // uint64_t *counter = counters[pred]; // if (!counter) return; Value *ZExtPred = Builder.CreateZExt(Pred, Builder.getInt64Ty()); - Arg = llvm::next(Fn->arg_begin()); + Arg = std::next(Fn->arg_begin()); Arg->setName("counters"); Value *GEP = Builder.CreateGEP(Arg, ZExtPred); Value *Counter = Builder.CreateLoad(GEP, "counter");