diff options
author | Calixte Denizet <cdenizet@mozilla.com> | 2018-11-07 13:49:17 +0000 |
---|---|---|
committer | Calixte Denizet <cdenizet@mozilla.com> | 2018-11-07 13:49:17 +0000 |
commit | c3bed1e8e6eb7779fa7d4b24a43e827c675c0331 (patch) | |
tree | bdf548eb8a7d709148e91ab812e2f6ad8d12fbf8 /llvm/lib | |
parent | c9f3cba3c60c8e854e56e3f4d63def664ec9527e (diff) | |
download | bcm5719-llvm-c3bed1e8e6eb7779fa7d4b24a43e827c675c0331.tar.gz bcm5719-llvm-c3bed1e8e6eb7779fa7d4b24a43e827c675c0331.zip |
[GCOV] Flush counters before to avoid counting the execution before fork twice and for exec** functions we must flush before the call
Summary:
This is replacement for patch in https://reviews.llvm.org/D49460.
When we fork, the counters are duplicate as they're and so the values are finally wrong when writing gcda for parent and child.
So just before to fork, we flush the counters and so the parent and the child have new counters set to zero.
For exec** functions, we need to flush before the call to have some data.
Reviewers: vsk, davidxl, marco-c
Reviewed By: marco-c
Subscribers: llvm-commits, sylvestre.ledru, marco-c
Differential Revision: https://reviews.llvm.org/D53593
llvm-svn: 346313
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/TargetLibraryInfo.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | 36 |
2 files changed, 60 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index b3cd40e098e..e6c6b4a76d6 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -613,6 +613,28 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, unsigned NumParams = FTy.getNumParams(); switch (F) { + case LibFunc_execl: + case LibFunc_execlp: + return (NumParams >= 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32)); + case LibFunc_execle: + return (NumParams >= 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(NumParams - 1)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32)); + case LibFunc_execv: + case LibFunc_execvp: + return (NumParams == 2 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32)); + case LibFunc_execvP: + case LibFunc_execvpe: + case LibFunc_execve: + return (NumParams == 3 && FTy.getParamType(0)->isPointerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy() && + FTy.getReturnType()->isIntegerTy(32)); case LibFunc_strlen: return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && FTy.getReturnType()->isIntegerTy()); @@ -863,6 +885,8 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && FTy.getParamType(0)->isPointerTy() && FTy.getParamType(1)->isPointerTy()); + case LibFunc_fork: + return (NumParams == 0 && FTy.getReturnType()->isIntegerTy(32)); case LibFunc_fdopen: return (NumParams == 2 && FTy.getReturnType()->isPointerTy() && FTy.getParamType(1)->isPointerTy()); diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 01938a0f357..084e6b7e436 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -109,6 +109,8 @@ private: insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>); + void AddFlushBeforeForkAndExec(); + enum class GCovFileType { GCNO, GCDA }; std::string mangleName(const DICompileUnit *CU, GCovFileType FileType); @@ -468,6 +470,8 @@ bool GCOVProfiler::runOnModule(Module &M, const TargetLibraryInfo &TLI) { this->TLI = &TLI; Ctx = &M.getContext(); + AddFlushBeforeForkAndExec(); + if (Options.EmitNotes) emitProfileNotes(); if (Options.EmitData) return emitProfileArcs(); return false; @@ -524,6 +528,38 @@ static bool shouldKeepInEntry(BasicBlock::iterator It) { return false; } +void GCOVProfiler::AddFlushBeforeForkAndExec() { + SmallVector<Instruction *, 2> ForkAndExecs; + for (auto &F : M->functions()) { + for (auto &I : instructions(F)) { + if (CallInst *CI = dyn_cast<CallInst>(&I)) { + if (Function *Callee = CI->getCalledFunction()) { + LibFunc LF; + if (TLI->getLibFunc(*Callee, LF) && + (LF == LibFunc_fork || LF == LibFunc_execl || + LF == LibFunc_execle || LF == LibFunc_execlp || + LF == LibFunc_execv || LF == LibFunc_execvp || + LF == LibFunc_execve || LF == LibFunc_execvpe || + LF == LibFunc_execvP)) { + ForkAndExecs.push_back(&I); + } + } + } + } + } + + // We need to split the block after the fork/exec call + // because else the counters for the lines after will be + // the same as before the call. + for (auto I : ForkAndExecs) { + IRBuilder<> Builder(I); + FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false); + Constant *GCOVFlush = M->getOrInsertFunction("__gcov_flush", FTy); + Builder.CreateCall(GCOVFlush); + I->getParent()->splitBasicBlock(I); + } +} + void GCOVProfiler::emitProfileNotes() { NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; |