[llvm] 5809a32 - [gcov] Add __gcov_dump/__gcov_reset and delete __gcov_flush
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 18 15:08:27 PDT 2020
Author: Fangrui Song
Date: 2020-07-18T15:07:46-07:00
New Revision: 5809a32e7c2d79a9a463eb9c15cde994b42e3002
URL: https://github.com/llvm/llvm-project/commit/5809a32e7c2d79a9a463eb9c15cde994b42e3002
DIFF: https://github.com/llvm/llvm-project/commit/5809a32e7c2d79a9a463eb9c15cde994b42e3002.diff
LOG: [gcov] Add __gcov_dump/__gcov_reset and delete __gcov_flush
GCC r187297 (2012-05) introduced `__gcov_dump` and `__gcov_reset`.
`__gcov_flush = __gcov_dump + __gcov_reset`
The resolution to https://gcc.gnu.org/PR93623 ("No need to dump gcdas when forking" target GCC 11.0) removed the unuseful and undocumented __gcov_flush.
Close PR38064.
Reviewed By: calixte, serge-sans-paille
Differential Revision: https://reviews.llvm.org/D83149
Added:
Modified:
clang/lib/Driver/ToolChains/Darwin.cpp
clang/test/CodeGen/code-coverage.c
clang/test/Driver/darwin-ld.c
compiler-rt/lib/profile/GCDAProfiling.c
compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c
compiler-rt/test/profile/Posix/gcov-dlopen.c
compiler-rt/test/profile/Posix/gcov-shared-flush.c
compiler-rt/test/profile/gcov-__gcov_flush-terminate.c
compiler-rt/test/profile/gcov-dump-and-remove.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 7b879f8cb652..f910c88fa967 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -1196,7 +1196,8 @@ void Darwin::addProfileRTLibs(const ArgList &Args,
// runtime's functionality.
if (hasExportSymbolDirective(Args)) {
if (ForGCOV) {
- addExportedSymbol(CmdArgs, "___gcov_flush");
+ addExportedSymbol(CmdArgs, "___gcov_dump");
+ addExportedSymbol(CmdArgs, "___gcov_reset");
addExportedSymbol(CmdArgs, "_flush_fn_list");
addExportedSymbol(CmdArgs, "_writeout_fn_list");
addExportedSymbol(CmdArgs, "_reset_fn_list");
diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c
index 34ba3554f5b5..5a663135e2f0 100644
--- a/clang/test/CodeGen/code-coverage.c
+++ b/clang/test/CodeGen/code-coverage.c
@@ -51,7 +51,6 @@ int test2(int b) {
// Check that the noredzone flag is set on the generated functions.
// CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]]
-// CHECK: void @__llvm_gcov_flush() unnamed_addr [[NRZ]]
// CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]]
// CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} }
diff --git a/clang/test/Driver/darwin-ld.c b/clang/test/Driver/darwin-ld.c
index 3fc0556a2bde..ea71142e88c1 100644
--- a/clang/test/Driver/darwin-ld.c
+++ b/clang/test/Driver/darwin-ld.c
@@ -351,7 +351,8 @@
// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
// RUN: %clang -target x86_64-apple-darwin12 -fprofile-arcs -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log
// RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log
-// GCOV_EXPORT: "-exported_symbol" "___gcov_flush"
+// GCOV_EXPORT: "-exported_symbol" "___gcov_dump"
+// GCOV_EXPORT: "-exported_symbol" "___gcov_reset"
//
// Check that we can pass the outliner down to the linker.
// RUN: env IPHONEOS_DEPLOYMENT_TARGET=7.0 \
diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c
index 57d8dec423cc..fa4b95138332 100644
--- a/compiler-rt/lib/profile/GCDAProfiling.c
+++ b/compiler-rt/lib/profile/GCDAProfiling.c
@@ -639,25 +639,6 @@ static void llvm_writeout_and_clear(void) {
fn_list_remove(&writeout_fn_list);
}
-COMPILER_RT_VISIBILITY
-void llvm_register_flush_function(fn_ptr fn) {
- fn_list_insert(&flush_fn_list, fn);
-}
-
-void __gcov_flush() {
- struct fn_node* curr = flush_fn_list.head;
-
- while (curr) {
- curr->fn();
- curr = curr->next;
- }
-}
-
-COMPILER_RT_VISIBILITY
-void llvm_delete_flush_function_list(void) {
- fn_list_remove(&flush_fn_list);
-}
-
COMPILER_RT_VISIBILITY
void llvm_register_reset_function(fn_ptr fn) {
fn_list_insert(&reset_fn_list, fn);
@@ -698,15 +679,12 @@ pid_t __gcov_fork() {
#endif
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 rfn) {
static int atexit_ran = 0;
if (wfn)
llvm_register_writeout_function(wfn);
- if (ffn)
- llvm_register_flush_function(ffn);
-
if (rfn)
llvm_register_reset_function(rfn);
@@ -715,11 +693,20 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn, fn_ptr rfn) {
/* Make sure we write out the data and delete the data structures. */
atexit(llvm_delete_reset_function_list);
- atexit(llvm_delete_flush_function_list);
#ifdef _WIN32
atexit(llvm_writeout_and_clear);
#endif
}
}
+void __gcov_dump(void) {
+ for (struct fn_node *f = writeout_fn_list.head; f; f = f->next)
+ f->fn();
+}
+
+void __gcov_reset(void) {
+ for (struct fn_node *f = reset_fn_list.head; f; f = f->next)
+ f->fn();
+}
+
#endif
diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c b/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c
index 3f4a4f6cc6a6..416b90384c7d 100644
--- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c
+++ b/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c
@@ -46,21 +46,21 @@ int main(int argc, char *argv[]) {
#endif
dlerror();
- void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush");
- if (gcov_flush1 == NULL) {
- fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror());
+ void (*gcov_reset1)() = (void (*)())dlsym(f1_handle, "__gcov_reset");
+ if (gcov_reset1 == NULL) {
+ fprintf(stderr, "unable to find __gcov_reset in func.shared': %s\n", dlerror());
return EXIT_FAILURE;
}
dlerror();
- void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush");
- if (gcov_flush2 == NULL) {
- fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror());
+ void (*gcov_reset2)() = (void (*)())dlsym(f2_handle, "__gcov_reset");
+ if (gcov_reset2 == NULL) {
+ fprintf(stderr, "unable to find __gcov_reset in func2.shared': %s\n", dlerror());
return EXIT_FAILURE;
}
- if (gcov_flush1 == gcov_flush2) {
- fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n");
+ if (gcov_reset1 == gcov_reset2) {
+ fprintf(stderr, "Same __gcov_reset found in func.shared and func2.shared\n");
return EXIT_FAILURE;
}
diff --git a/compiler-rt/test/profile/Posix/gcov-dlopen.c b/compiler-rt/test/profile/Posix/gcov-dlopen.c
index f09129d3b7c4..0212979e87ff 100644
--- a/compiler-rt/test/profile/Posix/gcov-dlopen.c
+++ b/compiler-rt/test/profile/Posix/gcov-dlopen.c
@@ -64,14 +64,19 @@ int main(int argc, char *argv[]) {
func3();
#endif
- void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush");
- if (gcov_flush1 == NULL)
- return fprintf(stderr, "unable to find __gcov_flush in func1.so': %s\n", dlerror());
- void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush");
- if (gcov_flush2 == NULL)
- return fprintf(stderr, "unable to find __gcov_flush in func2.so': %s\n", dlerror());
- if (gcov_flush1 == gcov_flush2)
- return fprintf(stderr, "same __gcov_flush found in func1.so and func2.so\n");
+ void (*gcov_reset1)() = (void (*)())dlsym(f1_handle, "__gcov_reset");
+ if (gcov_reset1 == NULL)
+ return fprintf(stderr, "unable to find __gcov_reset in func1.so': %s\n", dlerror());
+ void (*gcov_reset2)() = (void (*)())dlsym(f2_handle, "__gcov_reset");
+ if (gcov_reset2 == NULL)
+ return fprintf(stderr, "unable to find __gcov_reset in func2.so': %s\n", dlerror());
+ if (gcov_reset1 == gcov_reset2)
+ return fprintf(stderr, "same __gcov_reset found in func1.so and func2.so\n");
+
+ /// Test that __gcov_dump is in the dynamic symbol table.
+ void (*gcov_dump1)() = (void (*)())dlsym(f1_handle, "__gcov_dump");
+ if (gcov_dump1 == NULL)
+ return fprintf(stderr, "unable to find __gcov_dump in func1.so': %s\n", dlerror());
if (dlclose(f2_handle) != 0)
return fprintf(stderr, "unable to close 'func2.so': %s\n", dlerror());
diff --git a/compiler-rt/test/profile/Posix/gcov-shared-flush.c b/compiler-rt/test/profile/Posix/gcov-shared-flush.c
index 97d44ad5204e..494fb9be761d 100644
--- a/compiler-rt/test/profile/Posix/gcov-shared-flush.c
+++ b/compiler-rt/test/profile/Posix/gcov-shared-flush.c
@@ -7,7 +7,7 @@
// RUN: %clang --coverage -fPIC -shared shared.c -o libfunc.so
// RUN: test -f shared.gcno
-/// Test the case where we exit abruptly after calling __gcov_flush, which means we don't write out the counters at exit.
+/// Test the case where we exit abruptly after calling __gcov_dump, which means we don't write out the counters at exit.
// RUN: %clang -DEXIT_ABRUPTLY -DSHARED_CALL_BEFORE_FLUSH -DSHARED_CALL_AFTER_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t
// RUN: test -f gcov-shared-flush.gcno
@@ -21,7 +21,7 @@
// SHARED: 1: {{[[0-9]+}}:void foo(int n)
-/// Test the case where we exit normally and we have a call to the shared library function before __gcov_flush.
+/// Test the case where we exit normally and we have a call to the shared library function before __gcov_dump.
// RUN: %clang -DSHARED_CALL_BEFORE_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t
// RUN: test -f gcov-shared-flush.gcno
@@ -32,14 +32,15 @@
// BEFORE: -: {{[0-9]+}}:#ifdef SHARED_CALL_BEFORE_FLUSH
// BEFORE-NEXT: 1: {{[0-9]+}}: foo(1);
-// BEFORE: 1: {{[0-9]+}}: __gcov_flush();
+// BEFORE: 1: {{[0-9]+}}: __gcov_dump();
+// BEFORE-NEXT: 1: {{[0-9]+}}: __gcov_reset();
// BEFORE: -: {{[0-9]+}}:#ifdef SHARED_CALL_AFTER_FLUSH
// BEFORE-NEXT: -: {{[0-9]+}}: foo(1);
// BEFORE: 1: {{[0-9]+}}: bar(5);
// SHARED_ONCE: 1: {{[0-9]+}}:void foo(int n)
-// # Test the case where we exit normally and we have a call to the shared library function after __gcov_flush.
+// # Test the case where we exit normally and we have a call to the shared library function after __gcov_dump.
// RUN: %clang -DSHARED_CALL_AFTER_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t
// RUN: test -f gcov-shared-flush.gcno
@@ -50,12 +51,13 @@
// AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_BEFORE_FLUSH
// AFTER-NEXT: -: {{[0-9]+}}: foo(1);
-// AFTER: 1: {{[0-9]+}}: __gcov_flush();
+// AFTER: 1: {{[0-9]+}}: __gcov_dump();
+// AFTER-NEXT: 1: {{[0-9]+}}: __gcov_reset();
// AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_AFTER_FLUSH
// AFTER-NEXT: 1: {{[0-9]+}}: foo(1);
// AFTER: 1: {{[0-9]+}}: bar(5);
-// # Test the case where we exit normally and we have calls to the shared library function before and after __gcov_flush.
+// # Test the case where we exit normally and we have calls to the shared library function before and after __gcov_dump.
// RUN: %clang -DSHARED_CALL_BEFORE_FLUSH -DSHARED_CALL_AFTER_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t
// RUN: test -f gcov-shared-flush.gcno
@@ -66,7 +68,8 @@
// BEFORE_AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_BEFORE_FLUSH
// BEFORE_AFTER-NEXT: 1: {{[0-9]+}}: foo(1);
-// BEFORE_AFTER: 1: {{[0-9]+}}: __gcov_flush();
+// BEFORE_AFTER: 1: {{[0-9]+}}: __gcov_dump();
+// BEFORE_AFTER-NEXT: 1: {{[0-9]+}}: __gcov_reset();
// BEFORE_AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_AFTER_FLUSH
// BEFORE_AFTER-NEXT: 1: {{[0-9]+}}: foo(1);
// BEFORE_AFTER: 1: {{[0-9]+}}: bar(5);
@@ -78,7 +81,8 @@ void foo(int n) {
}
#else
extern void foo(int n);
-extern void __gcov_flush(void);
+extern void __gcov_dump(void);
+extern void __gcov_reset(void);
int bar1 = 0;
int bar2 = 1;
@@ -96,7 +100,8 @@ int main(int argc, char *argv[]) {
#endif
bar(5);
- __gcov_flush();
+ __gcov_dump();
+ __gcov_reset();
bar(5);
#ifdef SHARED_CALL_AFTER_FLUSH
diff --git a/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c b/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c
index 5303e045063e..649538dc2aaf 100644
--- a/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c
+++ b/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c
@@ -10,11 +10,13 @@
// CHECK: -: 0:Runs:1
// CHECK-NEXT: -: 0:Programs:1
-void __gcov_flush(void);
+void __gcov_dump(void);
+void __gcov_reset(void);
int main(void) { // CHECK: 1: [[#@LINE]]:int main(void)
int i = 22; // CHECK-NEXT: 1: [[#@LINE]]:
- __gcov_flush(); // CHECK-NEXT: 1: [[#@LINE]]:
+ __gcov_dump(); // CHECK-NEXT: 1: [[#@LINE]]:
+ __gcov_reset(); // CHECK-NEXT: 1: [[#@LINE]]:
i = 42; // CHECK-NEXT: 1: [[#@LINE]]:
__builtin_trap(); // CHECK-NEXT: 1: [[#@LINE]]:
i = 84; // CHECK-NEXT: 1: [[#@LINE]]:
diff --git a/compiler-rt/test/profile/gcov-dump-and-remove.c b/compiler-rt/test/profile/gcov-dump-and-remove.c
index 1dcf7b5bd5ca..b7f80535aada 100644
--- a/compiler-rt/test/profile/gcov-dump-and-remove.c
+++ b/compiler-rt/test/profile/gcov-dump-and-remove.c
@@ -8,16 +8,19 @@
// RUN: rm -f gcov-dump-and-remove.gcda && %run %t
// RUN: llvm-cov gcov -t gcov-dump-and-remove.gcda | FileCheck %s
-extern void __gcov_flush(void);
+extern void __gcov_dump(void);
+extern void __gcov_reset(void);
extern int remove(const char *); // CHECK: -: [[#@LINE]]:extern int remove
int main(void) { // CHECK-NEXT: #####: [[#@LINE]]:
- __gcov_flush(); // CHECK-NEXT: #####: [[#@LINE]]:
+ __gcov_dump(); // CHECK-NEXT: #####: [[#@LINE]]:
+ __gcov_reset(); // CHECK-NEXT: #####: [[#@LINE]]:
if (remove("gcov-dump-and-remove.gcda") != 0) // CHECK-NEXT: #####: [[#@LINE]]:
return 1; // CHECK-NEXT: #####: [[#@LINE]]: return 1;
// CHECK-NEXT: -: [[#@LINE]]:
- __gcov_flush(); // CHECK-NEXT: #####: [[#@LINE]]:
- __gcov_flush(); // CHECK-NEXT: #####: [[#@LINE]]:
- if (remove("gcov-dump-and-remove.gcda") != 0) // CHECK-NEXT: #####: [[#@LINE]]:
+ __gcov_dump(); // CHECK-NEXT: 1: [[#@LINE]]:
+ __gcov_reset(); // CHECK-NEXT: 1: [[#@LINE]]:
+ __gcov_dump(); // CHECK-NEXT: 1: [[#@LINE]]:
+ if (remove("gcov-dump-and-remove.gcda") != 0) // CHECK-NEXT: 1: [[#@LINE]]:
return 1; // CHECK-NEXT: #####: [[#@LINE]]: return 1;
return 0;
diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index d8a965a90127..cd2ea8d5e4ed 100644
--- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -130,7 +130,6 @@ class GCOVProfiler {
Function *
insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
Function *insertReset(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
- Function *insertFlush(Function *ResetF);
bool AddFlushBeforeForkAndExec();
@@ -909,7 +908,6 @@ bool GCOVProfiler::emitProfileArcs() {
Function *WriteoutF = insertCounterWriteout(CountersBySP);
Function *ResetF = insertReset(CountersBySP);
- Function *FlushF = insertFlush(ResetF);
// 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
@@ -927,14 +925,13 @@ 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)};
- FTy = FunctionType::get(Builder.getVoidTy(), Params, false);
+ auto *PFTy = PointerType::get(FTy, 0);
+ FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy}, false);
// Initialize the environment and register the local writeout, flush and
// reset functions.
FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy);
- Builder.CreateCall(GCOVInit, {WriteoutF, FlushF, ResetF});
+ Builder.CreateCall(GCOVInit, {WriteoutF, ResetF});
Builder.CreateRetVoid();
appendToGlobalCtors(*M, F, 0);
@@ -1266,36 +1263,3 @@ Function *GCOVProfiler::insertReset(
return ResetF;
}
-
-Function *GCOVProfiler::insertFlush(Function *ResetF) {
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
- Function *FlushF = M->getFunction("__llvm_gcov_flush");
- if (!FlushF)
- FlushF = Function::Create(FTy, GlobalValue::InternalLinkage,
- "__llvm_gcov_flush", M);
- FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
- FlushF->addFnAttr(Attribute::NoInline);
- if (Options.NoRedZone)
- FlushF->addFnAttr(Attribute::NoRedZone);
-
- BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF);
-
- // Write out the current counters.
- Function *WriteoutF = M->getFunction("__llvm_gcov_writeout");
- assert(WriteoutF && "Need to create the writeout function first!");
-
- IRBuilder<> Builder(Entry);
- Builder.CreateCall(WriteoutF, {});
- Builder.CreateCall(ResetF, {});
-
- Type *RetTy = FlushF->getReturnType();
- if (RetTy->isVoidTy())
- Builder.CreateRetVoid();
- else if (RetTy->isIntegerTy())
- // Used if __llvm_gcov_flush was implicitly declared.
- Builder.CreateRet(ConstantInt::get(RetTy, 0));
- else
- report_fatal_error("invalid return type for __llvm_gcov_flush");
-
- return FlushF;
-}
More information about the llvm-commits
mailing list