From 18764716861243c58a711a92190624dc2f6aafc9 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Tue, 19 Mar 2013 21:03:22 +0000 Subject: [PATCH] Register the GCOV writeout functions so that they're emitted serially. 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177437 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Instrumentation/GCOVProfiling.cpp | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 7fa4cfb2d13..093984cac69 100644 --- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -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); -- 2.34.1