diff --git a/llvm/test/tools/llvm-profgen/inline-noprobe.test b/llvm/test/tools/llvm-profgen/inline-noprobe.test --- a/llvm/test/tools/llvm-profgen/inline-noprobe.test +++ b/llvm/test/tools/llvm-profgen/inline-noprobe.test @@ -4,6 +4,8 @@ ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-RAW-PROFILE ; RUN: llvm-profgen --format=text --unsymbolized-profile=%t --binary=%S/Inputs/inline-noprobe.perfbin --output=%t1 ; RUN: FileCheck %s --input-file %t1 --check-prefix=CHECK +; RUN: llvm-profgen --format=text --unsymbolized-profile=%t --binary=%S/Inputs/inline-noprobe.perfbin --output=%t1 --populate-zero-for-all-funcs +; RUN: FileCheck %s --input-file %t1 --check-prefix=CHECK ; RUN: llvm-profgen --format=text --use-dwarf-correlation --perfscript=%S/Inputs/inline-noprobe.perfscript --binary=%S/Inputs/inline-noprobe.perfbin --output=%t ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK @@ -20,6 +22,21 @@ CHECK: 3.2: bar:21 CHECK: 1: 21 +CHECK-ALL-ZERO: bar:0:0 +CHECK-ALL-ZERO: 1: 0 +CHECK-ALL-ZERO: 5: 0 +CHECK-ALL-ZERO: foo:0:0 +CHECK-ALL-ZERO: 0: 0 +CHECK-ALL-ZERO: 2.1: 0 +CHECK-ALL-ZERO: 3: 0 +CHECK-ALL-ZERO: 3.2: 0 +CHECK-ALL-ZERO: 4: 0 +CHECK-ALL-ZERO: 3.1: bar:0 +CHECK-ALL-ZERO: 1: 0 +CHECK-ALL-ZERO: 3.2: bar:0 +CHECK-ALL-ZERO: 1: 0 +CHECK-ALL-ZERO: 7: 0 + CHECK-RAW-PROFILE: 3 CHECK-RAW-PROFILE-NEXT: 650-691:21 CHECK-RAW-PROFILE-NEXT: 669-677:20 diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -36,6 +36,11 @@ "populate-profile-symbol-list", cl::init(false), cl::Hidden, cl::desc("Populate profile symbol list (only meaningful for -extbinary)")); +static cl::opt FillZeroForAllFuncs( + "fill-zero-for-all-funcs", cl::init(false), cl::Hidden, + cl::desc("Attribute all functions's range with zero count " + "even it's not hit by any samples.")); + static cl::opt RecursionCompression( "compress-recursion", cl::desc("Compressing recursion by deduplicating adjacent frame " @@ -347,14 +352,22 @@ RangeSample ProfileGenerator::preprocessRangeCounter(const RangeSample &RangeCounter) { RangeSample Ranges(RangeCounter.begin(), RangeCounter.end()); - // For each range, we search for all ranges of the function it belongs to and - // initialize it with zero count, so it remains zero if doesn't hit any - // samples. This is to be consistent with compiler that interpret zero count - // as unexecuted(cold). - for (auto I : RangeCounter) { - uint64_t StartOffset = I.first.first; - for (const auto &Range : Binary->getRangesForOffset(StartOffset)) - Ranges[{Range.first, Range.second - 1}] += 0; + if (FillZeroForAllFuncs) { + for (auto &FuncI : Binary->getAllBinaryFunctions()) { + for (auto &R : FuncI.second.Ranges) { + Ranges[{R.first, R.second}] += 0; + } + } + } else { + // For each range, we search for all ranges of the function it belongs to + // and initialize it with zero count, so it remains zero if doesn't hit any + // samples. This is to be consistent with compiler that interpret zero count + // as unexecuted(cold). + for (auto I : RangeCounter) { + uint64_t StartOffset = I.first.first; + for (const auto &Range : Binary->getRangesForOffset(StartOffset)) + Ranges[{Range.first, Range.second - 1}] += 0; + } } RangeSample DisjointRanges; findDisjointRanges(DisjointRanges, Ranges); @@ -643,7 +656,7 @@ CSProfMergeColdContext = false; } - // Trim and merge cold context profile using cold threshold above. + // Trim and merge cold context profile using cold threshold above. if (CSProfTrimColdContext || CSProfMergeColdContext) { SampleContextTrimmer(ProfileMap) .trimAndMergeColdContextProfiles( diff --git a/llvm/tools/llvm-profgen/ProfiledBinary.h b/llvm/tools/llvm-profgen/ProfiledBinary.h --- a/llvm/tools/llvm-profgen/ProfiledBinary.h +++ b/llvm/tools/llvm-profgen/ProfiledBinary.h @@ -384,6 +384,11 @@ return FRange->Func->Ranges; } + const std::unordered_map & + getAllBinaryFunctions() { + return BinaryFunctions; + } + uint32_t getFuncSizeForContext(SampleContext &Context) { return FuncSizeTracker.getFuncSizeForContext(Context); }