[compiler-rt] 546918c - Revert "[compiler-rt] Add a critical section when flushing gcov counters"
Hans Wennborg via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 26 04:30:53 PST 2020
Author: Hans Wennborg
Date: 2020-02-26T13:27:44+01:00
New Revision: 546918cbb4b2231c65cf91fceb738a59d03af7bf
URL: https://github.com/llvm/llvm-project/commit/546918cbb4b2231c65cf91fceb738a59d03af7bf
DIFF: https://github.com/llvm/llvm-project/commit/546918cbb4b2231c65cf91fceb738a59d03af7bf.diff
LOG: Revert "[compiler-rt] Add a critical section when flushing gcov counters"
See discussion on PR44792.
This reverts commit 02ce9d8ef5a84bc884de4105eae5f8736ef67634.
It also reverts the follow-up commits
8f46269f0 "[profile] Don't dump counters when forking and don't reset when calling exec** functions"
62c7d8402 "[profile] gcov_mutex must be static"
Added:
Modified:
clang/lib/Driver/ToolChains/Darwin.cpp
compiler-rt/lib/profile/GCDAProfiling.c
llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index c9f87e0e4355..b32fad791bd3 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1144,10 +1144,8 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
if (hasExportSymbolDirective(Args)) {
if (ForGCOV) {
addExportedSymbol(CmdArgs, "___gcov_flush");
- addExportedSymbol(CmdArgs, "___gcov_fork");
addExportedSymbol(CmdArgs, "_flush_fn_list");
addExportedSymbol(CmdArgs, "_writeout_fn_list");
- addExportedSymbol(CmdArgs, "_reset_fn_list");
} else {
addExportedSymbol(CmdArgs, "___llvm_profile_filename");
addExportedSymbol(CmdArgs, "___llvm_profile_raw_version");
diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c
index 98815dab541b..498c05900bf2 100644
--- a/compiler-rt/lib/profile/GCDAProfiling.c
+++ b/compiler-rt/lib/profile/GCDAProfiling.c
@@ -32,9 +32,8 @@
#include <windows.h>
#include "WindowsMMap.h"
#else
-#include <sys/file.h>
#include <sys/mman.h>
-#include <unistd.h>
+#include <sys/file.h>
#endif
#if defined(__FreeBSD__) && defined(__i386__)
@@ -65,18 +64,6 @@ typedef unsigned long long uint64_t;
/* #define DEBUG_GCDAPROFILING */
-#ifndef _WIN32
-#include <pthread.h>
-static pthread_mutex_t gcov_mutex = PTHREAD_MUTEX_INITIALIZER;
-static __inline void gcov_lock() { pthread_mutex_lock(&gcov_mutex); }
-static __inline void gcov_unlock() { pthread_mutex_unlock(&gcov_mutex); }
-#else
-#include <windows.h>
-static SRWLOCK gcov_mutex = SRWLOCK_INIT;
-static __inline void gcov_lock() { AcquireSRWLockExclusive(&gcov_mutex); }
-static __inline void gcov_unlock() { ReleaseSRWLockExclusive(&gcov_mutex); }
-#endif
-
/*
* --- GCOV file format I/O primitives ---
*/
@@ -132,12 +119,6 @@ struct fn_list writeout_fn_list;
*/
struct fn_list flush_fn_list;
-/*
- * A list of reset functions that our __gcov_reset() function should call,
- * shared between all dynamic objects.
- */
-struct fn_list reset_fn_list;
-
static void fn_list_insert(struct fn_list* list, fn_ptr fn) {
struct fn_node* new_node = malloc(sizeof(struct fn_node));
new_node->fn = fn;
@@ -638,96 +619,36 @@ void llvm_register_flush_function(fn_ptr fn) {
fn_list_insert(&flush_fn_list, fn);
}
-COMPILER_RT_VISIBILITY
-void llvm_register_reset_function(fn_ptr fn) {
- fn_list_insert(&reset_fn_list, fn);
-}
-
-COMPILER_RT_VISIBILITY
-void llvm_reset_counters(void) {
- struct fn_node *curr = reset_fn_list.head;
-
- while (curr) {
- if (curr->id == CURRENT_ID) {
- curr->fn();
- }
- curr = curr->next;
- }
-}
-
void __gcov_flush() {
- gcov_lock();
-
struct fn_node* curr = flush_fn_list.head;
while (curr) {
curr->fn();
curr = curr->next;
}
-
- gcov_unlock();
}
-#if !defined(_WIN32)
-pid_t __gcov_fork() {
- pid_t parent_pid = getpid();
- pid_t pid;
-
- gcov_lock();
- // Avoid a concurrent modification of the lists during the fork.
- // For example, a thread is making a fork while another one is
- // loading a CU and so executing global initializer in this case
- // the child process could inherit a bad list (e.g. bad tail)
- // or could have the malloc in a wrong state.
- pid = fork();
- gcov_unlock();
-
- if (pid == 0) {
- pid_t child_pid = getpid();
- if (child_pid != parent_pid) {
- // The pid changed so we've a fork (one could have its own fork function)
- // Just reset the counters for this child process
- // No need to lock here since we just forked and cannot have any other
- // threads.
- llvm_reset_counters();
- }
- }
- return pid;
-}
-#endif
-
COMPILER_RT_VISIBILITY
void llvm_delete_flush_function_list(void) {
fn_list_remove(&flush_fn_list);
}
COMPILER_RT_VISIBILITY
-void llvm_delete_reset_function_list(void) { fn_list_remove(&reset_fn_list); }
-
-COMPILER_RT_VISIBILITY
-void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn, fn_ptr rfn) {
+void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn) {
static int atexit_ran = 0;
- gcov_lock();
-
if (wfn)
llvm_register_writeout_function(wfn);
if (ffn)
llvm_register_flush_function(ffn);
- if (rfn)
- llvm_register_reset_function(rfn);
-
- gcov_unlock();
-
if (atexit_ran == 0) {
atexit_ran = 1;
/* Make sure we write out the data and delete the data structures. */
atexit(llvm_delete_flush_function_list);
atexit(llvm_delete_writeout_function_list);
- atexit(llvm_delete_reset_function_list);
atexit(llvm_writeout_files);
}
}
diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index ee57a5493261..2a302b547dc4 100644
--- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -115,8 +115,7 @@ class GCOVProfiler {
// list.
Function *
insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
- Function *insertReset(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
- Function *insertFlush(Function *ResetF);
+ Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
void AddFlushBeforeForkAndExec();
@@ -632,74 +631,35 @@ static bool shouldKeepInEntry(BasicBlock::iterator It) {
}
void GCOVProfiler::AddFlushBeforeForkAndExec() {
- SmallVector<std::pair<bool, CallInst *>, 2> ForkAndExecs;
+ SmallVector<Instruction *, 2> ForkAndExecs;
for (auto &F : M->functions()) {
auto *TLI = &GetTLI(F);
for (auto &I : instructions(F)) {
if (CallInst *CI = dyn_cast<CallInst>(&I)) {
if (Function *Callee = CI->getCalledFunction()) {
LibFunc LF;
- if (TLI->getLibFunc(*Callee, LF)) {
- if (LF == LibFunc_fork) {
-#if !defined(_WIN32)
- ForkAndExecs.push_back({true, CI});
-#endif
- } else if (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({false, CI});
- }
+ 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);
}
}
}
}
}
- for (auto F : ForkAndExecs) {
- IRBuilder<> Builder(F.second);
- BasicBlock *Parent = F.second->getParent();
- auto NextInst = ++F.second->getIterator();
-
- if (F.first) {
- // We've a fork so just reset the counters in the child process
- FunctionType *FTy = FunctionType::get(Builder.getInt32Ty(), {}, false);
- FunctionCallee GCOVFork = M->getOrInsertFunction("__gcov_fork", FTy);
- F.second->setCalledFunction(GCOVFork);
- if (NextInst != Parent->end()) {
- // We split just after the fork to have a counter for the lines after
- // Anyway there's a bug:
- // void foo() { fork(); }
- // void bar() { foo(); blah(); }
- // then "blah();" will be called 2 times but showed as 1
- // because "blah()" belongs to the same block as "foo();"
- Parent->splitBasicBlock(NextInst);
-
- // back() is a br instruction with a debug location
- // equals to the one from NextAfterFork
- // So to avoid to have two debug locs on two blocks just change it
- DebugLoc Loc = F.second->getDebugLoc();
- Parent->back().setDebugLoc(Loc);
- }
- } else {
- // Since the process is replaced by a new one we need to write out gcdas
- // No need to reset the counters since they'll be lost after the exec**
- FunctionType *FTy = FunctionType::get(Builder.getVoidTy(), {}, false);
- FunctionCallee WriteoutF =
- M->getOrInsertFunction("llvm_writeout_files", FTy);
- Builder.CreateCall(WriteoutF);
- if (NextInst != Parent->end()) {
- DebugLoc Loc = F.second->getDebugLoc();
- Builder.SetInsertPoint(&*NextInst);
- // If the exec** fails we must reset the counters since they've been
- // dumped
- FunctionCallee ResetF =
- M->getOrInsertFunction("llvm_reset_counters", FTy);
- Builder.CreateCall(ResetF)->setDebugLoc(Loc);
- Parent->splitBasicBlock(NextInst);
- Parent->back().setDebugLoc(Loc);
- }
- }
+ // 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);
+ FunctionCallee GCOVFlush = M->getOrInsertFunction("__gcov_flush", FTy);
+ Builder.CreateCall(GCOVFlush);
+ I->getParent()->splitBasicBlock(I);
}
}
@@ -891,8 +851,7 @@ bool GCOVProfiler::emitProfileArcs() {
}
Function *WriteoutF = insertCounterWriteout(CountersBySP);
- Function *ResetF = insertReset(CountersBySP);
- Function *FlushF = insertFlush(ResetF);
+ Function *FlushF = insertFlush(CountersBySP);
// Create a small bit of code that registers the "__llvm_gcov_writeout" to
// be executed at exit and the "__llvm_gcov_flush" function to be executed
@@ -910,14 +869,16 @@ bool GCOVProfiler::emitProfileArcs() {
IRBuilder<> Builder(BB);
FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
- Type *Params[] = {PointerType::get(FTy, 0), PointerType::get(FTy, 0),
- PointerType::get(FTy, 0)};
+ Type *Params[] = {
+ PointerType::get(FTy, 0),
+ PointerType::get(FTy, 0)
+ };
FTy = FunctionType::get(Builder.getVoidTy(), Params, false);
- // Initialize the environment and register the local writeout, flush and
- // reset functions.
+ // Initialize the environment and register the local writeout and flush
+ // functions.
FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);
- Builder.CreateCall(GCOVInit, {WriteoutF, FlushF, ResetF});
+ Builder.CreateCall(GCOVInit, {WriteoutF, FlushF});
Builder.CreateRetVoid();
appendToGlobalCtors(*M, F, 0);
@@ -1230,43 +1191,8 @@ Function *GCOVProfiler::insertCounterWriteout(
return WriteoutF;
}
-Function *GCOVProfiler::insertReset(
- ArrayRef<std::pair<GlobalVariable *, MDNode *>> CountersBySP) {
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
- Function *ResetF = M->getFunction("__llvm_gcov_reset");
- if (!ResetF)
- ResetF = Function::Create(FTy, GlobalValue::InternalLinkage,
- "__llvm_gcov_reset", M);
- else
- ResetF->setLinkage(GlobalValue::InternalLinkage);
- ResetF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
- ResetF->addFnAttr(Attribute::NoInline);
- if (Options.NoRedZone)
- ResetF->addFnAttr(Attribute::NoRedZone);
-
- BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", ResetF);
- IRBuilder<> Builder(Entry);
-
- // Zero out the counters.
- for (const auto &I : CountersBySP) {
- GlobalVariable *GV = I.first;
- Constant *Null = Constant::getNullValue(GV->getValueType());
- Builder.CreateStore(Null, GV);
- }
-
- Type *RetTy = ResetF->getReturnType();
- if (RetTy == Type::getVoidTy(*Ctx))
- Builder.CreateRetVoid();
- else if (RetTy->isIntegerTy())
- // Used if __llvm_gcov_reset was implicitly declared.
- Builder.CreateRet(ConstantInt::get(RetTy, 0));
- else
- report_fatal_error("invalid return type for __llvm_gcov_reset");
-
- return ResetF;
-}
-
-Function *GCOVProfiler::insertFlush(Function *ResetF) {
+Function *GCOVProfiler::
+insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *FlushF = M->getFunction("__llvm_gcov_flush");
if (!FlushF)
@@ -1280,13 +1206,20 @@ Function *GCOVProfiler::insertFlush(Function *ResetF) {
FlushF->addFnAttr(Attribute::NoRedZone);
BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF);
- IRBuilder<> Builder(Entry);
+ // Write out the current counters.
Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
assert(WriteoutF && "Need to create the writeout function first!");
- Builder.CreateCall(WriteoutF);
- Builder.CreateCall(ResetF);
+ IRBuilder<> Builder(Entry);
+ Builder.CreateCall(WriteoutF, {});
+
+ // Zero out the counters.
+ for (const auto &I : CountersBySP) {
+ GlobalVariable *GV = I.first;
+ Constant *Null = Constant::getNullValue(GV->getValueType());
+ Builder.CreateStore(Null, GV);
+ }
Type *RetTy = FlushF->getReturnType();
if (RetTy == Type::getVoidTy(*Ctx))
More information about the llvm-commits
mailing list