From: Arthur Eubanks Date: Fri, 6 Aug 2021 04:18:53 +0000 (-0700) Subject: [GCov] Emit memset instead of stores in __llvm_gcov_reset X-Git-Tag: upstream/15.0.7~34515 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a1b21ed3fb4a9f4b85d8fa29f95c31b737e0840f;p=platform%2Fupstream%2Fllvm.git [GCov] Emit memset instead of stores in __llvm_gcov_reset For a very large module, __llvm_gcov_reset can become very large. __llvm_gcov_reset previously emitted stores to a bunch of globals in one huge basic block. MemCpyOpt would turn many of these stores into memsets, and updating MemorySSA would be extremely slow. Verified that this makes the compile time of certain files go down drastically (20min -> 5min). Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D107538 --- diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index c99f2e6..d029a0ca 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -1373,12 +1373,16 @@ Function *GCOVProfiler::insertReset( BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", ResetF); IRBuilder<> Builder(Entry); + LLVMContext &C = Entry->getContext(); // Zero out the counters. for (const auto &I : CountersBySP) { GlobalVariable *GV = I.first; - Constant *Null = Constant::getNullValue(GV->getValueType()); - Builder.CreateStore(Null, GV); + auto *GVTy = cast(GV->getValueType()); + Builder.CreateMemSet(GV, Constant::getNullValue(Type::getInt8Ty(C)), + GVTy->getNumElements() * + GVTy->getElementType()->getScalarSizeInBits() / 8, + GV->getAlign()); } Type *RetTy = ResetF->getReturnType(); diff --git a/llvm/test/Transforms/GCOVProfiling/reset.ll b/llvm/test/Transforms/GCOVProfiling/reset.ll new file mode 100644 index 0000000..b8869ea --- /dev/null +++ b/llvm/test/Transforms/GCOVProfiling/reset.ll @@ -0,0 +1,37 @@ +; RUN: mkdir -p %t && cd %t +; RUN: opt < %s -S -passes=insert-gcov-profiling | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +define void @foo() !dbg !8 { +entry: + ret void, !dbg !12 +} + +define void @bar() !dbg !13 { +entry: + ret void, !dbg !14 +} + +; CHECK: define internal void @__llvm_gcov_reset() +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* bitcast ([1 x i64]* @__llvm_gcov_ctr to i8*), i8 0, i64 8, i1 false) +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* bitcast ([1 x i64]* @__llvm_gcov_ctr.1 to i8*), i8 0, i64 8, i1 false) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "/tmp/a.c", directory: "/tmp") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"uwtable", i32 1} +!8 = distinct !DISubprogram(name: "foo", scope: !9, file: !9, line: 1, type: !10, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!9 = !DIFile(filename: "/tmp/a.c", directory: "") +!10 = !DISubroutineType(types: !11) +!11 = !{null} +!12 = !DILocation(line: 1, column: 13, scope: !8) +!13 = distinct !DISubprogram(name: "bar", scope: !9, file: !9, line: 2, type: !10, scopeLine: 2, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!14 = !DILocation(line: 2, column: 13, scope: !13)