Register the GCOV writeout functions so that they're emitted serially.
authorBill Wendling <isanbard@gmail.com>
Tue, 19 Mar 2013 21:03:22 +0000 (21:03 +0000)
committerBill Wendling <isanbard@gmail.com>
Tue, 19 Mar 2013 21:03:22 +0000 (21:03 +0000)
We don't want to write out >1000 files at the same time. That could make things
prohibitively expensive. Instead, register the "writeout" function so that it's
emitted serially.
<rdar://problem/12439551>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177437 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Instrumentation/GCOVProfiling.cpp

index 7fa4cfb2d13093a2c75c0846df61720a92849ff1..093984cac69a4f8b7d47f057dd3e56edfea2c08b 100644 (file)
@@ -101,6 +101,7 @@ namespace {
     Constant *getIncrementIndirectCounterFunc();
     Constant *getEmitFunctionFunc();
     Constant *getEmitArcsFunc();
+    Constant *getDeleteWriteoutFunctionListFunc();
     Constant *getDeleteFlushFunctionListFunc();
     Constant *getEndFileFunc();
 
@@ -550,8 +551,8 @@ bool GCOVProfiler::emitProfileArcs() {
     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
-    //  when "__gcov_flush" is called.
+    // be executed at exit and the "__llvm_gcov_flush" function to be executed
+    // when "__gcov_flush" is called.
     FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
     Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
                                    "__llvm_gcov_init", M);
@@ -564,21 +565,36 @@ bool GCOVProfiler::emitProfileArcs() {
     BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F);
     IRBuilder<> Builder(BB);
 
-    FTy = FunctionType::get(Builder.getInt32Ty(),
-                            PointerType::get(FTy, 0), false);
-    Constant *AtExitFn = M->getOrInsertFunction("atexit", FTy);
-    Builder.CreateCall(AtExitFn, WriteoutF);
-
-    // Register the local flush function.
     FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
     FTy = FunctionType::get(Builder.getVoidTy(),
                             PointerType::get(FTy, 0), false);
+
+    // Register the local writeout function.
+    Constant *RegWriteout =
+      M->getOrInsertFunction("llvm_register_writeout_function", FTy);
+    Builder.CreateCall(RegWriteout, WriteoutF);
+
+    // Register the local flush function.
     Constant *RegFlush =
       M->getOrInsertFunction("llvm_register_flush_function", FTy);
     Builder.CreateCall(RegFlush, FlushF);
 
-    // Make sure that all the flush function list is deleted.
-    Builder.CreateCall(AtExitFn, getDeleteFlushFunctionListFunc());
+    if (M->getFunction("main")) {
+      Constant *AtExitFn = M->getOrInsertFunction("atexit", FTy);
+
+      // In the module that has the 'main' function, make sure that the flush
+      // and writeout function lists are deleted. Also make sure that the
+      // writeout function list is deleted.
+      Builder.CreateCall(AtExitFn, getDeleteWriteoutFunctionListFunc());
+      Builder.CreateCall(AtExitFn, getDeleteFlushFunctionListFunc());
+
+      // Make sure we write out all files when exiting. Note: This is called
+      // first from atexit().
+      FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
+      Builder.CreateCall(AtExitFn,
+                         M->getOrInsertFunction("__llvm_writeout_files", FTy));
+    }
+
     Builder.CreateRetVoid();
 
     appendToGlobalCtors(*M, F, 0);
@@ -677,6 +693,11 @@ Constant *GCOVProfiler::getEmitArcsFunc() {
   return M->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
 }
 
+Constant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() {
+  FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
+  return M->getOrInsertFunction("llvm_delete_writeout_function_list", FTy);
+}
+
 Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
   FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
   return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy);