summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorCalixte Denizet <cdenizet@mozilla.com>2018-11-07 13:49:17 +0000
committerCalixte Denizet <cdenizet@mozilla.com>2018-11-07 13:49:17 +0000
commitc3bed1e8e6eb7779fa7d4b24a43e827c675c0331 (patch)
treebdf548eb8a7d709148e91ab812e2f6ad8d12fbf8 /llvm/lib
parentc9f3cba3c60c8e854e56e3f4d63def664ec9527e (diff)
downloadbcm5719-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.cpp24
-rw-r--r--llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp36
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;
OpenPOWER on IntegriCloud