[clang] 5809a32 - [gcov] Add __gcov_dump/__gcov_reset and delete __gcov_flush

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Sat Jul 18 15:08:26 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 cfe-commits mailing list