diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -125,6 +125,7 @@ function_ref GetBPI, function_ref GetTLI); + Function *createInternalFunction(FunctionType *FTy, StringRef Name); void emitGlobalConstructor( SmallVectorImpl> &CountersBySP); @@ -1023,22 +1024,28 @@ return true; } +Function *GCOVProfiler::createInternalFunction(FunctionType *FTy, + StringRef Name) { + Function *F = Function::createWithDefaultAttr( + FTy, GlobalValue::InternalLinkage, 0, Name, M); + F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + F->addFnAttr(Attribute::NoUnwind); + if (Options.NoRedZone) + F->addFnAttr(Attribute::NoRedZone); + return F; +} + void GCOVProfiler::emitGlobalConstructor( SmallVectorImpl> &CountersBySP) { Function *WriteoutF = insertCounterWriteout(CountersBySP); Function *ResetF = insertReset(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 + // be executed at exit and the "__llvm_gcov_reset" 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); - F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - F->setLinkage(GlobalValue::InternalLinkage); + Function *F = createInternalFunction(FTy, "__llvm_gcov_init"); F->addFnAttr(Attribute::NoInline); - if (Options.NoRedZone) - F->addFnAttr(Attribute::NoRedZone); BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); IRBuilder<> Builder(BB); @@ -1113,12 +1120,8 @@ FunctionType *WriteoutFTy = FunctionType::get(Type::getVoidTy(*Ctx), false); Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); if (!WriteoutF) - WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage, - "__llvm_gcov_writeout", M); - WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + WriteoutF = createInternalFunction(WriteoutFTy, "__llvm_gcov_writeout"); WriteoutF->addFnAttr(Attribute::NoInline); - if (Options.NoRedZone) - WriteoutF->addFnAttr(Attribute::NoRedZone); BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", WriteoutF); IRBuilder<> Builder(BB); @@ -1363,12 +1366,8 @@ 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); - ResetF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + ResetF = createInternalFunction(FTy, "__llvm_gcov_reset"); ResetF->addFnAttr(Attribute::NoInline); - if (Options.NoRedZone) - ResetF->addFnAttr(Attribute::NoRedZone); BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", ResetF); IRBuilder<> Builder(Entry); diff --git a/llvm/test/Transforms/GCOVProfiling/function-numbering.ll b/llvm/test/Transforms/GCOVProfiling/function-numbering.ll --- a/llvm/test/Transforms/GCOVProfiling/function-numbering.ll +++ b/llvm/test/Transforms/GCOVProfiling/function-numbering.ll @@ -20,7 +20,7 @@ ; GCDA-SAME: { i32 0, ; GCDA-SAME: { i32 1, ; -; GCDA-LABEL: define internal void @__llvm_gcov_writeout() {{.*}} { +; GCDA-LABEL: define internal void @__llvm_gcov_writeout() unnamed_addr #[[#ATTR:]] { ; GCDA-NEXT: entry: ; GCDA-NEXT: br label %[[FILE_LOOP_HEADER:.*]] ; @@ -94,6 +94,8 @@ ret void, !dbg !13 } +; GCDA: attributes #[[#ATTR]] = { noinline nounwind } + !llvm.gcov = !{!14} !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !10} diff --git a/llvm/test/Transforms/GCOVProfiling/module-flags.ll b/llvm/test/Transforms/GCOVProfiling/module-flags.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GCOVProfiling/module-flags.ll @@ -0,0 +1,34 @@ +; RUN: mkdir -p %t && cd %t +; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +define dso_local void @empty() !dbg !5 { +entry: + ret void, !dbg !8 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !9, !10} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "a.c", directory: "") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = distinct !DISubprogram(name: "empty", scope: !1, file: !1, line: 1, type: !6, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!6 = !DISubroutineType(types: !7) +!7 = !{null} +!8 = !DILocation(line: 2, column: 1, scope: !5) + +;; Due to -fasynchronous-unwind-tables. +!9 = !{i32 7, !"uwtable", i32 1} + +;; Due to -fno-omit-frame-pointer. +!10 = !{i32 7, !"frame-pointer", i32 2} + +;; Infer uwtable and "frame-pointer" from the module flags. +; CHECK: define internal void @__llvm_gcov_writeout() unnamed_addr #[[#ATTR:]] +; CHECK: define internal void @__llvm_gcov_reset() unnamed_addr #[[#ATTR]] +; CHECK: define internal void @__llvm_gcov_init() unnamed_addr #[[#ATTR]] +; CHECK: attributes #[[#ATTR]] = { noinline nounwind uwtable "frame-pointer"="all" }